diff options
Diffstat (limited to 'tcosmonitor/extensions')
22 files changed, 4771 insertions, 0 deletions
diff --git a/tcosmonitor/extensions/Makefile b/tcosmonitor/extensions/Makefile new file mode 100644 index 0000000..e3820c9 --- /dev/null +++ b/tcosmonitor/extensions/Makefile @@ -0,0 +1,15 @@ +all: + #none + +include ../../common.mk + + +clean: + rm -f *~ *.pyc + +install: + install -d $(DESTDIR)/$(PREFIX)/share/$(PACKAGE)/extensions + @for ext in $(shell ls *.py |grep -v template); do \ + echo "install -m 644 $$ext $(DESTDIR)/$(PREFIX)/share/$(PACKAGE)/extensions" ; \ + install -m 644 $$ext $(DESTDIR)/$(PREFIX)/share/$(PACKAGE)/extensions ; \ + done diff --git a/tcosmonitor/extensions/__init__.py b/tcosmonitor/extensions/__init__.py new file mode 100644 index 0000000..6285c3e --- /dev/null +++ b/tcosmonitor/extensions/__init__.py @@ -0,0 +1,47 @@ +# -*- coding: UTF-8 -*- +# TcosMonitor version __VERSION__ +# +# Copyright (c) 2006-2011 Mario Izquierdo <mariodebian@gmail.com> +# +# This package is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# +# This package is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +import glob as __glob__ +import os as __os__ +import sys as __sys__ + +def __load__(): + """ + read contents of extensions dir and put in __all__ list + """ + _ext_dir=__os__.path.dirname( __file__ ) + _ext=[] + for file_ in __glob__.glob(_ext_dir+"/*.py"): + if file_ == "__init__.py": + continue + _ext_name = __os__.path.basename(file_).split('.py')[0] + if _ext_name == "__init__": + continue + _ext.append( _ext_name ) + try: + if __sys__.version_info[0:3] < (2, 5, 0): + __import__('tcosmonitor.extensions.' + _ext_name, globals(), locals(), ['extensions'] ) + else: + __import__('tcosmonitor.extensions.' + _ext_name, fromlist = ['extensions'] ) + except Exception, err: + print ("Exception importing extension='%s', err='%s'"%(_ext_name, err)) + return _ext + +__all__=__load__() diff --git a/tcosmonitor/extensions/appsmsg.py b/tcosmonitor/extensions/appsmsg.py new file mode 100644 index 0000000..88e34bd --- /dev/null +++ b/tcosmonitor/extensions/appsmsg.py @@ -0,0 +1,373 @@ +# -*- coding: UTF-8 -*- +# TcosMonitor version __VERSION__ +# +# Copyright (c) 2006-2011 Mario Izquierdo <mariodebian@gmail.com> +# +# This package is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# +# This package is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +""" template extension """ + +from gettext import gettext as _ + +from tcosmonitor import shared +from tcosmonitor.TcosExtensions import TcosExtension + +import gtk +from time import time +import os +import sys +import glob + +def print_debug(txt): + if shared.debug: + print >> sys.stderr, "%s::%s" % (__name__, txt) + #print("%s::%s" % (__name__, txt), file=sys.stderr) + +def crono(start, txt): + print_debug ("crono(), %s get %f seconds" %(txt, (time() - start)) ) + return + +class AppsAndMsgs(TcosExtension): + def register(self): + self.init_ask() + self.main.classview.class_external_exe=self.exe_app_external + self.main.actions.button_action_exe=self.exe_app_all + self.main.actions.button_action_text=self.send_msg_all + + self.main.menus.register_simple( _("Exec app on user display") , "menu_exec.png", 1, self.exe_app, "exe") + self.main.menus.register_simple( _("Send a text message to user") , "menu_msg.png", 1, self.send_msg, "text") + + self.main.menus.register_all( _("Exec same app in all connected users") , "menu_exec.png", 1, self.exe_app_all, "exe") + self.main.menus.register_all( _("Send a text message to all connected users") , "menu_msg.png", 1, self.send_msg_all, "text") + +############################################################################## + def askfor(self, mode="mess", msg="", users=None, users_txt=None): + if users == None or users_txt == None: + users=[] + self.ask_usernames=[] + if len(users) == 0 or users[0] == shared.NO_LOGIN_MSG: + shared.error_msg( _("Clients not connected") ) + return + else: + self.ask_usernames=users + + #users_txt="" + #counter=1 + #for user in self.ask_usernames: + # users_txt+="%s, " %(user) + # print_debug("askfor() counter=%s" %(counter) ) + # if counter % 4 == 0: + # users_txt+="\n" + # counter=int(counter+1) + + #if users_txt[-2:] == "\n": users_txt=users_txt[:-2] + #if users_txt[-2:] == ", ": users_txt=users_txt[:-2] + + if mode == "exec": + # enable drag & drop + self.main.ask_fixed.show() + self.main.ask_dragdrop.show() + self.main.image_entry.show() + self.main.image_entry.set_from_stock(gtk.STOCK_DIALOG_QUESTION, 4) + self.main.ask_label.set_markup( _("<b>Exec app in user(s) screen(s)\nor open web address to:</b>\n%s" ) %( users_txt ) ) + elif mode == "mess": + self.main.ask_label.set_markup( _("<b>Send a message to:</b>\n%s" ) %( users_txt ) ) + elif mode == "any": + self.main.ask_label.set_markup( msg ) + self.ask_mode=mode + self.main.ask.show() + return True + + + def on_ask_exec_click(self, widget): + app=self.main.ask_entry.get_text() + if app != "": + self.exe_app_in_client_display(app) + return + + + def on_ask_cancel_click(self, widget): + self.main.ask.hide() + self.main.ask_entry.set_text("") + # disable drag & drop + self.main.ask_fixed.hide() + self.main.image_entry.hide() + self.main.ask_dragdrop.hide() + return +############################################################################## + + def exe_app_external(self, filename=None, txt=None): + if self.main.classview.ismultiple() or txt != None: + if not self.get_all_clients(): + return + elif not self.get_client(): + return + + if len(self.connected_users) == 0 or self.connected_users[0] == shared.NO_LOGIN_MSG: + shared.error_msg ( _("Can't exec application, user is not logged") ) + return + #print_debug("user=%s data=%s" %(self.connected_users, data) + app="" + self.ask_usernames=self.connected_users + self.ask_mode="exec" + + if txt != None: + app="x-www-browser %s" %txt + self.exe_app_in_client_display(app) + return + + print_debug("open_file() reading data from \"%s\"..." \ + %(filename) ) + try: + fd=file(filename, 'r') + data=fd.readlines() + fd.close() + except Exception, err: + shared.error_msg( _("%s is not a valid application") %(os.path.basename(filename)) ) + return + + for line in data: + if line != '\n': + if line.startswith("Exec="): + line=line.replace('\n', '') + action, app=line.split("=",1) + app=app.replace("%U","").replace("%u","").replace("%F","").replace("%f","").replace("%c","").replace("%i","").replace("%m","") + + if len(app) <1: + shared.error_msg( _("%s is not a valid application") %(os.path.basename(filename)) ) + + if app != "": + self.exe_app_in_client_display(app) + return + + + def exe_app(self, w, ip): + if not self.get_client(): + return + if len(self.connected_users) == 0 or self.connected_users[0] == shared.NO_LOGIN_MSG: + shared.error_msg ( _("Can't exec application, user is not logged") ) + return + self.askfor(mode="exec", users=self.connected_users, users_txt=self.connected_users_txt) + + + def send_msg(self, w, ip): + if not self.get_client(): + return + if len(self.connected_users) == 0 or self.connected_users[0] == shared.NO_LOGIN_MSG: + shared.error_msg ( _("Can't send message, user is not logged") ) + return + self.askfor(mode="mess", users=self.connected_users, users_txt=self.connected_users_txt) + + def exe_app_all(self, *args): + if not self.get_all_clients(): + return + self.askfor(mode="exec", users=self.connected_users, users_txt=self.connected_users_txt) + + def send_msg_all(self, *args): + if not self.get_all_clients(): + return + self.askfor(mode="mess", users=self.connected_users, users_txt=self.connected_users_txt) + + +####################### INIT ############################################ + def init_ask(self): + self.main.ask_ip=None + + self.ui = gtk.Builder() + self.ui.set_translation_domain(shared.PACKAGE) + self.ui.add_from_file(shared.GLADE_DIR + 'tcosmonitor-askwindow.ui') + + self.main.ask = self.ui.get_object('askwindow') + self.main.ask.connect('delete-event', self.askwindow_close ) + self.main.ask.set_icon_from_file(shared.IMG_DIR +'tcos-icon-32x32.png') + + + self.main.ask_label = self.ui.get_object('txt_asklabel') + ## arrastrar y soltar + self.main.ask_fixed = self.ui.get_object('ask_fixed') + self.main.ask_dragdrop = self.ui.get_object('label99') + self.main.image_entry = self.ui.get_object('image_askentry') + self.main.image_entry.drag_dest_set( gtk.DEST_DEFAULT_ALL, [( 'text/uri-list', 0, 2 ), ], gtk.gdk.ACTION_DEFAULT | gtk.gdk.ACTION_COPY) + self.main.image_entry.connect( 'drag_data_received', self.on_drag_data_received) + self.main.ask_fixed.hide() + self.main.image_entry.hide() + self.main.ask_dragdrop.hide() + ## fin arrastrar y soltar + self.liststore = gtk.ListStore(str) + for s in shared.appslist: + self.liststore.append([s]) + + self.main.ask_entry = self.ui.get_object('txt_askentry') + self.main.ask_completion = gtk.EntryCompletion() + self.main.ask_completion.set_model(self.liststore) + self.main.ask_entry.set_completion(self.main.ask_completion) + self.main.ask_completion.set_text_column(0) + + self.main.ask_completion.connect('match-selected', self.match_cb) + self.main.ask_entry.connect('activate', self.activate_cb) + + self.main.ask_cancel = self.ui.get_object('ask_cancelbutton') + self.main.ask_exec = self.ui.get_object('ask_exebutton') + + # buttons signals + self.main.ask_exec.connect('clicked', self.on_ask_exec_click) + self.main.ask_cancel.connect('clicked', self.on_ask_cancel_click) + + + def askwindow_close(self, widget, event): + print_debug ( "askwindow_close() closing ask window" ) + self.main.ask.hide() + return True + + def on_drag_data_received( self, widget, context, x, y, selection, targetType, dtime): + files = selection.data.split('\n', 1) + start1=time() + print_debug("on_drag_data_received() files=%s dtime=%s"%(files, dtime)) + for f in files: + if f: + desktop = f.strip().replace('%20', ' ') + break + + if desktop.startswith('file:///') and desktop.lower().endswith('.desktop') and os.path.isfile(desktop[7:]): + print_debug("open_file() reading data from \"%s\"..." \ + %(desktop[7:]) ) + fd=file(desktop[7:], 'r') + data=fd.readlines() + fd.close() + + # try to load gnome theme with gconf + mytheme=[] + theme=self.main.common.get_icon_theme() + print_debug("on_drag_data_received() gconf theme=%s"%theme) + + str_image="" + files=[] + + if theme and os.path.isdir("/usr/share/icons/%s"%theme): + files+=glob.glob("/usr/share/icons/%s/48x48/*.png"%(theme)) + + files+=glob.glob("/usr/share/icons/hicolor/48x48/*/*.png") + \ + glob.glob("/usr/share/icons/gnome/48x48/*/*.png") + \ + glob.glob("/usr/share/pixmaps/*png") +\ + glob.glob("/usr/share/pixmaps/*xpm") + + for line in data: + if line != '\n': + if line.startswith("Exec="): + line=line.replace('\n', '') + action, str_exec=line.split("=",1) + str_exec=str_exec.replace("%U","").replace("%u","").replace("%F","").replace("%f","").replace("%c","").replace("%i","").replace("%m","") + elif line.startswith("Icon="): + line=line.replace('\n', '') + action, image_name=line.split("=",1) + if not os.path.isfile(image_name): + start2=time() + for f in files: + if image_name in f or image_name.replace('_', '-') in f: + str_image=f + crono(start2, "on_drag_data_received() ICON FOUND AT %s"%f ) + break + else: + str_image=image_name + + if len(str_exec) <1: + shared.error_msg( _("%s is not application") %(os.path.basename(desktop[7:])) ) + else: + if len(str_image) <1: + print_debug("on_drag_data_received() image '%s' not found"%image_name) + self.main.image_entry.set_from_stock(gtk.STOCK_DIALOG_QUESTION, 4) + else: + self.main.image_entry.set_from_file(str_image) + self.main.ask_entry.set_text(str_exec) + else: + shared.error_msg( _("%s is not application") %(os.path.basename(desktop[7:])) ) + crono(start1, "on_drag_data_received() end" ) + return True + + def match_cb(self, completion, model, iter): + print_debug ( "match_cb() " ) + print_debug( "%s was selected" %(model[iter][0]) ) + self.exe_app_in_client_display(model[iter][0]) + return + + + def activate_cb(self, entry): + text = self.main.ask_entry.get_text() + print_debug ( "activate_cb() text=%s" %(text) ) + + # append to liststore + if text: + if text not in [row[0] for row in self.liststore]: + self.liststore.append([text]) + #self.main.ask_entry.set_text('') + + # exe app + self.exe_app_in_client_display(text) + return + + def exe_app_in_client_display(self, arg): + usernames=self.ask_usernames + newusernames=[] + print_debug("exe_app_in_client_display() usernames=%s" %usernames) + + if arg.startswith('rm ') or arg.find(" rm ") != -1 \ + or arg.startswith('mv ') or arg.find(" mv ") != -1 \ + or arg.startswith('cp ') or arg.find(" cp ") != -1: + arg="" + + #if self.ask_mode == "mess": + # arg=arg.replace("'", "´") + if self.ask_mode == "exec": + if arg.startswith('http://') or arg.startswith('https://') or arg.startswith('ftp://'): + arg="xdg-open %s" %arg + + for user in usernames: + if user.find(":") != -1: + # we have a standalone user... + usern, ip = user.split(":") + print_debug("exe_app_in_client_display() STANDALONE username=%s ip=%s" %(usern, ip)) + self.main.xmlrpc.newhost(ip) + self.main.xmlrpc.DBus(self.ask_mode, arg) + else: + newusernames.append(user) + + # we have a thin client user + if self.ask_mode == "exec": + result = self.main.dbus_action.do_exec( newusernames , arg ) + if not result: + shared.error_msg ( _("Error while exec remote app:\nReason: %s") %( self.main.dbus_action.get_error_msg() ) ) + else: + self.main.ask.hide() + self.main.ask_entry.set_text("") + elif self.ask_mode == "mess": + result = self.main.dbus_action.do_message( newusernames , arg) + if not result: + shared.error_msg ( _("Error while send message:\nReason: %s") %( self.main.dbus_action.get_error_msg() ) ) + self.main.ask_dragdrop.hide() + self.main.ask_fixed.hide() + self.main.image_entry.hide() + self.main.ask.hide() + self.main.ask_entry.set_text("") + dbus_action=None + self.ask_mode=None + return + +__extclass__=AppsAndMsgs + + + + + + diff --git a/tcosmonitor/extensions/audiortp.py b/tcosmonitor/extensions/audiortp.py new file mode 100644 index 0000000..3914ae3 --- /dev/null +++ b/tcosmonitor/extensions/audiortp.py @@ -0,0 +1,542 @@ +# -*- coding: UTF-8 -*- +# TcosMonitor version __VERSION__ +# +# Copyright (c) 2006-2011 Mario Izquierdo <mariodebian@gmail.com> +# +# This package is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# +# This package is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +""" template extension """ + +from gettext import gettext as _ +import gtk +import sys + +from tcosmonitor import shared +from tcosmonitor.TcosExtensions import TcosExtension +COL_N, COL_ACTIVE,COL_B,COL_BOOL= range(4) + +def print_debug(txt): + if shared.debug: + print >> sys.stderr, "%s::%s" % (__name__, txt) + #print("%s::%s" % (__name__, txt), file=sys.stderr) + + +class AudioRTP(TcosExtension): + def register(self): + self.rtp_count={} + self.rtp_control_count={} + self.control_list=False + self.init_chat() + self.main.actions.button_action_audio=self.rtp_all + self.main.actions.button_action_chat=self.rtp_chat + self.main.actions.button_action_list=self.control_chat + + self.main.menus.register_all( _("Send audio conference") , "menu_rtp.png", 2, self.rtp_all, "conference") + self.main.menus.register_all( _("Audio chat conference") , "menu_chat.png", 2, self.rtp_chat, "conference") + self.main.menus.register_all( _("Audio chat list") , "menu_list.png", 2, self.control_chat, "conference") + self.main.menus.register_simple( _("Send audio conference (from this host)") , "menu_rtp.png", 2, self.rtp_simple, "conference") + + + def init_chat(self): + print_debug ("init chat control") + self.selected_emission=None + + self.model=gtk.ListStore(str, gtk.gdk.Pixbuf, str, 'gboolean') + + self.ui = gtk.Builder() + self.ui.set_translation_domain(shared.PACKAGE) + + self.ui.add_from_file(shared.GLADE_DIR + 'tcosmonitor-chatwindow.ui') + + self.main.chatwindow=self.ui.get_object('chatwindow') + self.main.chatwindow.connect('delete-event', self.chat_exit ) + + self.main.chatlist = self.ui.get_object('chatlist') + self.main.chatlist.set_model (self.model) + + cell1 = gtk.CellRendererText () + column1 = gtk.TreeViewColumn (_("Emission"), cell1, text = COL_N) + column1.set_resizable (True) + column1.set_sort_column_id(COL_N) + self.main.chatlist.append_column (column1) + + cell2 = gtk.CellRendererPixbuf() + column2 = gtk.TreeViewColumn (_("State"), cell2, pixbuf = COL_ACTIVE) + self.main.chatlist.append_column (column2) + + cell3 = gtk.CellRendererText () + column3 = gtk.TreeViewColumn (_("Channel"), cell3, text = COL_B) + column3.set_resizable (True) + column3.set_sort_column_id(COL_B) + self.main.chatlist.append_column (column3) + + self.table_file = self.main.chatlist.get_selection() + self.table_file.connect("changed", self.on_chat_list_change) + + self.main.chat_button_disconnect=self.ui.get_object('button_chat_disconnect') + self.main.chat_button_disconnect.connect('clicked', self.chat_disconnect) + + self.main.chat_button_connect=self.ui.get_object('button_chat_connect') + self.main.chat_button_connect.connect('clicked', self.chat_connect) + + self.main.chat_button_exit=self.ui.get_object('button_exit') + self.main.chat_button_exit.connect('clicked', self.chat_exit) + + self.main.chat_button_disconnect.set_sensitive(False) + self.main.chat_button_connect.set_sensitive(False) + + self.main.chatwindow.hide() + + def control_chat(self, *args): + #if len(self.rtp_count) < 1: + # shared.info_msg( _("No active chats to manage") ) + # return + + self.populate_data(self.rtp_count) + self.main.chatwindow.show() + self.control_list=True + + def populate_data(self, data): + self.image_noactive = gtk.gdk.pixbuf_new_from_file(shared.IMG_DIR + 'no.png') + self.image_active = gtk.gdk.pixbuf_new_from_file(shared.IMG_DIR + 'ok.png') + + for item in data: + if data[item] not in self.rtp_control_count.keys(): + continue + self.new_line=True + model=self.main.chatlist.get_model() + model.foreach(self.line_exists, data[item]) + + if self.new_line: + self.iter = self.model.append (None) + name="Chat %s" %item + self.model.set_value (self.iter, COL_N, name ) + self.model.set_value (self.iter, COL_B, data[item] ) + if len(self.rtp_control_count[data[item]]) < 1: + self.model.set_value (self.iter, COL_ACTIVE, self.image_noactive ) + self.model.set_value (self.iter, COL_BOOL, False ) + + else: + self.model.set_value (self.iter, COL_ACTIVE, self.image_active ) + self.model.set_value (self.iter, COL_BOOL, True ) + + def control_buttons(self, active): + if active: + self.main.chat_button_disconnect.set_sensitive(True) + self.main.chat_button_connect.set_sensitive(False) + else: + self.main.chat_button_disconnect.set_sensitive(False) + self.main.chat_button_connect.set_sensitive(True) + + def on_chat_list_change (self, data): + (model, iter) = self.main.chatlist.get_selection().get_selected() + if not iter: + self.control_buttons(False) + return + self.selected_num=model.get_value(iter,0) + self.selected_channel=model.get_value(iter, 2) + self.connected_rtp=model.get_value(iter, 3) + print_debug("selected_num=%s selected_channel=%s connected=%s" %(self.selected_num, self.selected_channel, self.connected_rtp)) + if self.connected_rtp: + self.control_buttons(True) + else: + self.control_buttons(False) + + def chat_disconnect(self, *args): + (model, iter) = self.main.chatlist.get_selection().get_selected() + if not iter: + self.control_buttons(False) + return + self.selected_channel=model.get_value(iter, 2) + self.main.common.exe_cmd("pactl unload-module %s" %self.rtp_control_count[self.selected_channel][0]) + self.main.common.exe_cmd("pactl unload-module %s" %self.rtp_control_count[self.selected_channel][1]) + self.rtp_control_count[self.selected_channel]=[] + print_debug("chat_connects %s" %self.rtp_control_count) + model.foreach(self.line_changer, [self.selected_channel, self.image_noactive, False]) + self.main.chat_button_disconnect.set_sensitive(False) + self.main.chat_button_connect.set_sensitive(True) + return True + + def chat_connect(self, *args): + (model, iter) = self.main.chatlist.get_selection().get_selected() + if not iter: + self.control_buttons(False) + return + self.selected_channel=model.get_value(iter, 2) + output_send = self.main.common.exe_cmd("pactl load-module module-rtp-send format=s16be channels=2 rate=44100 source=@DEFAULT_SOURCE@ loop=0 destination=%s" %self.selected_channel) + output_recv = self.main.common.exe_cmd("pactl load-module module-rtp-recv sap_address=%s" %self.selected_channel) + if output_send != "" or output_recv != "": + self.rtp_control_count[self.selected_channel]=[output_send, output_recv] + print_debug("chat_connects %s" %self.rtp_control_count) + model.foreach(self.line_changer, [self.selected_channel, self.image_active, True]) + self.main.chat_button_disconnect.set_sensitive(True) + self.main.chat_button_connect.set_sensitive(False) + return True + + def chat_exit(self, *args): + self.main.chatwindow.hide() + self.model.clear() + self.control_list=False + return True + + def line_exists(self, model, path, iter, args): + ip = args + # change mac if ip is the same. + if model.get_value(iter, 2) == ip: + self.new_line=False + + def line_changer(self, model, path, iter, args): + ip, image, active = args + # change mac if ip is the same. + if model.get_value(iter, 2) == ip: + model.set_value(iter, 1, image) + model.set_value(iter, 3, active) + + def line_delete(self, model, path, iter, args): + ip = args + if model.get_value(iter, 2) == ip: + self.delete_iter=iter + + def chat_delete(self, data): + print_debug("chat_delete() data=%s" %data) + model=self.main.chatlist.get_model() + self.delete_iter=None + model.foreach(self.line_delete, data) + # delete iter if found + if self.delete_iter is not None: + model.remove(self.delete_iter) + + def rtp_all(self, *args): + if not self.get_all_clients(): + return + # conference mode + if len(self.connected_users) == 0 or self.connected_users[0] == shared.NO_LOGIN_MSG: + shared.error_msg( _("No users logged.") ) + return + + cmd=("LC_ALL=C LC_MESSAGES=C pactl --version 2>/dev/null | awk '{print $2}' | awk -F\".\" '{if ((int($2) >= 9) && (int($3) >= 10)) printf 1}'") + output=self.main.common.exe_cmd(cmd) + if output != "1": + shared.error_msg( _("Your pulseaudio server is too old.\nIs required pulseaudio version >= 0.9.10") ) + return + + msg=_( _("Do you want to start audio conference to the following users: %s?" )%(self.connected_users_txt) ) + + if not shared.ask_msg ( msg ): + return + + remote_msg=_("You have entered in audio conference") + eth=self.main.config.GetVar("network_interface") + max_uip=255 + uip=0 + while uip <= max_uip: + uip_cmd="225.0.0.%s" %(uip) + cmd=("LC_ALL=C LC_MESSAGES=C netstat -putan 2>/dev/null | grep -c %s" %(uip_cmd) ) + print_debug("Check broadcast ip %s." %(uip_cmd) ) + output=self.main.common.exe_cmd(cmd) + uip+=1 + if output == "0" and uip_cmd not in self.rtp_count.values(): + print_debug("Broadcast ip found: %s" %(uip_cmd)) + ip_broadcast="%s" %uip_cmd + break + elif uip == max_uip: + print_debug("Not found an available broadcast ip") + return + result = self.main.localdata.Route("route-add", ip_broadcast, "255.255.255.255", eth) + if result == "error": + print_debug("Add multicast-ip route failed") + return + self.main.common.exe_cmd("/usr/lib/tcos/pactl-controller.sh start-server") + output = self.main.common.exe_cmd("pactl load-module module-rtp-send format=s16be channels=2 rate=44100 source=@DEFAULT_SOURCE@ loop=0 destination=%s" %ip_broadcast) + + self.main.write_into_statusbar( _("Waiting for start audio conference...") ) + + total=0 + for client in self.newallclients: + self.main.xmlrpc.rtp("startrtp-recv", client, ip_broadcast ) + total+=1 + + if total < 1: + self.main.write_into_statusbar( _("No users logged.") ) + # kill x11vnc + self.main.common.exe_cmd("pactl unload-module %s" %output) + result = self.main.localdata.Route("route-del", ip_broadcast, "255.255.255.255", eth) + if result == "error": + print_debug("Del multicast-ip route failed") + if len(self.rtp_count.keys()) == 0: + self.main.common.exe_cmd("/usr/lib/tcos/pactl-controller.sh stop-server") + else: + newusernames=[] + for user in self.connected_users: + if user.find(":") != -1: + # we have a standalone user... + usern, ip = user.split(":") + self.main.xmlrpc.newhost(ip) + self.main.xmlrpc.DBus("mess", remote_msg) + else: + newusernames.append(user) + + self.main.dbus_action.do_message( newusernames, remote_msg ) + self.main.write_into_statusbar( _("Running in audio conference with %s clients.") %(total) ) + # new mode Stop Button + if len(self.rtp_count.keys()) != 0: + count=len(self.rtp_count.keys())-1 + nextkey=self.rtp_count.keys()[count]+1 + self.rtp_count[nextkey]=ip_broadcast + else: + nextkey=1 + self.rtp_count[nextkey]=ip_broadcast + #self.main.menus.broadcast_count[ip_broadcast]=None + self.add_progressbox( {"target": "rtp", "pid":output, "allclients":self.newallclients, "ip":"", "ip_broadcast":ip_broadcast, "iface":eth, "key":nextkey}, _("Running in audio conference from server. Conference Nº %s") %(nextkey) ) + + + def rtp_simple(self, widget, ip_simple): + if not self.get_client(): + return + + client_simple=self.connected_users_txt + + # conference mode + if len(self.connected_users) == 0 or self.connected_users[0] == shared.NO_LOGIN_MSG: + shared.error_msg( _("Can't start conference mode, user is not logged") ) + return + + cmd=("LC_ALL=C LC_MESSAGES=C pactl --version 2>/dev/null | awk '{print $2}' | awk -F\".\" '{if ((int($2) >= 9) && (int($3) >= 10)) printf 1}'") + output=self.main.common.exe_cmd(cmd) + if output != "1": + shared.error_msg( _("Your pulseaudio server is too old.\nIs required pulseaudio version >= 0.9.10") ) + return + + msg=_( _("Do you want audio conference from user %s?" ) %(client_simple) ) + if not shared.ask_msg ( msg ): + return + + + # Allow one client + # if len(self.allclients) == 0: return + remote_msg=_("You have entered in audio conference from user %s") %client_simple + eth=self.main.config.GetVar("network_interface") + max_uip=255 + uip=0 + while uip <= max_uip: + uip_cmd="225.0.0.%s" %(uip) + cmd=("LC_ALL=C LC_MESSAGES=C netstat -putan 2>/dev/null | grep -c %s" %(uip_cmd) ) + print_debug("Check broadcast ip %s." %(uip_cmd) ) + output=self.main.common.exe_cmd(cmd) + uip+=1 + if output == "0" and uip_cmd not in self.rtp_count.values(): + print_debug("Broadcast ip found: %s" %(uip_cmd)) + ip_broadcast="%s" %uip_cmd + break + elif uip == max_uip: + print_debug("Not found an available broadcast ip") + return + + if not self.get_all_clients(): + return + + result = self.main.localdata.Route("route-add", ip_broadcast, "255.255.255.255", eth) + if result == "error": + print_debug("Add multicast-ip route failed") + return + + #self.main.xmlrpc.newhost(ip) + self.main.xmlrpc.rtp("startrtp-send", ip_simple, ip_broadcast ) + self.main.write_into_statusbar( _("Waiting for start audio conference from user %s...") %(client_simple) ) + + output = self.main.common.exe_cmd("pactl load-module module-rtp-recv sap_address=%s" %ip_broadcast) + + newallclients2=[] + total=1 + for client in self.newallclients: + self.main.localdata.newhost(client) + if client != ip_simple: + self.main.xmlrpc.rtp("startrtp-recv", client, ip_broadcast ) + total+=1 + newallclients2.append(client) + + if total < 1: + self.main.write_into_statusbar( _("No users logged.") ) + self.main.common.exe_cmd("pactl unload-module %s" %output) + self.main.xmlrpc.rtp("stoprtp-send", ip_simple ) + result = self.main.localdata.Route("route-del", ip_broadcast, "255.255.255.255", eth) + if result == "error": + print_debug("Del multicast-ip route failed") + else: + newusernames=[] + for user in self.connected_users: + if user.find(":") != -1: + # we have a standalone user... + usern, ip = user.split(":") + self.main.xmlrpc.newhost(ip) + self.main.xmlrpc.DBus("mess", remote_msg) + else: + newusernames.append(user) + self.main.dbus_action.do_message( newusernames, remote_msg ) + self.main.write_into_statusbar( _("Running in audio conference with %s clients.") %(total) ) + # new mode Stop Button + if len(self.rtp_count.keys()) != 0: + count=len(self.rtp_count.keys())-1 + nextkey=self.rtp_count.keys()[count]+1 + self.rtp_count[nextkey]=ip_broadcast + else: + nextkey=1 + self.rtp_count[nextkey]=ip_broadcast + #self.main.menus.broadcast_count[ip_broadcast]=None + self.add_progressbox( {"target": "rtp", "pid":output, "allclients":newallclients2, "ip":ip_simple, "ip_broadcast":ip_broadcast, "iface":eth, "key":nextkey}, _("Running in audio conference from user %(host)s. Conference Nº %(count)s") %{"host":client_simple, "count":nextkey} ) + + def rtp_chat(self, *args): + if not self.get_all_clients(): + return + # conference mode + if len(self.connected_users) == 0 or self.connected_users[0] == shared.NO_LOGIN_MSG: + shared.error_msg( _("No users logged.") ) + return + + cmd=("LC_ALL=C LC_MESSAGES=C pactl --version 2>/dev/null | awk '{print $2}' | awk -F\".\" '{if ((int($2) >= 9) && (int($3) >= 10)) printf 1}'") + output=self.main.common.exe_cmd(cmd) + if output != "1": + shared.error_msg( _("Your pulseaudio server is too old.\nIs required pulseaudio version >= 0.9.10") ) + return + + msg=_( _("Do you want to start audio chat conference to the following users: %s?" )%(self.connected_users_txt) ) + + if not shared.ask_msg ( msg ): + return + + remote_msg=_("You have entered in audio chat conference. Participants: %s") %self.connected_users_txt + eth=self.main.config.GetVar("network_interface") + max_uip=255 + uip=0 + while uip <= max_uip: + uip_cmd="225.0.0.%s" %(uip) + cmd=("LC_ALL=C LC_MESSAGES=C netstat -putan 2>/dev/null | grep -c %s" %(uip_cmd) ) + print_debug("Check broadcast ip %s." %(uip_cmd) ) + output=self.main.common.exe_cmd(cmd) + uip+=1 + if output == "0" and uip_cmd not in self.rtp_count.values(): + print_debug("Broadcast ip found: %s" %(uip_cmd)) + ip_broadcast="%s" %uip_cmd + break + elif uip == max_uip: + print_debug("Not found an available broadcast ip") + return + result = self.main.localdata.Route("route-add", ip_broadcast, "255.255.255.255", eth) + if result == "error": + print_debug("Add multicast-ip route failed") + return + + self.main.write_into_statusbar( _("Waiting for start audio chat conference...") ) + + output_send="" + output_recv="" + self.rtp_control_count[ip_broadcast]=[] + self.main.common.exe_cmd("/usr/lib/tcos/pactl-controller.sh start-server") + msg=_( "Do you want to connect to this audio chat conference now?" ) + if shared.ask_msg ( msg ): + output_send = self.main.common.exe_cmd("pactl load-module module-rtp-send format=s16be channels=2 rate=44100 source=@DEFAULT_SOURCE@ loop=0 destination=%s" %ip_broadcast) + output_recv = self.main.common.exe_cmd("pactl load-module module-rtp-recv sap_address=%s" %ip_broadcast) + self.rtp_control_count[ip_broadcast]=[output_send, output_recv] + total=0 + for client in self.newallclients: + self.main.xmlrpc.rtp("startrtp-chat", client, ip_broadcast ) + total+=1 + + if total < 1: + self.main.write_into_statusbar( _("No users logged.") ) + # kill x11vnc + if output_send != "" or output_recv != "": + self.main.common.exe_cmd("pactl unload-module %s" %output_send) + self.main.common.exe_cmd("pactl unload-module %s" %output_recv) + del self.rtp_control_count[ip_broadcast] + result = self.main.localdata.Route("route-del", ip_broadcast, "255.255.255.255", eth) + if result == "error": + print_debug("Del multicast-ip route failed") + if len(self.rtp_count.keys()) == 0: + self.main.common.exe_cmd("/usr/lib/tcos/pactl-controller.sh stop-server") + else: + newusernames=[] + for user in self.connected_users: + if user.find(":") != -1: + # we have a standalone user... + usern, ip = user.split(":") + self.main.xmlrpc.newhost(ip) + self.main.xmlrpc.DBus("mess", remote_msg) + else: + newusernames.append(user) + self.main.dbus_action.do_message( newusernames, remote_msg ) + + self.main.write_into_statusbar( _("Running in audio chat conference with %s clients.") %(total) ) + # new mode Stop Button + if len(self.rtp_count.keys()) != 0: + count=len(self.rtp_count.keys())-1 + nextkey=self.rtp_count.keys()[count]+1 + self.rtp_count[nextkey]=ip_broadcast + else: + nextkey=1 + self.rtp_count[nextkey]=ip_broadcast + if self.control_list: + self.populate_data(self.rtp_count) + #self.main.menus.broadcast_count[ip_broadcast]=None + self.add_progressbox( {"target": "rtp-chat", "pid_send":output_send, "pid_recv":output_recv, "allclients":self.newallclients, "ip":"", "ip_broadcast":ip_broadcast, "iface":eth, "key":nextkey}, _("Running in audio chat conference. Conference Nº %s") %(nextkey) ) + + def on_progressbox_click(self, widget, args, box): + box.destroy() + print_debug("on_progressbox_click() widget=%s, args=%s, box=%s" %(widget, args, box) ) + + if not args['target']: + return + + self.main.stop_running_actions.remove(widget) + + if args['target'] == "rtp": + del self.rtp_count[args['key']] + if args['ip_broadcast'] != "": + result = self.main.localdata.Route("route-del", args['ip_broadcast'], "255.255.255.255", args['iface']) + if result == "error": + print_debug("Del multicast-ip route failed") + #del self.main.menus.broadcast_count[args['ip_broadcast']] + for client in args['allclients']: + self.main.xmlrpc.rtp("stoprtp-recv", client) + if "pid" in args: + self.main.common.exe_cmd("pactl unload-module %s" %args['pid']) + if args['ip'] != "": + self.main.xmlrpc.rtp("stoprtp-send", args['ip'] ) + if len(self.rtp_count.keys()) == 0: + self.main.common.exe_cmd("/usr/lib/tcos/pactl-controller.sh stop-server") + self.main.write_into_statusbar( _("Conference mode off.") ) + + if args['target'] == "rtp-chat": + del self.rtp_count[args['key']] + if args['ip_broadcast'] != "": + result = self.main.localdata.Route("route-del", args['ip_broadcast'], "255.255.255.255", args['iface']) + if result == "error": + print_debug("Del multicast-ip route failed") + #del self.main.menus.broadcast_count[args['ip_broadcast']] + for client in args['allclients']: + self.main.xmlrpc.rtp("stoprtp-chat", client) + if self.rtp_control_count.has_key(args['ip_broadcast']) and len(self.rtp_control_count[args['ip_broadcast']]) > 0: + self.main.common.exe_cmd("pactl unload-module %s" %self.rtp_control_count[args['ip_broadcast']][0]) + self.main.common.exe_cmd("pactl unload-module %s" %self.rtp_control_count[args['ip_broadcast']][1]) + del self.rtp_control_count[args['ip_broadcast']] + if self.control_list: + self.chat_delete(args['ip_broadcast']) + if len(self.rtp_count.keys()) == 0: + self.main.common.exe_cmd("/usr/lib/tcos/pactl-controller.sh stop-server") + self.main.write_into_statusbar( _("Audio chat conference off.") ) + + + +__extclass__=AudioRTP diff --git a/tcosmonitor/extensions/clean.py b/tcosmonitor/extensions/clean.py new file mode 100644 index 0000000..2aa63c9 --- /dev/null +++ b/tcosmonitor/extensions/clean.py @@ -0,0 +1,58 @@ +# -*- coding: UTF-8 -*- +# TcosMonitor version __VERSION__ +# +# Copyright (c) 2006-2011 Mario Izquierdo <mariodebian@gmail.com> +# +# This package is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# +# This package is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +""" template extension """ + +from gettext import gettext as _ +import sys + +from tcosmonitor import shared +from tcosmonitor.TcosExtensions import TcosExtension + + +def print_debug(txt): + if shared.debug: + print >> sys.stderr, "%s::%s" % (__name__, txt) + #print("%s::%s" % (__name__, txt), file=sys.stderr) + + +class Clean(TcosExtension): + def register(self): + self.main.menus.register_simple(_("Clean info about terminal"), "menu_clear.png", 0, self.clean, "clean") + self.main.menus.register_all( _("Clean info about terminal"), "menu_clear.png", 0, self.clean, "clean") + + def clean(self, *args): + print_debug("clean()") + self.main.datatxt.clean() + self.main.write_into_statusbar('') + + + + + + +__extclass__=Clean + + + + + + + + diff --git a/tcosmonitor/extensions/dpms.py b/tcosmonitor/extensions/dpms.py new file mode 100644 index 0000000..44b35d5 --- /dev/null +++ b/tcosmonitor/extensions/dpms.py @@ -0,0 +1,98 @@ +# -*- coding: UTF-8 -*- +# TcosMonitor version __VERSION__ +# +# Copyright (c) 2006-2011 Mario Izquierdo <mariodebian@gmail.com> +# +# This package is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# +# This package is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +""" template extension """ + +from gettext import gettext as _ +import sys + +from tcosmonitor import shared +from tcosmonitor.TcosExtensions import TcosExtension + + +def print_debug(txt): + if shared.debug: + print >> sys.stderr, "%s::%s" % (__name__, txt) + #print("%s::%s" % (__name__, txt), file=sys.stderr) + + +class Dpms(TcosExtension): + def register(self): + self.main.menus.register_simple( _("DPMS Power off monitor"), "menu_dpms_off.png", 0, self.dpms_off, "dpms") + self.main.menus.register_all( _("DPMS Power off monitors"), "menu_dpms_off.png", 0, self.dpms_off_all, "dpms") + self.main.menus.register_simple( _("DPMS Power on monitor"), "menu_dpms_on.png", 0, self.dpms_on, "dpms") + self.main.menus.register_all( _("DPMS Power on monitors"), "menu_dpms_on.png", 0, self.dpms_on_all, "dpms") + + def dpms_off(self, w, ip): + if not self.get_client(): + return + # DPMS off + self.main.xmlrpc.dpms('off') + self.change_lockscreen(self.main.selected_ip) + + def dpms_on(self, w, ip): + if not self.get_client(): + return + # DPMS on + self.main.xmlrpc.dpms('on') + self.change_lockscreen(self.main.selected_ip) + + def real_action(self, ip, action): + print_debug("real_action() ip=%s action='%s'"%(ip, action) ) + + if action == 'dpmsoff': + result=self.main.xmlrpc.dpms('off') + print_debug("real_action() DPMS OFF result=%s"%result) + self.main.common.threads_enter("extensions/dpms::real_action dpms off") + self.change_lockscreen(ip) + self.main.common.threads_leave("extensions/dpms::real_action dpms off") + elif action == 'dpmson': + result=self.main.xmlrpc.dpms('on') + print_debug("real_action() DPMS ON result=%s"%result) + self.main.common.threads_enter("extensions/dpms::real_action dpms on") + self.change_lockscreen(ip) + self.main.common.threads_leave("extensions/dpms::real_action dpms on") + + + def dpms_off_all(self, *args): + if not self.get_all_clients(): + return + msg=_( _("Do you want to switch off the following monitors: %s?" ) %(self.connected_users_txt_all) ) + if shared.ask_msg ( msg ): + self.main.worker=shared.Workers(self.main, None, None) + self.main.worker.set_for_all_action(self.action_for_clients, \ + self.allclients_logged, "dpmsoff" ) + + def dpms_on_all(self, *args): + if not self.get_all_clients(): + return + msg=_( _("Do you want to switch on the following monitors: %s?" ) %(self.connected_users_txt_all) ) + if shared.ask_msg ( msg ): + self.main.worker=shared.Workers(self.main, None, None) + self.main.worker.set_for_all_action(self.action_for_clients, \ + self.allclients_logged, "dpmson" ) + + +__extclass__=Dpms + + + + + + diff --git a/tcosmonitor/extensions/info.py b/tcosmonitor/extensions/info.py new file mode 100644 index 0000000..80fefab --- /dev/null +++ b/tcosmonitor/extensions/info.py @@ -0,0 +1,616 @@ +# -*- coding: UTF-8 -*- +# TcosMonitor version __VERSION__ +# +# Copyright (c) 2006-2011 Mario Izquierdo <mariodebian@gmail.com> +# +# This package is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# +# This package is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +""" template extension """ + +from gettext import gettext as _ +from time import time +import gtk +import os +import sys + +from tcosmonitor import shared +from tcosmonitor.TcosExtensions import TcosExtension +from tcosmonitor.ping import PingPort + +def crono(start, txt): + print_debug ("crono(), %s get %f seconds" %(txt, (time() - start)) ) + return + +def print_debug(txt): + if shared.debug: + print >> sys.stderr, "%s::%s" % (__name__, txt) + #print("%s::%s" % (__name__, txt), file=sys.stderr) + + +class Info(TcosExtension): + def register(self): + self.main.menus.register_simple(_("Refresh terminal info"), "menu_refresh.png", 0, self.get_info, "info") + # register file click event target + self.main.listview.populate_datatxt=self.populate_datatxt + + def get_info(self, widget, ip): + if not self.get_client(): + return + print_debug("get_info() ip=%s"%(ip)) + self.main.xmlrpc.ip=ip + self.main.worker=shared.Workers( self.main,\ + target=self.populate_datatxt, args=(ip,) ).start() + + + def populate_datatxt(self, ip): + start1=time() + print_debug ("populate_datatxt() INIT ip %s"%ip) + + if not self.main.xmlrpc.connected: + print_debug ( "populate_datatxt(%s) NO CONNECTION" %(ip) ) + crono(start1, "populate_datatxt(%s)" %(ip) ) + return + + # dictionary with all data + tcos_vars={} + + self.datatxt = self.main.datatxt + + # clear datatxt + self.main.common.threads_enter("TcosActions:populate_datatxt clean datatxt") + self.datatxt.clean() + self.main.common.threads_leave("TcosActions:populate_datatxt clean datatxt") + tcos_vars["get_client"] = self.main.xmlrpc.ReadInfo("get_client") + print_debug ( "Client type=%s" %(tcos_vars["get_client"]) ) + + # print into statusbar + self.main.common.threads_enter("TcosActions:populate_datatxt show progressbar") + + if shared.disable_textview_on_update and self.main.listview.isactive(): + self.main.tabla.set_sensitive(True) + + #self.main.write_into_statusbar( _("Connecting with %s to retrieve some info..." ) %(ip) ) + + self.main.progressbar.show() + #self.main.progressbutton.show() + self.main.actions.set_progressbar( _("Connecting with %s to retrieve some info..." ) %(ip) , 0, show_percent=False) + + self.main.common.threads_leave("TcosActions:populate_datatxt show progressbar") + + + info_percent=0.0 + info_items=0 + for elem in self.main.config.vars: + # elem can have 2 or 3 elements (don't use key,value in for) + key=elem[0] + value=elem[1] + if self.main.config.GetVar(key) == 1: + info_items += 1 + if info_items != 0: + percent_step=float((100/info_items)) + percent_step=percent_step/100 + + + + if self.main.config.GetVar("tcosinfo") == 1: + info_percent+=percent_step + self.main.common.threads_enter("TcosActions:populate_datatxt update progressbar") + self.main.actions.update_progressbar( info_percent ) + self.main.common.threads_leave("TcosActions:populate_datatxt update progressbar") + + if tcos_vars["get_client"] == "tcos": + self.datatxt.insert_block( _("Tcos info") , image=shared.IMG_DIR + "tcos-icon-32x32.png" ) + + elif tcos_vars["get_client"] == "pxes": + self.datatxt.insert_block( _("PXES info") , image="/usr/share/pixmaps/pxesconfig/2X.png" ) + + elif tcos_vars["get_client"] == "ltsp": + self.datatxt.insert_block( _("LTSP info") , image=shared.IMG_DIR + "ltsp_logo.png" ) + + elif tcos_vars["get_client"] == "standalone": + self.datatxt.insert_block( _("Standalone info") , image=shared.IMG_DIR + "standalone.png" ) + + elif tcos_vars["get_client"] == "multiseat": + self.datatxt.insert_block( _("Multiseat info") , image=shared.IMG_DIR + "standalone.png" ) + + else: + self.datatxt.insert_block( _("Unknow client info") ) + + tcos_vars["hostname"]=self.main.localdata.GetHostname(ip) + tcos_vars["version"]=self.main.xmlrpc.GetVersion() + + if not tcos_vars["version"]: + tcos_vars["version"]=_("unknow") + + self.datatxt.insert_list( [ + [ _("Hostname: "), tcos_vars["hostname"] ] , \ + [ _("Ip address: "), ip ] , \ + [ _("TcosXmlRpc version: "), tcos_vars["version"] ] + ] ) + + tcos_vars["tcos_version"]=self.main.xmlrpc.ReadInfo("tcos_version") + tcos_vars["tcos_generation_date"]=self.main.xmlrpc.ReadInfo("tcos_generation_date") + tcos_vars["tcos_date"]=self.main.xmlrpc.ReadInfo("tcos_date") + tcos_vars["tcos_uptime"]=self.main.xmlrpc.ReadInfo("tcos_uptime") + + self.datatxt.insert_list( [ \ + [_("Tcos image version: "), tcos_vars["tcos_version"] ], \ + [_("Tcos image date: "), tcos_vars["tcos_generation_date"] ], \ + [_("Date of thin client: "), tcos_vars["tcos_date"] ], + [_("Uptime: "), tcos_vars["tcos_uptime"] ] + ] ) + + + + if self.main.config.GetVar("kernelmodulesinfo") == 1: + info_percent+=percent_step + self.main.common.threads_enter("TcosActions:populate_datatxt update progressbar") + self.main.actions.update_progressbar( info_percent ) + self.main.common.threads_leave("TcosActions:populate_datatxt update progressbar") + + self.datatxt.insert_block( _("Kernel info"), image=shared.IMG_DIR + "info_kernel.png" ) + + tcos_vars["kernel_version"]=self.main.xmlrpc.ReadInfo("kernel_version") + tcos_vars["kernel_complete_version"]=self.main.xmlrpc.ReadInfo("kernel_complete_version") + tcos_vars["modules_loaded"]=self.main.xmlrpc.ReadInfo("modules_loaded") + tcos_vars["modules_notfound"]=self.main.xmlrpc.ReadInfo("modules_notfound") + + if tcos_vars["modules_notfound"] != "OK" and tcos_vars["get_client"] == "tcos": + + blabel=_("Force download and mount all modules") + self.main.action_button=gtk.Button( label=blabel ) + self.main.action_button.connect("clicked", self.on_downloadallmodules_click) + self.main.action_button.show() + + tcos_vars["modules_notfound"] = """ + <span style='color:red'>%s </span> + <input type='button' name='%s' label='%s' /> + """ % (tcos_vars["modules_notfound"], "self.main.action_button" , blabel) + + else: + tcos_vars["modules_notfound"] = _("None") + + self.datatxt.insert_list( [ \ + [_("Kernel version: "), tcos_vars["kernel_version"] ], \ + [_("Kernel complete version: "), tcos_vars["kernel_complete_version"] ], \ + [_("Loaded Modules: "), tcos_vars["modules_loaded"] ], \ + [_("Modules not found: "), tcos_vars["modules_notfound"] ] + ] ) + + + cpuinfo=self.main.config.GetVar("cpuinfo") + pciinfo=self.main.config.GetVar("pcibusinfo") + ramswapinfo=self.main.config.GetVar("ramswapinfo") + networkinfo=self.main.config.GetVar("networkinfo") + + + if cpuinfo == 1: + info_percent+=percent_step + self.main.common.threads_enter("TcosActions:populate_datatxt update progressbar") + self.main.actions.update_progressbar( info_percent ) + self.main.common.threads_leave("TcosActions:populate_datatxt update progressbar") + + self.datatxt.insert_block( _("Cpu info: "), image=shared.IMG_DIR + "info_cpu.png" ) + + tcos_vars["cpu_model"]=self.main.xmlrpc.ReadInfo("cpu_model") + tcos_vars["cpu_vendor"]=self.main.xmlrpc.ReadInfo("cpu_vendor") + tcos_vars["cpu_speed"]=self.main.xmlrpc.ReadInfo("cpu_speed") + + self.datatxt.insert_list( [ \ + [_("Cpu model: "), tcos_vars["cpu_model"] ], \ + [_("Cpu vendor: "), tcos_vars["cpu_vendor"] ], \ + [_("Cpu speed: "), tcos_vars["cpu_speed"] ] + ] ) + + + if pciinfo == 1: + info_percent+=percent_step + self.main.common.threads_enter("TcosActions:populate_datatxt update progressbar") + self.main.actions.update_progressbar( info_percent ) + self.main.common.threads_leave("TcosActions:populate_datatxt update progressbar") + + # PCI info + self.datatxt.insert_block( _("PCI buses: ") , image=shared.IMG_DIR + "info_pci.png" ) + + pcilist=[] + try: + allpci=self.main.xmlrpc.tc.tcos.pci("pci_all").split(' ') + except Exception, err: + print_debug("info() Exception pci error %s"%err) + self.main.xmlrpc.CheckSSL(err) + + for pci_id in allpci: + if pci_id != "": + try: + pci_info=self.main.xmlrpc.tc.tcos.pci(pci_id) + pcilist.append( [pci_id + " ", pci_info] ) + except Exception, err: + print_debug("info() Exception pci error %s"%err) + self.main.xmlrpc.CheckSSL(err) + + self.datatxt.insert_list( pcilist ) + + + + if self.main.config.GetVar("processinfo") == 1 and tcos_vars["get_client"] != "standalone": + info_percent+=percent_step + self.main.common.threads_enter("TcosActions:populate_datatxt update progressbar") + self.main.actions.update_progressbar( info_percent ) + self.main.common.threads_leave("TcosActions:populate_datatxt update progressbar") + + self.datatxt.insert_block( _("Process running: "), image=shared.IMG_DIR + "info_proc.png" ) + + proclist=[] + allprocess=self.main.xmlrpc.ReadInfo("get_process").split('|') + self.datatxt.insert_proc( allprocess ) + + + if ramswapinfo == 1: + info_percent+=percent_step + self.main.common.threads_enter("TcosActions:populate_datatxt update progressbar") + self.main.actions.update_progressbar( info_percent ) + self.main.common.threads_leave("TcosActions:populate_datatxt update progressbar") + + self.datatxt.insert_block( _("Ram info: "), image=shared.IMG_DIR + "info_ram.png" ) + + tcos_vars["ram_total"]=self.main.xmlrpc.ReadInfo("ram_total") + tcos_vars["ram_free"]=self.main.xmlrpc.ReadInfo("ram_free") + tcos_vars["ram_active"]=self.main.xmlrpc.ReadInfo("ram_active") + + self.datatxt.insert_list( [ \ + [_("Total Ram: "), tcos_vars["ram_total"] ], \ + [_("Free RAM: "), tcos_vars["ram_free"] ], \ + [_("Active RAM: "), tcos_vars["ram_active"] ] + ] ) + + self.datatxt.insert_block( _("Swap info: "), image=shared.IMG_DIR + "info_swap.png" ) + tcos_vars["swap_avalaible"]=self.main.xmlrpc.ReadInfo("swap_avalaible") + tcos_vars["swap_total"]=self.main.xmlrpc.ReadInfo("swap_total") + tcos_vars["swap_used"]=self.main.xmlrpc.ReadInfo("swap_used") + + self.datatxt.insert_list( [ \ + [_("Swap enabled: "), tcos_vars["swap_avalaible"] ], \ + [_("Total Swap: "), tcos_vars["swap_total"] ], \ + [_("Used Swap: "), tcos_vars["swap_used"] ] + ] ) + + + + if networkinfo == 1: + info_percent+=percent_step + self.main.common.threads_enter("TcosActions:populate_datatxt update progressbar") + self.main.actions.update_progressbar( info_percent ) + self.main.common.threads_leave("TcosActions:populate_datatxt update progressbar") + self.datatxt.insert_block( _("Network info: ") , image=shared.IMG_DIR + "info_net.png" ) + + tcos_vars["network_hostname"]=self.main.xmlrpc.ReadInfo("network_hostname") + tcos_vars["network_ip"]=self.main.xmlrpc.ReadInfo("network_ip") + tcos_vars["network_mask"]=self.main.xmlrpc.ReadInfo("network_mask") + tcos_vars["network_mac"]=self.main.xmlrpc.ReadInfo("network_mac") + tcos_vars["network_rx"]=self.main.xmlrpc.ReadInfo("network_rx") + tcos_vars["network_tx"]=self.main.xmlrpc.ReadInfo("network_tx") + + self.datatxt.insert_list( [ \ + [_("Network hostname: "), tcos_vars["network_hostname"] ], \ + [_("Network IP: "), tcos_vars["network_ip"] ], \ + [_("Network MASK: "), tcos_vars["network_mask"] ], \ + [_("Network MAC: "), tcos_vars["network_mac"] ], \ + [_("Data received(rx): "), tcos_vars["network_rx"] ], \ + [_("Data send(tx): "), tcos_vars["network_tx"] ] + ] ) + + + if self.main.config.GetVar("xorginfo") == 1 and tcos_vars["get_client"] != "standalone": + info_percent+=percent_step + self.main.common.threads_enter("TcosActions:populate_datatxt update progressbar") + self.main.actions.update_progressbar( info_percent ) + self.main.common.threads_leave("TcosActions:populate_datatxt update progressbar") + + self.datatxt.insert_block( _("Xorg info") , image=shared.IMG_DIR + "info_xorg.png" ) + + xorglist=[] + try: + alldata=self.main.xmlrpc.tc.tcos.xorg("get", "", \ + self.main.config.GetVar("xmlrpc_username"), \ + self.main.config.GetVar("xmlrpc_password") ).split() + except Exception, err: + print_debug("info() Exception networking error %s"%err) + self.main.xmlrpc.CheckSSL(err) + + print_debug ( "populate_datatxt() %s" %( " ".join(alldata) ) ) + if alldata[0].find("error") == 0: + #shared.error_msg( _("Error getting Xorg info:\n%s" ) %( " ".join(alldata)) ) + pass + else: + for data in alldata: + try: + (key, value)=data.split('=') + except Exception, err: + print_debug("populate_datatxt() Exception spliting data=%s, err=%s"%(data, err)) + key=data + value="" + + if value== "1": + value = _("enabled") + elif value == "0": + value = _("disabled") + + if key == "xsession": + key=_("X Session Type") + elif key == "xdriver": + key=_("Xorg Driver") + elif key == "xres": + key=_("Xorg Resolution") + elif key == "xdepth": + key=_("Xorg Color depth") + elif key == "xdpms": + key=_("DPMS energy monitor control") + elif key == "xdontzap": + key=_("Disable kill X with Ctrl+Alt+Backspace") + elif key == "xmousewheel": + key=_("Enable mouse wheel") + elif key == "xrefresh": + key=_("Refresh rate") + elif key == "xfontserver": + key = _("Xorg font server") + elif key == "xmousedev": + key = _("Mouse device") + elif key == "xmouseprotocol": + key = _("Mouse protocol") + elif key == "xhorizsync": + key = _("X Horiz sync") + elif key == "xvertsync": + key = _("X Vert sync") + xorglist.append( [key + " " , value] ) + self.datatxt.insert_list(xorglist) + + + if self.main.config.GetVar("soundserverinfo") == 1: + info_percent+=percent_step + self.main.common.threads_enter("TcosActions:populate_datatxt update progressbar") + self.main.actions.update_progressbar( info_percent ) + self.main.common.threads_leave("TcosActions:populate_datatxt update progressbar") + + # make a ping to port + if tcos_vars["get_client"] == "standalone" or PingPort(ip, shared.pulseaudio_soundserver_port, 0.5).get_status() == "OPEN": + self.datatxt.insert_block ( _("PulseAudio Sound server is running"), image=shared.IMG_DIR + "info_sound_ok.png" ) + + channel_list=[] + tcos_sound_vars={} + #tcos_sound_vars["allchannels"]=self.main.xmlrpc.GetSoundChannels() + tcos_sound_vars["allchannels"]=self.main.xmlrpc.GetSoundChannelsContents() + #print_debug ( "populate_datatxt() sound channels=%s" %(tcos_sound_vars["allchannels"]) ) + + counter=0 + self.main.volume_sliders=[] + self.main.volume_checkboxes=[] + + self.datatxt.insert_html(""" + <br /> + <div style='text-align:center; background-color:#f3d160 ; margin-left: 25%%; margin-right: 25%%'> + <img file="%s" /> + <span style='font-weight: bold; font-size: 150%%'>%s</span> + </div> + """ %( shared.IMG_DIR + "icon_mixer.png", _("Remote Sound Mixer")) ) + + + for channel in tcos_sound_vars["allchannels"]: + volumebutton=None + # only show channel in list + if not channel['name'] in shared.sound_only_channels: + print_debug("populate_datatxt() *** AUDIO CHANNEL HIDDEN*** channel=%s"%channel) + continue + txt=""" + <div style='text-align:center; background-color:#f3d160 ; margin-left: 25%%; margin-right: 25%%'> + <span style='font-size: 120%%'>%s: </span> + """ %(channel['name']) + + + #value=self.main.xmlrpc.GetSoundInfo(channel, mode="--getlevel") + #value=value.replace('%','') + value=channel['level'] + try: + value=float(value) + except Exception, err: + print_debug("populate_datatxt() Exception getting volume=%s, err=%s"%(value, err) ) + value=0.0 + + #ismute=self.main.xmlrpc.GetSoundInfo(channel, mode="--getmute") + ismute=channel['mute'] + if ismute == "off": + ismute = True + else: + ismute = False + + ctype=channel['type'] + print_debug ( "populate_datatxt() channel=%s ismute=%s volume level=%s ctype=%s" %(channel['name'], ismute, value, ctype) ) + ############ mute checkbox ################## + volume_checkbox=gtk.CheckButton(label=_("Mute"), use_underline=True) + volume_checkbox.set_active(ismute) + volume_checkbox.connect("toggled", self.checkbox_value_changed, channel['name'], ip) + if "switch" in ctype: + volume_checkbox.show() + else: + volume_checkbox.hide() + self.main.volume_checkboxes.append(volume_checkbox) + + txt+="<input type='checkbox' name='self.main.volume_checkboxes' index='%s' />" %(counter) + + + ############# volume slider ################### + adjustment = gtk.Adjustment(value=0, + lower=0, + upper=100, + step_incr=1, + page_incr=1) + volume_slider = gtk.HScale(adjustment) + volume_slider.set_size_request(100, 30) + volume_slider.set_value_pos(gtk.POS_RIGHT) + volume_slider.set_digits(0) + volume_slider.set_value( value ) + volume_slider.connect("button_release_event", self.slider_value_changed, adjustment, channel['name'], ip) + volume_slider.connect("scroll_event", self.slider_value_changed, adjustment, channel['name'], ip) + if "volume" in ctype: + volume_slider.show() + else: + volume_slider.hide() + self.main.volume_sliders.append(volume_slider) + txt+="<input type='slider' name='self.main.volume_sliders' index='%s' />" %(counter) + + txt+="</div>" + self.datatxt.insert_html(txt) + counter+=1 + + if tcos_vars["get_client"] == "tcos": + # PulseAudio utils + self.main.openvolumecontrol_button=None + self.main.openvolumecontrol_button=gtk.Button(label=_("PulseAudio Control") ) + self.main.openvolumecontrol_button.connect("clicked", self.on_openvolumecontrol_button_click, ip) + self.main.openvolumecontrol_button.show() + + self.main.openvolumemeter_button=None + self.main.openvolumemeter_button=gtk.Button(label=_("PulseAudio Meter") ) + self.main.openvolumemeter_button.connect("clicked", self.on_openvolumemeter_button_click, ip) + self.main.openvolumemeter_button.show() + + self.main.volumemanager_button=None + self.main.volumemanager_button=gtk.Button(label=_("PulseAudio Manager") ) + self.main.volumemanager_button.connect("clicked", self.on_volumemanager_button_click, ip) + self.main.volumemanager_button.show() + + self.datatxt.insert_block(_("PulseAudio utils: ") + """ + <input type='button' name='self.main.volumemanager_button' /> + <input type='button' name='self.main.openvolumecontrol_button' /> + <input type='button' name='self.main.openvolumemeter_button' /> + """) + + self.datatxt.insert_block( _("PulseAudio stats") ) + pulseaudioinfo=self.main.xmlrpc.GetSoundInfo(channel="", mode="--getserverinfo").split('|') + #print pulseaudioinfo + allpulseaudioinfo=[] + allpulseaudioinfo_trans=[] + output=[] + for line in pulseaudioinfo: + if line != "" and line.find(":") != -1: + key, value = line.split(':') + allpulseaudioinfo.append([ key+":", value ]) + allpulseaudioinfo_trans.append(value) + if len(allpulseaudioinfo_trans) == 11: + output.append( ["%s:" %( _("Currently in use")), allpulseaudioinfo_trans[0] ]) + output.append( ["%s:" %( _("Allocated during whole lifetime")), allpulseaudioinfo_trans[1] ]) + output.append( ["%s:" %( _("Sample cache size")), allpulseaudioinfo_trans[2] ]) + output.append( ["%s:" %( _("User name")), allpulseaudioinfo_trans[3] ]) + output.append( ["%s:" %( _("Host Name")), allpulseaudioinfo_trans[4] ]) + output.append( ["%s:" %( _("Server Name")), allpulseaudioinfo_trans[5] ]) + output.append( ["%s:" %( _("Server Version")), allpulseaudioinfo_trans[6] ]) + output.append( ["%s:" %( _("Default Sample Specification")), allpulseaudioinfo_trans[7] ]) + output.append( ["%s:" %( _("Default Sink")), allpulseaudioinfo_trans[8] ]) + output.append( ["%s:" %( _("Default Source")), allpulseaudioinfo_trans[9] ]) + output.append( ["%s:" %( _("Cookie")), allpulseaudioinfo_trans[10] ]) + self.datatxt.insert_list( output ) + else: + self.datatxt.insert_list( allpulseaudioinfo ) + + else: + self.datatxt.insert_block ( _("Sound server is not running"), image=shared.IMG_DIR + "info_sound_ko.png") + + self.main.common.threads_enter("TcosActions:populate_datatxt end") + self.datatxt.display() + self.main.actions.update_progressbar( 1 ) + self.main.progressbar.hide() + + if shared.disable_textview_on_update and self.main.iconview.isactive(): + self.main.tabla.set_sensitive(True) + + self.main.common.threads_leave("TcosActions:populate_datatxt end") + + crono(start1, "populate_datatxt(%s)" %(ip) ) + return False + + def on_downloadallmodules_click(self, widget): + print_debug ( "on_downloadallmodules_click() ################" ) + if self.main.selected_ip != None: + print_debug( "on_downloadallmodules_click() downloading modules for %s" %(self.main.selected_ip) ) + # download allmodules.squashfs and mount it + self.main.xmlrpc.Exe("useallmodules.sh") + return + + + def slider_value_changed(self, widget, adjustment, event, channel, ip): + value=widget.get_value() + print_debug ( "slider_value_changed() ip=%s channel=%s value=%s" %(ip, channel, value) ) + + self.main.write_into_statusbar( \ + _("Changing value of %(channel)s channel, to %(value)s%%..." )\ + %{"channel":channel, "value":value} ) + + tmp=self.main.xmlrpc.SetSound(ip, channel, str(value)+"%") + newvalue="%2d%%"%int(tmp['level']) + + self.main.write_into_statusbar( \ + _("Changed value of %(channel)s channel, to %(value)s" ) \ + %{"channel":channel, "value":newvalue} ) + + def checkbox_value_changed(self, widget, channel, ip): + value=widget.get_active() + if not value: + value="off" + self.main.write_into_statusbar( _("Unmuting %s channel..." ) %(channel) ) + tmp=self.main.xmlrpc.SetSound(ip, channel, value="", mode="--setunmute") + newvalue=tmp['mute'] + else: + value="on" + self.main.write_into_statusbar( _("Muting %s channel..." ) %(channel) ) + tmp=self.main.xmlrpc.SetSound(ip, channel, value="", mode="--setmute") + newvalue=tmp['mute'] + self.main.write_into_statusbar( _("Status of %(channel)s channel, is \"%(newvalue)s\"" )\ + %{"channel":channel, "newvalue":newvalue} ) + + + def on_openvolumecontrol_button_click(self, widget, ip): + print_debug ( "on_openvolumecontrol_button_click() ip=%s" %(ip) ) + cmd="PULSE_SERVER=\"%s\" pavucontrol" %(ip) + if os.path.isdir("/dev/shm"): + self.main.common.exe_cmd( cmd, verbose=0, background=True ) + else: + shared.error_msg ( _("PulseAudio apps need /dev/shm.") ) + + def on_openvolumemeter_button_click(self, widget, ip): + print_debug ( "on_openvolumemeter_button_click() ip=%s" %(ip) ) + cmd="PULSE_SERVER=\"%s\" pavumeter" %(ip) + if os.path.isdir("/dev/shm"): + self.main.common.exe_cmd( cmd, verbose=0, background=True ) + else: + shared.error_msg ( _("PulseAudio apps need /dev/shm.") ) + + def on_volumemanager_button_click(self, widget, ip): + print_debug ( "on_volumemanager_button_click() ip=%s" %(ip) ) + cmd="PULSE_SERVER=\"%s\" paman" %(ip) + if os.path.isdir("/dev/shm"): + self.main.common.exe_cmd( cmd, verbose=0, background=True ) + else: + shared.error_msg ( _("PulseAudio apps need /dev/shm.") ) + + + +__extclass__=Info + + + + + + + + diff --git a/tcosmonitor/extensions/italc.py b/tcosmonitor/extensions/italc.py new file mode 100644 index 0000000..00bfe59 --- /dev/null +++ b/tcosmonitor/extensions/italc.py @@ -0,0 +1,88 @@ +# -*- coding: UTF-8 -*- +# TcosMonitor version __VERSION__ +# +# Copyright (c) 2006-2011 Mario Izquierdo <mariodebian@gmail.com> +# +# This package is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# +# This package is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +""" template extension """ + +from gettext import gettext as _ +from time import sleep +import sys + +from tcosmonitor import shared +from tcosmonitor.TcosExtensions import TcosExtension + + +def print_debug(txt): + if shared.debug: + print >> sys.stderr, "%s::%s" % (__name__, txt) + #print("%s::%s" % (__name__, txt), file=sys.stderr) + + +class iTalc(TcosExtension): + def register(self): + self.main.menus.register_simple( _("Connect to remote screen (iTALC)"), "menu_remote.png", 1, self.ivs, "italc") + + + def ivs(self, w, ip): + if not self.get_client(): + return + + if len(self.allclients_logged) == 0: + shared.error_msg( _("No user logged.") ) + return + + self.main.worker=shared.Workers(self.main, target=self.start_ivs, args=(self.allclients_logged) ) + self.main.worker.start() + + def start_ivs(self, ip): + self.main.xmlrpc.newhost(ip) + # check if remote proc is running + if not self.main.xmlrpc.GetStatus("ivs"): + self.main.common.threads_enter("TcosActions:start_ivs write connecting msg") + self.main.write_into_statusbar( "Connecting with %s to start iTALC support" %(ip) ) + self.main.common.threads_leave("TcosActions:start_ivs write connecting msg") + + try: + self.main.xmlrpc.newhost(ip) + self.main.xmlrpc.Exe("startivs") + self.main.common.threads_enter("TcosActions:start_ivs write waiting msg") + self.main.write_into_statusbar( "Waiting for start of IVS server..." ) + self.main.common.threads_leave("TcosActions:start_ivs write waiting msg") + sleep(5) + except Exception, err: + print_debug("start_ivs() Exception, error=%s"%err) + self.main.common.threads_enter("TcosActions:start_ivs write error msg") + shared.error_msg ( _("Can't start IVS, please add iTALC support") ) + self.main.common.threads_leave("TcosActions:start_ivs write error msg") + return + + cmd = "icv " + ip + " root" + print_debug ( "start_process() threading \"%s\"" %(cmd) ) + self.main.common.exe_cmd (cmd, verbose=0, background=True) + + self.main.common.threads_enter("TcosActions:start_ivs END") + self.main.write_into_statusbar( "" ) + self.main.common.threads_leave("TcosActions:start_ivs END") + +__extclass__=iTalc + + + + + + diff --git a/tcosmonitor/extensions/livevnc.py b/tcosmonitor/extensions/livevnc.py new file mode 100644 index 0000000..cfbc511 --- /dev/null +++ b/tcosmonitor/extensions/livevnc.py @@ -0,0 +1,220 @@ +# -*- coding: UTF-8 -*- +# TcosMonitor version __VERSION__ +# +# Copyright (c) 2006-2011 Mario Izquierdo <mariodebian@gmail.com> +# +# This package is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# +# This package is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +from gettext import gettext as _ + + +import gtk +import sys + +# needed for get_screenshot +from time import sleep + +from tcosmonitor import shared +from tcosmonitor.TcosExtensions import TcosExtension +from tcosmonitor.ping import PingPort + +import gtkvnc +from random import Random +import string + +def print_debug(txt): + if shared.debug: + print >> sys.stderr, "%s::%s" % (__name__, txt) + #print("%s::%s" % (__name__, txt), file=sys.stderr) + + + +class LiveVNC(TcosExtension): + def register(self): + self.main.menus.register_all( _("Live view screens with VNC") , "menu_remote.png", 1, self.live_all, "livevnc") + self.main.livevnc={} + self.vncpasswd="" + self.vncxres={} + self.main.triggers['clean.datatxt']=self.__cleandatatxt + self.main.stop_liveview_button=None + + ########### MULTIPLE HOSTS ############### + + def live_all(self, widget): + if not self.get_all_clients(): + return + self.vncpasswd=''.join( Random().sample(string.letters+string.digits, 12) ) + + self.main.worker=shared.Workers(self.main, None, None) + self.main.worker.set_for_all_action(self.action_for_clients, self.allclients, 'livevnc' ) + + + def start_action(self, *args): + print_debug("START_ACTION") + self.main.datatxt.clean() + self.main.stop_liveview_button=gtk.Button(_("Stop") ) + self.main.stop_liveview_button.connect("clicked", self.__cleandatatxt, 'force') + self.main.stop_liveview_button.show() + + self.main.datatxt.insert_block( _("Live view of all hosts") ) + #"""<span> </span><input type='button' name="self.main.stop_liveview_button" />""" ) + self.main.datatxt.insert_html("<br/>") + + def real_action(self, ip, action): + #print_debug("real_action() ip=%s self.main.livevnc=%s" %(ip, self.main.livevnc) ) + max_wait=10 + + + # generate pass on client + #self.main.xmlrpc.newhost(ip) + self.main.xmlrpc.vnc("genpass", ip, self.vncpasswd) + + + # start x11vnc + result=self.main.xmlrpc.vnc("startscale", ip) + print_debug("real_action() start remote x11vnc result=%s"%result) + if result.find("error") != -1: + return + + # wait for start + status = "CLOSED" + + wait=0 + while status != "OPEN": + status=PingPort(ip, 5900).get_status() + if status == "CLOSED": + sleep(1) + wait+=1 + if wait > max_wait: + break + + # start vnc and save in self.main.vnc dict + self.main.livevnc[ip]=gtkvnc.Display() + self.main.livevnc[ip].set_credential(gtkvnc.CREDENTIAL_PASSWORD, self.vncpasswd) + self.main.livevnc[ip].set_credential(gtkvnc.CREDENTIAL_CLIENTNAME, self.main.name) + + self.main.livevnc[ip].connect("vnc-auth-credential", self._vnc_auth_cred, ip) + #self.main.livevnc[ip].connect("size-request", self._force_resize, ip) + self.main.livevnc[ip].connect("vnc-connected", self._vnc_connected, ip) + #self.main.livevnc[ip].connect("clicked", self._vnc_clicked, ip) + self.main.livevnc[ip].connect("button-press-event", self.on_iconview_click, ip) + # this freeze GUI + #self.main.livevnc[ip].set_tooltip_text("%s"%ip) + + #print dir(self.main.livevnc[ip]) + + print_debug("real_action() vnc started!!! ") + + def _vnc_clicked(self, vnc, ip): + print_debug("_vnc_clicked() vnc=%s ip=%s"%(vnc, ip)) + + + def on_iconview_click(self, widget, event, ip): + if event.button == 3: + self.main.force_selected_ip=ip + # right click show menu + self.main.menus.RightClickMenuOne( None , None, ip) + self.main.menu.popup( None, None, None, event.button, event.time) + return True + + + def _vnc_auth_cred(self, *args): + #print_debug("vnc_auth_cred() args=%s"%args) + return + + + def _force_resize(self, src, size, ip): + #print_debug("_force_resize() src=%s size=%s ip=%s"%(src, size, ip)) + w, h = src.get_size_request() + #print "_force_resize() w=%s h=%s"%(w, h) + if w == -1 or h == -1: + print_debug("_force_resize() returning w=%s h=%s ip=%s"%(w, h, ip)) + return + width=300 + height=200 + if self.vncxres.has_key(ip): + # cached data + width=self.vncxres[ip][0] + height=self.vncxres[ip][1] + else: + self.vncxres[ip]=[width, height] + try: + screensize=self.main.xmlrpc.ReadInfo("screensize") + if screensize != '': + width=int(screensize.split('x')[0]) * 100 / int(self.main.config.GetVar("miniscrot_size")) + height=int(screensize.split('x')[1]) * 100 / int(self.main.config.GetVar("miniscrot_size")) + self.vncxres[ip]=[width, height] + print_debug("_force_resize() RESIZE w=%s h=%s"%(width, height)) + except Exception, err: + print_debug("_force_resize() Exception err=%s"%err) + width=300 + height=200 + self.vncxres[ip]=[width, height] + self.main.livevnc[ip].set_size_request(self.vncxres[ip][0], self.vncxres[ip][1]) + + + def _vnc_connected(self, vnc, ip): + print_debug("_vnc_connected() vnc=%s livevnc[ip]=%s ip=%s"%(vnc, self.main.livevnc[ip], ip)) + self.main.livevnc[ip].show() + self.main.livevnc[ip].realize() + + + def finish_action(self, *args): + for ip in self.main.livevnc: + #self.main.livevnc[ip] + hostname=self.main.localdata.GetUsername(ip) + if hostname == shared.NO_LOGIN_MSG: + hostname=self.main.localdata.GetHostname(ip) + self.main.datatxt.insert_html( + "<span style='background-color:#f3d160'>" + + "\n\t<livevnc ip='%s' objdict='livevnc' title='%s' title_rotate='90'/> " %(ip, hostname) + + "<span style='background-color:#f3d160; color:#f3d160'>__</span>\n</span>"+ + "") + self.main.livevnc[ip].open_host(ip, '5900') + #self.main.livevnc[ip].set_scaling(True) + self.main.livevnc[ip].set_read_only(True) + self.main.livevnc[ip].show() + # draw widgets + self.main.datatxt.display() + stopargs={"target": "livevnc"} + self.add_progressbox( stopargs, _("Running in LiveView mode") ) + + def on_progressbox_click(self, widget, args, box): + try: + box.destroy() + except: + pass + self.__cleandatatxt(None, 'force') + + + + def __cleandatatxt(self, *args): + # stop all livevnc connections + for ip in self.main.livevnc: + print_debug("__cleandatatxt() STOPPING ip=%s"%ip) + self.main.livevnc[ip].close() + # stop server (don't wait) + self.main.xmlrpc.vnc("stopserver", ip ) + self.main.livevnc={} + + if len(args) == 2 and args[1] == 'force': + self.main.datatxt.clean() + self.main.stop_liveview_button=None + + + +__extclass__=LiveVNC + diff --git a/tcosmonitor/extensions/lockscreen.py b/tcosmonitor/extensions/lockscreen.py new file mode 100644 index 0000000..02b8317 --- /dev/null +++ b/tcosmonitor/extensions/lockscreen.py @@ -0,0 +1,100 @@ +# -*- coding: UTF-8 -*- +# TcosMonitor version __VERSION__ +# +# Copyright (c) 2006-2011 Mario Izquierdo <mariodebian@gmail.com> +# +# This package is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# +# This package is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +""" template extension """ + +from gettext import gettext as _ +import sys + +from tcosmonitor import shared +from tcosmonitor.TcosExtensions import TcosExtension + + +def print_debug(txt): + if shared.debug: + print >> sys.stderr, "%s::%s" % (__name__, txt) + #print("%s::%s" % (__name__, txt), file=sys.stderr) + + +class LockUnlockScreen(TcosExtension): + def register(self): + self.main.menus.register_simple( _("Lock screen"), "menu_lock.png", 0, self.lock, "lock") + self.main.menus.register_all( _("Lock all screens"), "menu_lock.png", 0, self.lock_all, "lock") + self.main.menus.register_simple( _("Unlock screen"), "menu_unlock.png", 0, self.unlock, "lock") + self.main.menus.register_all( _("Unlock all screens"), "menu_unlock.png", 0, self.unlock_all, "lock") + + def lock(self, w, ip): + if not self.get_client(): + return + if not self.main.xmlrpc.lockscreen(): + shared.error_msg( _("Can't connect to tcosxmlrpc.\nPlease verify user and password in prefences!") ) + return + self.change_lockscreen(ip) + + def unlock(self, w, ip): + if not self.get_client(): + return + if not self.main.xmlrpc.unlockscreen(): + shared.error_msg( _("Can't connect to tcosxmlrpc.\nPlease verify user and password in prefences!") ) + return + self.change_lockscreen(ip) + + def real_action(self, ip, action): + print_debug("real_action() ip=%s action='%s'"%(ip, action) ) + + if action == 'lockscreen': + self.main.xmlrpc.lockscreen() + # update icon + self.main.common.threads_enter("extensions/lockscreen::real_action lockscreen") + self.change_lockscreen(ip) + self.main.common.threads_leave("extensions/lockscreen::real_action lockscreen") + elif action == 'unlockscreen': + self.main.xmlrpc.unlockscreen() + # update icon + self.main.common.threads_enter("extensions/lockscreen::real_action unlockscreen") + self.change_lockscreen(ip) + self.main.common.threads_leave("extensions/lockscreen::real_action unlockscreen") + + + def lock_all(self, *args): + if not self.get_all_clients(): + return + msg=_( _("Do you want to lock the following screens: %s?" )%(self.connected_users_txt_all) ) + if shared.ask_msg ( msg ): + self.main.worker=shared.Workers(self.main, None, None) + self.main.worker.set_for_all_action(self.action_for_clients, \ + self.allclients_logged, "lockscreen" ) + + def unlock_all(self, *args): + if not self.get_all_clients(): + return + msg=_( _("Do you want to unlock the following screens: %s?" )%(self.connected_users_txt_all) ) + if shared.ask_msg ( msg ): + self.main.worker=shared.Workers(self.main, None, None) + self.main.worker.set_for_all_action(self.action_for_clients, \ + self.allclients_logged, "unlockscreen" ) + + +__extclass__=LockUnlockScreen + + + + + + diff --git a/tcosmonitor/extensions/logout.py b/tcosmonitor/extensions/logout.py new file mode 100644 index 0000000..bab6441 --- /dev/null +++ b/tcosmonitor/extensions/logout.py @@ -0,0 +1,94 @@ +# -*- coding: UTF-8 -*- +# TcosMonitor version __VERSION__ +# +# Copyright (c) 2006-2011 Mario Izquierdo <mariodebian@gmail.com> +# +# This package is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# +# This package is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +""" template extension """ + +from gettext import gettext as _ +import sys + +from tcosmonitor import shared +from tcosmonitor.TcosExtensions import TcosExtension + + +def print_debug(txt): + if shared.debug: + print >> sys.stderr, "%s::%s" % (__name__, txt) + #print("%s::%s" % (__name__, txt), file=sys.stderr) + + +class LogOut(TcosExtension): + def register(self): + self.main.menus.register_simple( _("Logout client"), "menu_restartx.png", 0, self.logout, "restartx") + self.main.menus.register_all( _("Logout clients"), "menu_restartx.png" , 0, self.logout_all, "restartx") + + + def logout(self, w, ip): + if not self.get_client(): + return + if len(self.connected_users) == 0 or self.connected_users[0] == shared.NO_LOGIN_MSG: + shared.error_msg ( _("User not logged") ) + return + + msg=_( _("Do you want to logout user: %s?" ) %(self.connected_users_txt) ) + if shared.ask_msg ( msg ): + newusernames=[] + timeout=self.main.config.GetVar("actions_timeout") + msg=_("Session will close in %s seconds") %timeout + remote_cmd="/usr/lib/tcos/session-cmd-send LOGOUT %s %s" %(timeout, msg.replace("'", "´")) + + if self.connected_users[0].find(":") != -1: + # we have a standalone user... + self.main.xmlrpc.DBus("exec", remote_cmd ) + else: + newusernames.append(self.connected_users[0]) + + self.main.dbus_action.do_exec(newusernames, remote_cmd ) + + def logout_all(self, widget): + if not self.get_all_clients(): + return + + if len(self.connected_users) == 0 or self.connected_users[0] == shared.NO_LOGIN_MSG: + shared.error_msg ( _("User not logged") ) + return + msg=_( _("Do you want to logout the following users: %s?" )%(self.connected_users_txt) ) + if shared.ask_msg ( msg ): + newusernames=[] + timeout=self.main.config.GetVar("actions_timeout") + msg=_("Session will close in %s seconds") %timeout + remote_cmd="/usr/lib/tcos/session-cmd-send LOGOUT %s %s" %(timeout, msg.replace("'", "´")) + + for user in self.connected_users: + if user.find(":") != -1: + # we have a standalone user... + usern, ip = user.split(":") + self.main.xmlrpc.newhost(ip) + self.main.xmlrpc.DBus("exec", remote_cmd ) + else: + newusernames.append(user) + + self.main.dbus_action.do_exec( newusernames, remote_cmd ) + +__extclass__=LogOut + + + + + + diff --git a/tcosmonitor/extensions/reboot.py b/tcosmonitor/extensions/reboot.py new file mode 100644 index 0000000..be943cb --- /dev/null +++ b/tcosmonitor/extensions/reboot.py @@ -0,0 +1,120 @@ +# -*- coding: UTF-8 -*- +# TcosMonitor version __VERSION__ +# +# Copyright (c) 2006-2011 Mario Izquierdo <mariodebian@gmail.com> +# +# This package is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# +# This package is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +""" template extension """ + +from gettext import gettext as _ +import sys + +from tcosmonitor import shared +from tcosmonitor.TcosExtensions import TcosExtension + + +def print_debug(txt): + if shared.debug: + print >> sys.stderr, "%s::%s" % (__name__, txt) + #print("%s::%s" % (__name__, txt), file=sys.stderr) + + +class RebootPoweroff(TcosExtension): + def register(self): + self.main.menus.register_simple(_("Reboot"), "menu_reboot.png", 0, self.reboot, "reboot") + self.main.menus.register_all( _("Reboot all clients"), "menu_reboot.png", 0, self.reboot_all, "reboot") + self.main.menus.register_simple( _("Poweroff"), "menu_poweroff.png", 0, self.poweroff, "reboot") + self.main.menus.register_all( _("Poweroff all clients"), "menu_poweroff.png", 0, self.poweroff_all, "reboot") + + def reboot(self, w, ip): + if not self.get_client(): + return + msg=_( _("Do you want to reboot: %s?" ) %(self.connected_users_txt_all) ) + if shared.ask_msg ( msg ): + timeout=self.main.config.GetVar("actions_timeout") + msg=(_("Pc will reboot in %s seconds") %timeout) + self.exe_app_in_client("reboot", timeout, msg, users=[ip], connected_users=self.connected_users) + + + def reboot_all(self, *args): + if not self.get_all_clients(): + return + msg=_( _("Do you want to reboot the following clients: %s?" ) %(self.connected_users_txt_all) ) + if shared.ask_msg ( msg ): + timeout=self.main.config.GetVar("actions_timeout") + msg=(_("Pc will reboot in %s seconds") %timeout) + self.exe_app_in_client("reboot", timeout, msg, users=self.allclients, connected_users=self.connected_users) + + def poweroff(self, w, ip): + if not self.get_client(): + return + msg=_( _("Do you want to poweroff: %s?" ) %(self.connected_users_txt_all) ) + if shared.ask_msg ( msg ): + timeout=self.main.config.GetVar("actions_timeout") + msg=(_("Pc will shutdown in %s seconds") %timeout) + self.exe_app_in_client("poweroff", timeout, msg, users=[ip], connected_users=self.connected_users) + + + def poweroff_all(self, *args): + if not self.get_all_clients(): + return + msg=_( _("Do you want to poweroff the following clients: %s?" )%(self.connected_users_txt_all) ) + if shared.ask_msg ( msg ): + timeout=self.main.config.GetVar("actions_timeout") + msg=(_("Pc will shutdown in %s seconds") %timeout) + self.exe_app_in_client("poweroff", timeout, msg, users=self.allclients, connected_users=self.connected_users) + + def real_action(self, ip, action): + print_debug("real_action() ip=%s action='%s'"%(ip, action) ) + self.main.xmlrpc.Exe(action) + + + def exe_app_in_client(self, mode, timeout=0, msg="", users=[], connected_users=[]): + remote_cmd=("/usr/lib/tcos/session-cmd-send %s %s %s" %(mode.upper(), timeout, msg.replace("'", "´"))) + action="down-controller %s %s" %(mode, timeout) + print_debug("exe_app_in_client() usernames=%s" %users) + + if len(connected_users) != 0 and connected_users[0] != shared.NO_LOGIN_MSG: + newusernames=[] + for user in connected_users: + if user.find(":") != -1: + # we have a standalone user... + usern, ip = user.split(":") + self.main.xmlrpc.newhost(ip) + self.main.xmlrpc.DBus("exec", remote_cmd ) + else: + # we have a thin client + newusernames.append(user) + + result = self.main.dbus_action.do_exec( newusernames, remote_cmd ) + + if not result: + shared.error_msg ( _("Error while exec remote app:\nReason:%s") %( self.main.dbus_action.get_error_msg() ) ) + + self.main.worker=shared.Workers(self.main, None, None) + self.main.worker.set_for_all_action(self.action_for_clients, users, action ) + return + + + + +__extclass__=RebootPoweroff + + + + + + diff --git a/tcosmonitor/extensions/remotessh.py b/tcosmonitor/extensions/remotessh.py new file mode 100644 index 0000000..bafd35b --- /dev/null +++ b/tcosmonitor/extensions/remotessh.py @@ -0,0 +1,57 @@ +# -*- coding: UTF-8 -*- +# TcosMonitor version __VERSION__ +# +# Copyright (c) 2006-2011 Mario Izquierdo <mariodebian@gmail.com> +# +# This package is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# +# This package is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +""" template extension """ + +from gettext import gettext as _ +import sys + +from tcosmonitor import shared +from tcosmonitor.TcosExtensions import TcosExtension + + +def print_debug(txt): + if shared.debug: + print >> sys.stderr, "%s::%s" % (__name__, txt) + #print("%s::%s" % (__name__, txt), file=sys.stderr) + + +class RemoteSSH(TcosExtension): + def register(self): + self.main.menus.register_simple( _("Give a remote xterm"), "menu_xterm.png", 0, self.remotessh, "shell") + + + def remotessh(self, w, ip): + if not self.get_client(): + return + # give a remote xterm throught SSH + pass_msg=_("Enter password of remote thin client (if asked for it)") + cmd="xterm -e \"echo '%s'; ssh %s@%s || sleep 5\"" %(pass_msg, self.main.config.GetVar("ssh_remote_username"),ip) + print_debug ( "remotessh() cmd=%s" %(cmd) ) + th=self.main.common.exe_cmd( cmd, verbose=0, background=True ) + + + +__extclass__=RemoteSSH + + + + + + diff --git a/tcosmonitor/extensions/restartxorg.py b/tcosmonitor/extensions/restartxorg.py new file mode 100644 index 0000000..5f3420f --- /dev/null +++ b/tcosmonitor/extensions/restartxorg.py @@ -0,0 +1,194 @@ +# -*- coding: UTF-8 -*- +# TcosMonitor version __VERSION__ +# +# Copyright (c) 2006-2011 Mario Izquierdo <mariodebian@gmail.com> +# +# This package is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# +# This package is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +""" template extension """ + +from gettext import gettext as _ +import gtk +import sys + +from tcosmonitor import shared +from tcosmonitor.TcosExtensions import TcosExtension + + +def print_debug(txt): + if shared.debug: + print >> sys.stderr, "%s::%s" % (__name__, txt) + #print("%s::%s" % (__name__, txt), file=sys.stderr) + + +class RestartXorg(TcosExtension): + def register(self): + self.main.menus.register_simple( _("Restart X session with new settings"), "menu_newconf.png", 0, self.restartx, "xorg") + self.main.menus.register_all( _("Restart X session of all clients"), "menu_newconf.png" , 0, self.restartx_all, "xorg") + + + def restartx(self, w, ip): + if not self.get_client(): + return + # restart xorg with new settings + # thin client must download again XXX.XXX.XXX.XXX.conf and rebuild xorg.conf + if self.client_type == "tcos": + msg=_( "Restart X session of %s with new config?" ) %(self.host) + if shared.ask_msg ( msg ): + # see xmlrpc/xorg.h, rebuild will download and sed xorg.conf.tpl + try: + self.main.xmlrpc.tc.tcos.xorg("rebuild", "--restartxorg", \ + self.main.config.GetVar("xmlrpc_username"), \ + self.main.config.GetVar("xmlrpc_password") ) + except Exception, err: + print_debug("restartx() Exception error %s"%err) + self.main.xmlrpc.CheckSSL(err) + + self.refresh_client_info(ip) + else: + shared.info_msg( _("%s is not supported to restart Xorg!") %(self.client_type) ) + + def restartx_all(self, widget): + if not self.get_all_clients(): + return + onlythinclients=[] + onlythinclients_txt="" + + for client in self.allclients: + if not self.main.xmlrpc.IsStandalone(client): + onlythinclients.append(client) + onlythinclients_txt+="\n %s" %(client) + + if len(onlythinclients) == 0: + shared.error_msg( _("No thin clients found.") ) + return + + msg=_( _("Do you want to restart X screens (only thin clients):%s?" )%(onlythinclients_txt) ) + if shared.ask_msg ( msg ): + self.main.worker=shared.Workers(self.main, None, None) + self.main.worker.set_for_all_action(self.action_for_clients, onlythinclients, "restartx" ) + + + def real_action(self, ip, action): + print_debug("real_action() ip=%s action='%s'"%(ip, action) ) + self.main.xmlrpc.Exe(action) + + + def refresh_client_info(self, ip): + print_debug ( "refresh_client_info() updating host data..." ) + + inactive_image = gtk.gdk.pixbuf_new_from_file(shared.IMG_DIR + 'inactive.png') + active_image = gtk.gdk.pixbuf_new_from_file(shared.IMG_DIR + 'active.png') + active_ssl_image = gtk.gdk.pixbuf_new_from_file(shared.IMG_DIR + 'active_ssl.png') + + logged_image = gtk.gdk.pixbuf_new_from_file(shared.IMG_DIR + 'logged.png') + unlogged_image = gtk.gdk.pixbuf_new_from_file(shared.IMG_DIR + 'unlogged.png') + + locked_image = gtk.gdk.pixbuf_new_from_file(shared.IMG_DIR + 'locked.png') + locked_net_image = gtk.gdk.pixbuf_new_from_file(shared.IMG_DIR + 'locked_net.png') + locked_net_screen_image = gtk.gdk.pixbuf_new_from_file(shared.IMG_DIR + 'locked_net_screen.png') + unlocked_image = gtk.gdk.pixbuf_new_from_file(shared.IMG_DIR + 'unlocked.png') + dpms_off_image = gtk.gdk.pixbuf_new_from_file(shared.IMG_DIR + 'menu_dpms_off.png') + dpms_on_image = gtk.gdk.pixbuf_new_from_file(shared.IMG_DIR + 'menu_dpms_on.png') + + # disable cache + self.main.localdata.cache_timeout=0 + + data={} + data['ip']=ip + print_debug("refresh_client_info() => get username") + data['username']=self.main.localdata.GetUsername(ip) + + print_debug("refresh_client_info() => get hostname") + data['hostname']=self.main.localdata.GetHostname(ip) + + if data['username'].startswith('error: tcos-last'): + data['username']="---" + + try: + print_debug("refresh_client_info() => get num process") + data['num_process']=self.main.localdata.GetNumProcess(ip) + except Exception, err: + print_debug("refresh_client_info() Exception error=%s"%err) + data['num_process']="---" + + print_debug("refresh_client_info() => get time logged") + data['time_logged']=self.main.localdata.GetTimeLogged(ip) + + if not data['time_logged'] or data['time_logged'] == "" or data['time_logged'].startswith('error: tcos-last'): + data['time_logged']="---" + + print_debug("refresh_client_info() => get active connection") + if self.main.localdata.IsActive(ip): + if self.main.xmlrpc.sslconnection: + data['image_active']=active_ssl_image + else: + data['image_active']=active_image + else: + data['image_active']=inactive_image + + print_debug("refresh_client_info() => get is logged") + if self.main.localdata.IsLogged(ip): + data['image_logged']=logged_image + else: + data['image_logged']=unlogged_image + + print_debug("refresh_client_info() => get is blocked") + if self.main.localdata.IsBlocked(ip): + data['blocked_screen']=True + else: + data['blocked_screen']=False + + print_debug("refresh_client_info() => get is blocked net") + if self.main.localdata.IsBlockedNet(ip, data['username']): + data['blocked_net']=True + else: + data['blocked_net']=False + + if self.main.xmlrpc.dpms('status', ip) == "Off": + data['dpms_off']=True + else: + data['dpms_off']=False + + if data['dpms_off']: + data['image_blocked']=dpms_off_image + elif data['blocked_screen'] and data['blocked_net']: + data['image_blocked']=locked_net_screen_image + elif data['blocked_screen'] == False and data['blocked_net']: + data['image_blocked']=locked_net_image + elif data['blocked_screen'] and data['blocked_net'] == False: + data['image_blocked']=locked_image + else: + data['image_blocked']=unlocked_image + + #enable cache again + self.main.localdata.cache_timeout=shared.cache_timeout + + if self.main.classview.isactive(): + self.main.classview.change_lockscreen(ip, data['image_blocked'], data['blocked_screen'], data['blocked_net']) + if self.main.iconview.isactive(): + self.main.iconview.change_lockscreen(ip, data['image_blocked'], data['blocked_screen'], data['blocked_net']) + if self.main.listview.isactive(): + self.main.listview.refresh_client_info(ip, data['image_blocked']) + + + +__extclass__=RestartXorg + + + + + + diff --git a/tcosmonitor/extensions/screenshot.py b/tcosmonitor/extensions/screenshot.py new file mode 100644 index 0000000..96dce48 --- /dev/null +++ b/tcosmonitor/extensions/screenshot.py @@ -0,0 +1,225 @@ +# -*- coding: UTF-8 -*- +# TcosMonitor version __VERSION__ +# +# Copyright (c) 2006-2011 Mario Izquierdo <mariodebian@gmail.com> +# +# This package is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# +# This package is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +from gettext import gettext as _ + + +# needed for get_screenshot +from time import localtime +import gtk +import os +import sys + +from tcosmonitor import shared +from tcosmonitor.TcosExtensions import TcosExtension + + +def print_debug(txt): + if shared.debug: + print >> sys.stderr, "%s::%s" % (__name__, txt) + #print("%s::%s" % (__name__, txt), file=sys.stderr) + + +class Screenshot(TcosExtension): + def register(self): + self.main.menus.register_simple( _("Screenshot"), "menu_screenshot.png", 2, self.take_screenshot, "screenshots") + self.main.menus.register_all( _("Capture All clients screens") , "menu_screenshot.png", 2, self.take_all_screenshots, "screenshots") + self.main.screenshots_action=None + self.__screenshot_counter=0 + self.__screenshot_data={} + + ########### SIMPLE HOST ############### + + def take_screenshot(self, widget, ip): + if not self.get_client(): + return + print_debug("take_screenshot() widget=%s ip=%s"%(widget, ip)) + + self.main.worker=shared.Workers(self.main, target=self.get_screenshot, args=(ip,) ) + self.main.worker.start() + + def get_screenshot(self, ip): + self.main.xmlrpc.newhost(ip) + if not self.main.xmlrpc.connected: + print_debug ( "get_screenshot(%s) NO CONNECTION" %(ip) ) + self.main.common.threads_enter("TcosActions::get_screenshot writing error msg") + self.main.write_into_statusbar( _("Can't make screenshot, error: %s") %"NO CONNECTION" ) + self.main.common.threads_leave("TcosActions::get_screenshot writing error msg") + return + + # get_size + print_debug ( "get_screenshot() scrot_size=%s" %(self.main.config.GetVar("scrot_size")) ) + + # write into statusbar + self.main.common.threads_enter("TcosActions::get_screenshot writing wait msg") + self.main.write_into_statusbar ( _("Trying to order terminal to do a screenshot...") ) + self.main.common.threads_leave("TcosActions::get_screenshot writing wait msg") + + # use Base64 screenshot + scrot=self.main.xmlrpc.getscreenshot( self.main.config.GetVar("scrot_size") ) + if scrot[0] != "ok": + #if not self.main.xmlrpc.screenshot( self.main.config.GetVar("scrot_size") ): + self.main.common.threads_enter("TcosActions::get_screenshot writing error msg") + self.main.write_into_statusbar( _("Can't make screenshot, error: %s") %scrot[1] ) + self.main.common.threads_leave("TcosActions::get_screenshot writing error msg") + return False + + slabel=_("Get another screenshot") + self.main.common.threads_enter("TcosActions::get_screenshot creating button") + self.main.another_screenshot_button=None + self.main.another_screenshot_button=gtk.Button(label=slabel ) + self.main.another_screenshot_button.connect("clicked", self.take_screenshot, ip) + self.main.another_screenshot_button.show() + self.main.common.threads_leave("TcosActions::get_screenshot creating button") + + + print_debug ( "get_screenshot() creating button..." ) + year, month, day, hour, minute, seconds ,wdy, yday, isdst= localtime() + datetxt="%02d/%02d/%4d %02d:%02d:%02d" %(day, month, year, hour, minute, seconds) + print_debug ( "get_screenshot() date=%s" %(datetxt) ) + + hostname=self.main.localdata.GetUsername(ip) + if hostname == shared.NO_LOGIN_MSG: + hostname=self.main.localdata.GetHostname(ip) + block_txt=_("Screenshot of <span style='font-style: italic'>%s</span>")%(hostname) + block_txt+="<span style='font-size: medium'> %s </span>" %(datetxt) + block_txt+="<span> </span><input type='button' name='self.main.another_screenshot_button' label='%s' />" %( slabel ) + + self.main.common.threads_enter("TcosActions::get_screenshot show capture") + #url="http://%s:%s/capture-thumb.jpg" %(ip, shared.httpd_port) + self.main.datatxt.clean() + self.main.datatxt.insert_block( block_txt ) + + #self.main.datatxt.insert_html( "<img src='%s' alt='%s'/>\n"\ + # %(url, _("Screenshot of %s" %(ip) )) ) + + # Use Base64 data + self.main.screenshots_action=self.on_screenshot_click + self.__screenshot_counter=0 + savedatetxt="%02d-%02d-%4d_%02d-%02d" %(day, month, year, hour, minute) + self.__screenshot_data["%s"%self.__screenshot_counter]={'hostname':hostname, 'ip':ip, 'date':savedatetxt} + self.main.datatxt.insert_html("""\n<img onclick="%s" base64="%s" />\n"""%(self.__screenshot_counter, scrot[1])) + + self.main.common.threads_leave("TcosActions::get_screenshot show capture") + + self.main.common.threads_enter("TcosActions::get_screenshot END") + self.main.datatxt.display() + self.main.write_into_statusbar ( _("Screenshot of %s, done.") %(ip) ) + self.main.common.threads_leave("TcosActions::get_screenshot END") + + return False + + def on_screenshot_click(self, eventbox, event, number, pixbuf): + if event.button == 3: + ip=self.__screenshot_data[number]['ip'] + self.main.force_selected_ip=ip + # right click show menu + self.main.menus.RightClickMenuOne( None , None, ip) + self.main.menu.popup( None, None, None, event.button, event.time) + return True + menu=gtk.Menu() + save_scrot = gtk.ImageMenuItem(_("Save Screenshot"), True) + icon = gtk.Image() + icon.set_from_stock (gtk.STOCK_SAVE, gtk.ICON_SIZE_BUTTON) + save_scrot.set_image(icon) + save_scrot.connect("activate", self.save_screenshot, number, pixbuf) + save_scrot.show() + menu.append(save_scrot) + menu.popup( None, None, None, event.button, event.time) + + def save_screenshot(self, image, number, pixbuf): + data=self.__screenshot_data[number] + + dialog = gtk.FileChooserDialog(title=_("Select file to save screenshot..."), + action=gtk.FILE_CHOOSER_ACTION_SAVE, + buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_SAVE,gtk.RESPONSE_OK)) + dialog.set_default_response(gtk.RESPONSE_OK) + dialog.set_current_name( _("screenshot_of_%(hostname)s_date_%(date)s.png") %{'hostname':data['hostname'], 'date':data['date']} ) + folder = _folder = os.environ['HOME'] + dialog.set_current_folder(folder) + _filter = gtk.FileFilter() + _filter.set_name( _("Image Files ( *.png, *.jpg)") ) + file_types=["*.png", "*.jpg"] + for elem in file_types: + _filter.add_pattern( elem ) + dialog.add_filter(_filter) + response = dialog.run() + if response == gtk.RESPONSE_OK: + filename=dialog.get_filename() + fext=filename.split('.')[-1] + if not fext in ['png', 'jpg']: + shared.error_msg( _("File must be png or jpg.") ) + dialog.destroy() + return + params={} +# if fext == "jpeg": +# {"quality":"100"} + pixbuf.save(filename, fext, params) + dialog.destroy() + + ########### MULTIPLE HOSTS ############### + + def take_all_screenshots(self, widget): + if not self.get_all_clients(): + return + self.main.screenshots_action=self.on_screenshot_click + self.main.worker=shared.Workers(self.main, None, None) + self.main.worker.set_for_all_action(self.action_for_clients, self.allclients, 'screenshot' ) + + + def start_action(self, *args): + self.__screenshot_counter=0 + self.__screenshot_data={} + self.main.datatxt.clean() + self.main.datatxt.insert_block( _("Screenshots of all hosts") ) + self.main.datatxt.insert_html("<br/>") + + def real_action(self, ip, action): + print_debug("real_action() ip=%s" %ip) + self.main.xmlrpc.newhost(ip) + scrot=self.main.xmlrpc.getscreenshot(self.main.config.GetVar("miniscrot_size")) + if scrot and scrot[0] == "ok": + self.__screenshot_counter+=1 + hostname=self.main.localdata.GetUsername(ip) + if hostname == shared.NO_LOGIN_MSG: + hostname=self.main.localdata.GetHostname(ip) + self.main.common.threads_enter("extensions/screenshot::real_action screenshot") + year, month, day, hour, minute, seconds ,wdy, yday, isdst= localtime() + savedatetxt="%02d-%02d-%4d_%02d-%02d" %(day, month, year, hour, minute) + self.__screenshot_data["%s"%self.__screenshot_counter]={'hostname':hostname, 'ip':ip, 'date':savedatetxt} + self.main.datatxt.insert_html( + "<span style='background-color:#f3d160'>" + + "\n\t<img onclick='%s' base64='%s' title='%s' title_rotate='90' /> " %(self.__screenshot_counter, scrot[1],_( "Screenshot of %s" ) %(hostname) ) + + "<span style='background-color:#f3d160; color:#f3d160'>__</span>\n</span>"+ + "") + self.main.common.threads_leave("extensions/screenshot::real_action screenshot") + + def finish_action(self, *args): + self.main.datatxt.display() + +__extclass__=Screenshot + + + + + + + + diff --git a/tcosmonitor/extensions/sendfiles.py b/tcosmonitor/extensions/sendfiles.py new file mode 100644 index 0000000..c43f10e --- /dev/null +++ b/tcosmonitor/extensions/sendfiles.py @@ -0,0 +1,275 @@ +# -*- coding: UTF-8 -*- +# TcosMonitor version __VERSION__ +# +# Copyright (c) 2006-2011 Mario Izquierdo <mariodebian@gmail.com> +# +# This package is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# +# This package is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +""" template extension """ + +from gettext import gettext as _ + + +from tcosmonitor import shared +from tcosmonitor.TcosExtensions import TcosExtension +import netifaces + +from shutil import copy +import os +import gtk +import sys + +def print_debug(txt): + if shared.debug: + print >> sys.stderr, "%s::%s" % (__name__, txt) + #print("%s::%s" % (__name__, txt), file=sys.stderr) + + +class SendFiles(TcosExtension): + def register(self): + self.main.actions.button_action_send=self.send_all + self.main.classview.class_external_send=self.send_external + + self.main.menus.register_simple( _("Send files") , "menu_send.png", 2, self.send_one, "send") + self.main.menus.register_all( _("Send files") , "menu_send.png", 2, self.send_all, "send") + + def get_ip_address(self, ifname): + print_debug("get_ip_address() ifname=%s" %(ifname) ) + if not ifname in netifaces.interfaces(): + return None + ip=netifaces.ifaddresses(ifname) + if ip.has_key(netifaces.AF_INET): + return ip[netifaces.AF_INET][0]['addr'] + return None + + def send_external(self, filenames): + if self.main.classview.ismultiple(): + if not self.get_all_clients(): + return + elif not self.get_client(): + return + # action sent by vidal_joshur at gva dot es + # send files + # search for connected users + if len(self.connected_users) == 0 or self.connected_users[0] == shared.NO_LOGIN_MSG: + shared.error_msg ( _("Can't send files, user is not logged") ) + return + + if not os.path.isdir("/tmp/tcos_share"): + shared.info_msg( _("TcosMonitor: FTP+TLS server is not running.") ) + return + + for filename in os.listdir("/tmp/tcos_share/"): + if os.path.isfile("/tmp/tcos_share/%s" %filename): + os.remove("/tmp/tcos_share/%s" %filename) + + open="True" + basenames = "" + for filename in filenames: + basenames += "%s\n" % ( os.path.basename(filename[7:]) ) + copy(filename[7:], "/tmp/tcos_share/") + os.chmod("/tmp/tcos_share/%s" %os.path.basename(filename[7:]), 0644) + self.main.write_into_statusbar( _("Waiting for send files...") ) + + newusernames=[] + + for user in self.connected_users: + if user.find(":") != -1: + usern, ip=user.split(":") + self.main.xmlrpc.newhost(ip) + server=self.main.xmlrpc.GetStandalone("get_server") + self.main.xmlrpc.DBus("sendfiles", "%s %s %s" %(_("Teacher"), server, open) ) + self.main.xmlrpc.DBus("mess", _("Teacher has sent some files to %(teacher)s folder:\n\n%(basenames)s") %{"teacher":_("Teacher"), "basenames":basenames}) + else: + newusernames.append(user) + + interface=self.main.config.GetVar("network_interface") + # maybe we the x remote display is other than tcosmonitor server + server=self.get_ip_address(interface) + result = self.main.dbus_action.do_sendfiles( newusernames , _("Teacher"), server, open) + + if not result: + shared.error_msg ( _("Error while exec remote app:\nReason:%s") %( self.main.dbus_action.get_error_msg() ) ) + self.main.write_into_statusbar( _("Error creating destination folder.") ) + else: + result = self.main.dbus_action.do_message(newusernames , + _("Teacher has sent some files to %(teacher)s folder:\n\n%(basenames)s") %{"teacher":_("Teacher"), "basenames":basenames} ) + + self.main.write_into_statusbar( _("Files sent.") ) + + + def send_one(self, widget, ip): + if not self.get_client(): + return + # action sent by vidal_joshur at gva dot es + # send files + # search for connected users + if len(self.connected_users) == 0 or self.connected_users[0] == shared.NO_LOGIN_MSG: + shared.error_msg ( _("Can't send files, user is not logged") ) + return + + str_scapes=[" ", "(", ")", "*", "!", "?", "\"", "`", "[", "]", "{", "}", ";", ":", ",", "=", "$"] + + dialog = gtk.FileChooserDialog( _("Select file or files..."), + None, + gtk.FILE_CHOOSER_ACTION_OPEN, + (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, + gtk.STOCK_OPEN, gtk.RESPONSE_OK)) + dialog.set_default_response(gtk.RESPONSE_OK) + #dialog.set_select_multiple(select_multiple) + dialog.set_select_multiple(True) + self.folder = self._folder = os.environ['HOME'] + dialog.set_current_folder(self.folder) + filter = gtk.FileFilter() + filter.set_name("All files") + filter.add_pattern("*") + dialog.add_filter(filter) + + + if not os.path.isdir("/tmp/tcos_share"): + shared.info_msg( _("TcosMonitor: FTP+TLS server is not running.") ) + return + + for filename in os.listdir("/tmp/tcos_share/"): + if os.path.isfile("/tmp/tcos_share/%s" %filename): + os.remove("/tmp/tcos_share/%s" %filename) + + response = dialog.run() + + if response == gtk.RESPONSE_OK: + + filenames = dialog.get_filenames() + + open="False" + basenames = "" + for filename in filenames: + basenames += "%s\n" % ( os.path.basename(filename) ) + copy(filename, "/tmp/tcos_share/") + os.chmod("/tmp/tcos_share/%s" %os.path.basename(filename), 0644) + self.main.write_into_statusbar( _("Waiting for send files...") ) + + msg=_( "Do you want open file(s) on client?" ) + if shared.ask_msg ( msg ): + open="True" + + newusernames=[] + + for user in self.connected_users: + if user.find(":") != -1: + #usern, ip=user.split(":") + #self.main.xmlrpc.newhost(ip) + server=self.main.xmlrpc.GetStandalone("get_server") + self.main.xmlrpc.DBus("sendfiles", "%s %s %s" %(_("Teacher"), server, open) ) + self.main.xmlrpc.DBus("mess", _("Teacher has sent some files to %(teacher)s folder:\n\n%(basenames)s") %{"teacher":_("Teacher"), "basenames":basenames}) + else: + newusernames.append(user) + + interface=self.main.config.GetVar("network_interface") + # maybe we the x remote display is other than tcosmonitor server + server=self.get_ip_address(interface) + result = self.main.dbus_action.do_sendfiles( newusernames , _("Teacher"), server, open) + + if not result: + shared.error_msg ( _("Error while exec remote app:\nReason:%s") %( self.main.dbus_action.get_error_msg() ) ) + self.main.write_into_statusbar( _("Error creating destination folder.") ) + else: + result = self.main.dbus_action.do_message(newusernames , + _("Teacher has sent some files to %(teacher)s folder:\n\n%(basenames)s") %{"teacher":_("Teacher"), "basenames":basenames} ) + self.main.write_into_statusbar( _("Files sent.") ) + dialog.destroy() + + def send_all(self, *args): + if not self.get_all_clients(): + return + # action sent by vidal_joshur at gva dot es + # send files + # search for connected users + if len(self.connected_users) == 0 or self.connected_users[0] == shared.NO_LOGIN_MSG: + shared.error_msg( _("No users logged.") ) + return + + str_scapes=[" ", "(", ")", "*", "!", "?", "\"", "`", "[", "]", "{", "}", ";", ":", ",", "=", "$"] + + dialog = gtk.FileChooserDialog( _("Select file or files..."), + None, + gtk.FILE_CHOOSER_ACTION_OPEN, + (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, + gtk.STOCK_OPEN, gtk.RESPONSE_OK)) + dialog.set_default_response(gtk.RESPONSE_OK) + #dialog.set_select_multiple(select_multiple) + dialog.set_select_multiple(True) + self.folder = self._folder = os.environ['HOME'] + dialog.set_current_folder(self.folder) + filter = gtk.FileFilter() + filter.set_name("All files") + filter.add_pattern("*") + dialog.add_filter(filter) + + + if not os.path.isdir("/tmp/tcos_share"): + shared.info_msg( _("TcosMonitor: FTP+TLS server is not running.") ) + return + + for filename in os.listdir("/tmp/tcos_share/"): + if os.path.isfile("/tmp/tcos_share/%s" %filename): + os.remove("/tmp/tcos_share/%s" %filename) + + response = dialog.run() + + if response == gtk.RESPONSE_OK: + + filenames = dialog.get_filenames() + + open="False" + basenames = "" + for filename in filenames: + basenames += "%s\n" % ( os.path.basename(filename) ) + copy(filename, "/tmp/tcos_share/") + os.chmod("/tmp/tcos_share/%s" %os.path.basename(filename), 0644) + self.main.write_into_statusbar( _("Waiting for send files...") ) + + msg=_( "Do you want open file(s) on client?" ) + if shared.ask_msg ( msg ): + open="True" + + newusernames=[] + + for user in self.connected_users: + if user.find(":") != -1: + usern, ip=user.split(":") + self.main.xmlrpc.newhost(ip) + server=self.main.xmlrpc.GetStandalone("get_server") + self.main.xmlrpc.DBus("sendfiles", "%s %s %s" %(_("Teacher"), server, open) ) + self.main.xmlrpc.DBus("mess", _("Teacher has sent some files to %(teacher)s folder:\n\n%(basenames)s") %{"teacher":_("Teacher"), "basenames":basenames}) + else: + newusernames.append(user) + + interface=self.main.config.GetVar("network_interface") + # maybe we the x remote display is other than tcosmonitor server + server=self.get_ip_address(interface) + result = self.main.dbus_action.do_sendfiles( newusernames , _("Teacher"), server, open) + + if not result: + shared.error_msg ( _("Error while exec remote app:\nReason:%s") %( self.main.dbus_action.get_error_msg() ) ) + self.main.write_into_statusbar( _("Error creating destination folder.") ) + else: + result = self.main.dbus_action.do_message(newusernames , + _("Teacher has sent some files to %(teacher)s folder:\n\n%(basenames)s") %{"teacher":_("Teacher"), "basenames":basenames} ) + + self.main.write_into_statusbar( _("Files sent.") ) + dialog.destroy() + + +__extclass__=SendFiles diff --git a/tcosmonitor/extensions/tcosnetcontroller.py b/tcosmonitor/extensions/tcosnetcontroller.py new file mode 100644 index 0000000..ff31be7 --- /dev/null +++ b/tcosmonitor/extensions/tcosnetcontroller.py @@ -0,0 +1,188 @@ +# -*- coding: UTF-8 -*- +# TcosMonitor version __VERSION__ +# +# Copyright (c) 2006-2011 Mario Izquierdo <mariodebian@gmail.com> +# +# This package is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# +# This package is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +""" template extension """ +from gettext import gettext as _ +import sys + +from tcosmonitor import shared +from tcosmonitor.TcosExtensions import TcosExtension + +def print_debug(txt): + if shared.debug: + print >> sys.stderr, "%s::%s" % (__name__, txt) + #print("%s::%s" % (__name__, txt), file=sys.stderr) + + +class TcosNetController(TcosExtension): + def register(self): + self.main.menus.register_simple( _("Lock internet"), "menu_locknet.png", 1, self.locknet_simple, "net") + self.main.menus.register_simple( _("Unlock internet"), "menu_unlocknet.png", 1, self.unlocknet_simple, "net") + + self.main.menus.register_all( _("Lock internet in all connected users"), "menu_locknet.png", 1, self.locknet_all, "net") + self.main.menus.register_all( _("Unlock internet in all connected users"), "menu_unlocknet.png", 1, self.unlocknet_all, "net") + + def locknet_simple(self, w, ip): + if not self.get_client(): + return + # lock net + eth=self.main.config.GetVar("network_interface") + ports="--ports=%s" %self.main.config.GetVar("ports_tnc") + remote_msg=_("Internet connection has been disabled") + act="disable-internet" + + if len(self.connected_users) == 0 or self.connected_users[0] == shared.NO_LOGIN_MSG: + shared.error_msg ( _("Can't disable internet, user is not logged") ) + return + + if self.client_type == "tcos": + if not self.main.localdata.user_in_group(None, 'tcos'): + msg=(_("In order to lock and unlock internet you need to be in 'tcos' group.\n\nExe by root: adduser %s tcos" ) %(self.main.localdata.get_username())) + shared.error_msg ( msg ) + return + result = self.main.localdata.BlockNet(act, self.connected_users[0], ports, eth) + if result == "disabled": + self.main.dbus_action.do_message( self.connected_users, remote_msg ) + else: + result = self.main.xmlrpc.tnc(act, self.connected_users[0].split(":")[0], ports) + if result == "disabled": + self.main.xmlrpc.DBus("mess", remote_msg) + + self.change_lockscreen(ip) + + + def unlocknet_simple(self, w, ip): + if not self.get_client(): + return + # unlock net + remote_msg=_("Internet connection has been enabled") + act="enable-internet" + + if len(self.connected_users) == 0 or self.connected_users[0] == shared.NO_LOGIN_MSG: + shared.error_msg ( _("Can't enable internet, user is not logged") ) + return + if self.client_type == "tcos": + if not self.main.localdata.user_in_group(None, 'tcos'): + msg=(_("In order to lock and unlock internet you need to be in 'tcos' group.\n\nExe by root: adduser %s tcos" ) %(self.main.localdata.get_username())) + shared.error_msg ( msg ) + return + result = self.main.localdata.BlockNet(act, self.connected_users[0]) + if result == "enabled": + self.main.dbus_action.do_message( self.connected_users, remote_msg ) + else: + result = self.main.xmlrpc.tnc(act, self.connected_users[0].split(":")[0]) + if result == "enabled": + self.main.xmlrpc.DBus("mess", remote_msg) + + self.change_lockscreen(ip) + + + def locknet_all(self, *args): + if not self.get_all_clients(): + return + if not self.main.localdata.user_in_group(None, 'tcos'): + msg=(_("In order to lock and unlock internet you need to be in 'tcos' group.\n\nExe by root: adduser %s tcos" ) %(self.main.localdata.get_username())) + shared.error_msg ( msg ) + return + # disable internet + eth=self.main.config.GetVar("network_interface") + ports="--ports=%s" %self.main.config.GetVar("ports_tnc") + remote_msg=_("Internet connection has been disabled") + act="disable-internet" + + if len(self.connected_users) == 0 or self.connected_users[0] == shared.NO_LOGIN_MSG: + shared.error_msg( _("No users logged.") ) + return + + msg=_( _("Do you want disable internet to following users: %s?" )%(self.connected_users_txt) ) + + if not shared.ask_msg ( msg ): + return + + newusernames=[] + + for user in self.connected_users: + if user.find(":") != -1: + usern, ip=user.split(":") + self.main.xmlrpc.newhost(ip) + result = self.main.xmlrpc.tnc(act, usern, ports) + if result == "disabled": + self.main.xmlrpc.DBus("mess", remote_msg) + else: + result = self.main.localdata.BlockNet(act, user, ports, eth) + if result == "disabled": + newusernames.append(user) + + result = self.main.dbus_action.do_message( newusernames, remote_msg ) + + for client in self.newallclients: + self.main.localdata.newhost(client) + self.main.xmlrpc.newhost(client) + self.change_lockscreen(client) + + + def unlocknet_all(self, *args): + if not self.get_all_clients(): + return + if not self.main.localdata.user_in_group(None, 'tcos'): + msg=(_("In order to lock and unlock internet you need to be in 'tcos' group.\n\nExe by root: adduser %s tcos" ) %(self.main.localdata.get_username())) + shared.error_msg ( msg ) + return + # enable internet + remote_msg=_("Internet connection has been enabled") + act="enable-internet" + + if len(self.connected_users) == 0 or self.connected_users[0] == shared.NO_LOGIN_MSG: + shared.error_msg( _("No users logged.") ) + return + + msg=_( _("Do you want enable internet to following users: %s?" )%(self.connected_users_txt) ) + + if not shared.ask_msg ( msg ): + return + + newusernames=[] + + for user in self.connected_users: + if user.find(":") != -1: + usern, ip=user.split(":") + self.main.xmlrpc.newhost(ip) + result = self.main.xmlrpc.tnc(act, usern) + if result == "enabled": + self.main.xmlrpc.DBus("mess", remote_msg) + else: + result = self.main.localdata.BlockNet(act, user) + if result == "enabled": + newusernames.append(user) + + result = self.main.dbus_action.do_message( newusernames, remote_msg ) + + for client in self.newallclients: + self.main.localdata.newhost(client) + self.main.xmlrpc.newhost(client) + self.change_lockscreen(client) + + +__extclass__=TcosNetController + + + + + + diff --git a/tcosmonitor/extensions/tcospersonalize.py b/tcosmonitor/extensions/tcospersonalize.py new file mode 100644 index 0000000..14b574f --- /dev/null +++ b/tcosmonitor/extensions/tcospersonalize.py @@ -0,0 +1,61 @@ +# -*- coding: UTF-8 -*- +# TcosMonitor version __VERSION__ +# +# Copyright (c) 2006-2011 Mario Izquierdo <mariodebian@gmail.com> +# +# This package is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# +# This package is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +""" template extension """ + +from gettext import gettext as _ +import os +import sys + +from tcosmonitor import shared +from tcosmonitor.TcosExtensions import TcosExtension + +def print_debug(txt): + if shared.debug: + print >> sys.stderr, "%s::%s" % (__name__, txt) + #print("%s::%s" % (__name__, txt), file=sys.stderr) + + +class TcosPersonalize(TcosExtension): + def register(self): + self.main.menus.register_simple( _("Configure this host"), "menu_configure.png", 0, self.launch_tcospersonalize, "personalize") + + + def launch_tcospersonalize(self, w, ip): + if not self.get_client(): + return + if self.client_type == "tcos": + if self.main.ingroup_tcos == False and os.getuid() != 0: + cmd="gksu \"tcospersonalize --host=%s\"" %(ip) + else: + cmd="tcospersonalize --host=%s" %(ip) + print_debug ( "launch_tcospersonalize() cmd=%s" %(cmd) ) + th=self.main.common.exe_cmd( cmd, verbose=0, background=True ) + else: + shared.info_msg( _("%s is not supported to personalize!") %(self.client_type) ) + + + +__extclass__=TcosPersonalize + + + + + + diff --git a/tcosmonitor/extensions/videolan.py b/tcosmonitor/extensions/videolan.py new file mode 100644 index 0000000..3824d1f --- /dev/null +++ b/tcosmonitor/extensions/videolan.py @@ -0,0 +1,648 @@ +# -*- coding: UTF-8 -*- +# TcosMonitor version __VERSION__ +# +# Copyright (c) 2006-2011 Mario Izquierdo <mariodebian@gmail.com> +# +# This package is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# +# This package is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +""" template extension """ + +from gettext import gettext as _ +import sys + +from tcosmonitor import shared +from tcosmonitor.TcosExtensions import TcosExtension + +import os +import gtk +import subprocess +import signal + +def print_debug(txt): + if shared.debug: + print >> sys.stderr, "%s::%s" % (__name__, txt) + #print("%s::%s" % (__name__, txt), file=sys.stderr) + + +class VideoOne(TcosExtension): + def register(self): + self.vlc_count={} + self.main.classview.class_external_video=self.video_external + self.main.actions.button_action_video=self.video_all + + self.main.menus.register_simple( _("Send Audio/Video broadcast") , "menu_broadcast.png", 2, self.video_one, "video") + self.main.menus.register_all( _("Send Audio/Video broadcast") , "menu_broadcast.png", 2, self.video_all, "video") + + + + def video_external(self, filename): + if self.main.classview.ismultiple(): + if not self.get_all_clients(): + return + elif not self.get_client(): + return + # action sent by vidal_joshur at gva dot es + # start video broadcast mode + # Stream to single client unicast + eth=self.main.config.GetVar("network_interface") + + if len(self.connected_users) == 0 or self.connected_users[0] == shared.NO_LOGIN_MSG: + shared.error_msg ( _("Can't send video broadcast, user is not logged") ) + return + + str_scapes=[" ", "(", ")", "*", "!", "?", "\"", "`", "[", "]", "{", "}", ";", ":", ",", "=", "$"] + lock="disable" + volume="85" + + if self.main.pref_vlc_method_send.get_active() == 0: + vcodec=shared.vcodecs[0] + venc=shared.vencs[0] + acodec=shared.acodecs[0] + aenc=shared.aencs[0] + access=shared.accesss[0] + mux=shared.muxs[0] + elif self.main.pref_vlc_method_send.get_active() == 1: + vcodec=shared.vcodecs[1] + venc=shared.vencs[0] + acodec=shared.acodecs[0] + aenc=shared.aencs[0] + access=shared.accesss[0] + mux=shared.muxs[0] + elif self.main.pref_vlc_method_send.get_active() == 2: + vcodec=shared.vcodecs[2] + venc=shared.vencs[1] + acodec=shared.acodecs[0] + aenc=shared.aencs[0] + access=shared.accesss[0] + mux=shared.muxs[0] + elif self.main.pref_vlc_method_send.get_active() == 3: + vcodec=shared.vcodecs[3] + venc=shared.vencs[2] + acodec=shared.acodecs[1] + aenc=shared.aencs[1] + access=shared.accesss[1] + mux=shared.muxs[1] + elif self.main.pref_vlc_method_send.get_active() == 4: + vcodec=shared.vcodecs[1] + venc=shared.vencs[0] + acodec=shared.acodecs[1] + aenc=shared.aencs[1] + access=shared.accesss[1] + mux=shared.muxs[1] + + if access == "udp": + max_uip=255 + uip=0 + while uip <= max_uip: + uip_cmd="239.254.%s.0" %(uip) + cmd=("LC_ALL=C LC_MESSAGES=C netstat -putan 2>/dev/null | grep -c %s" %(uip_cmd) ) + print_debug("Check broadcast ip %s." %(uip_cmd) ) + output=self.main.common.exe_cmd(cmd) + uip+=1 + if output == "0": + print_debug("Broadcast ip found: %s" %(uip_cmd)) + ip_broadcast="%s:1234" %uip_cmd + break + elif uip == max_uip: + print_debug("Not found an available broadcast ip") + return + else: + max_uip=50255 + uip=50000 + while uip <= max_uip: + uip_cmd=":%s" %(uip) + cmd=("LC_ALL=C LC_MESSAGES=C netstat -putan 2>/dev/null | grep -c %s" %(uip_cmd) ) + print_debug("Check broadcast ip %s." %(uip_cmd) ) + output=self.main.common.exe_cmd(cmd) + uip+=1 + if output == "0": + print_debug("Broadcast ip found: %s" %(uip_cmd)) + ip_broadcast=uip_cmd + uip_cmd="" + break + elif uip == max_uip: + print_debug("Not found an available broadcast ip") + return + + if uip_cmd != "": + result = self.main.localdata.Route("route-add", uip_cmd, "255.255.255.0", eth) + if result == "error": + print_debug("Add multicast-ip route failed") + return + + if filename.find(" ") != -1: + msg=_("Not allowed white spaces in \"%s\".\nPlease rename it." %os.path.basename(filename) ) + shared.info_msg( msg ) + return + + if access == "udp": + remote_cmd_standalone="vlc udp://@%s --udp-caching=1000 --aout=alsa --brightness=2.000000 --volume=300 --fullscreen --aspect-ratio=4:3 --loop" %(ip_broadcast) + remote_cmd_thin="vlc udp://@%s --udp-caching=1000 --aout=alsa --brightness=2.000000 --volume=300 --aspect-ratio=4:3 --loop" %(ip_broadcast) + + p=subprocess.Popen(["vlc", "file://%s" %filename, "--sout=#duplicate{dst=display{delay=1000},dst=\"transcode{vcodec=%s,venc=%s,acodec=%s,aenc=%s,vb=800,ab=112,channels=2,soverlay}:standard{access=%s,mux=%s,dst=%s}\"}" %(vcodec, venc, acodec, aenc, access, mux, ip_broadcast), "--miface=%s" %eth, "--ttl=12", "--brightness=2.000000"], shell=False, bufsize=0, close_fds=True) + + self.main.write_into_statusbar( _("Waiting for start video transmission...") ) + + #msg=_("First select the DVD chapter or play movie\nthen press enter to send client..." ) + #shared.info_msg( msg ) + + # check if vlc is running or fail like check ping in demo mode + running = p.poll() is None + if not running: + self.main.write_into_statusbar( _("Error while exec app")) + return + + #msg=_( "Lock keyboard and mouse on client?" ) + #if shared.ask_msg ( msg ): + # lock="enable" + + newusernames=[] + + for user in self.connected_users: + if user.find(":") != -1: + # we have a standalone user... + usern, ip = user.split(":") + self.main.xmlrpc.newhost(ip) + if access == "http": + server=self.main.xmlrpc.GetStandalone("get_server") + remote_cmd_standalone="vlc http://%s%s --aout=alsa --brightness=2.000000 --volume=300 --fullscreen --aspect-ratio=4:3 --http-reconnect --loop" %(server, ip_broadcast) + self.main.xmlrpc.DBus("exec", remote_cmd_standalone ) + else: + newusernames.append(user) + + if access == "http": + remote_cmd_thin="vlc http://localhost%s --aout=alsa --brightness=2.000000 --volume=300 --aspect-ratio=4:3 --http-reconnect --loop" % (ip_broadcast) + + result = self.main.dbus_action.do_exec( newusernames, remote_cmd_thin ) + + if not result: + shared.error_msg ( _("Error while exec remote app:\nReason:%s") %( self.main.dbus_action.get_error_msg() ) ) + + for client in self.newallclients: + self.main.xmlrpc.vlc( client, volume, lock ) + + self.main.write_into_statusbar( _("Running in broadcast video transmission.") ) + # new mode to Stop Button + if len(self.vlc_count.keys()) != 0: + count=len(self.vlc_count.keys())-1 + nextkey=self.vlc_count.keys()[count]+1 + self.vlc_count[nextkey]=uip_cmd + else: + nextkey=1 + self.vlc_count[nextkey]=uip_cmd + self.add_progressbox( {"target": "vlc", "pid":p.pid, "lock":lock, "allclients":self.newallclients, "ip":uip_cmd, "iface":eth, "key":nextkey}, _("Running in broadcast video transmission to user %(host)s. Broadcast Nº %(count)s") %{"host":self.connected_users_txt, "count":nextkey} ) + + def video_one(self, widget, ip): + if not self.get_client(): + return + # action sent by vidal_joshur at gva dot es + # start video broadcast mode + # Stream to single client unicast + eth=self.main.config.GetVar("network_interface") + + if len(self.connected_users) == 0 or self.connected_users[0] == shared.NO_LOGIN_MSG: + shared.error_msg ( _("Can't send video broadcast, user is not logged") ) + return + + str_scapes=[" ", "(", ")", "*", "!", "?", "\"", "`", "[", "]", "{", "}", ";", ":", ",", "=", "$"] + lock="disable" + volume="85" + + if self.main.pref_vlc_method_send.get_active() == 0: + vcodec=shared.vcodecs[0] + venc=shared.vencs[0] + acodec=shared.acodecs[0] + aenc=shared.aencs[0] + access=shared.accesss[0] + mux=shared.muxs[0] + elif self.main.pref_vlc_method_send.get_active() == 1: + vcodec=shared.vcodecs[1] + venc=shared.vencs[0] + acodec=shared.acodecs[0] + aenc=shared.aencs[0] + access=shared.accesss[0] + mux=shared.muxs[0] + elif self.main.pref_vlc_method_send.get_active() == 2: + vcodec=shared.vcodecs[2] + venc=shared.vencs[1] + acodec=shared.acodecs[0] + aenc=shared.aencs[0] + access=shared.accesss[0] + mux=shared.muxs[0] + elif self.main.pref_vlc_method_send.get_active() == 3: + vcodec=shared.vcodecs[3] + venc=shared.vencs[2] + acodec=shared.acodecs[1] + aenc=shared.aencs[1] + access=shared.accesss[1] + mux=shared.muxs[1] + elif self.main.pref_vlc_method_send.get_active() == 4: + vcodec=shared.vcodecs[1] + venc=shared.vencs[0] + acodec=shared.acodecs[1] + aenc=shared.aencs[1] + access=shared.accesss[1] + mux=shared.muxs[1] + + + if access == "udp": + if self.client_type == "tcos": + max_uip=255 + uip=0 + while uip <= max_uip: + uip_cmd="239.254.%s.0" %(uip) + cmd=("LC_ALL=C LC_MESSAGES=C netstat -putan 2>/dev/null | grep -c %s" %(uip_cmd) ) + print_debug("Check broadcast ip %s." %(uip_cmd) ) + output=self.main.common.exe_cmd(cmd) + uip+=1 + if output == "0": + print_debug("Broadcast ip found: %s" %(uip_cmd)) + ip_unicast="%s:1234" %uip_cmd + break + elif uip == max_uip: + print_debug("Not found an available broadcast ip") + return + remote_cmd="vlc udp://@%s --udp-caching=1000 --aout=alsa --brightness=2.000000 --volume=300 --aspect-ratio=4:3 --loop" %(ip_unicast) + else: + uip_cmd="" + ip_unicast="%s:1234" %self.main.selected_ip + remote_cmd="vlc udp://@:1234 --udp-caching=1000 --aout=alsa --brightness=2.000000 --volume=300 --fullscreen --aspect-ratio=4:3 --loop" + else: + max_uip=50255 + uip=50000 + while uip <= max_uip: + uip_cmd=":%s" %(uip) + cmd=("LC_ALL=C LC_MESSAGES=C netstat -putan 2>/dev/null | grep -c %s" %(uip_cmd) ) + print_debug("Check broadcast ip %s." %(uip_cmd) ) + output=self.main.common.exe_cmd(cmd) + uip+=1 + if output == "0": + print_debug("Broadcast ip found: %s" %(uip_cmd)) + ip_unicast=uip_cmd + uip_cmd="" + break + elif uip == max_uip: + print_debug("Not found an available broadcast ip") + return + if self.client_type == "tcos": + remote_cmd="vlc http://localhost%s --aout=alsa --brightness=2.000000 --volume=300 --aspect-ratio=4:3 --http-reconnect --loop" %(ip_unicast) + + if uip_cmd != "": + result = self.main.localdata.Route("route-add", uip_cmd, "255.255.255.0", eth) + if result == "error": + print_debug("Add multicast-ip route failed") + return + + dialog = gtk.FileChooserDialog(_("Select audio/video file.."), + None, + gtk.FILE_CHOOSER_ACTION_OPEN, + (_("Play DVD"), 1, + _("Play SVCD/VCD"), 2, + _("Play AudioCD"), 3, + gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, + gtk.STOCK_OPEN, gtk.RESPONSE_OK)) + dialog.set_default_response(gtk.RESPONSE_OK) + self.folder = self._folder = os.environ['HOME'] + dialog.set_current_folder(self.folder) + filter = gtk.FileFilter() + filter.set_name("Media Files ( *.avi, *.mpg, *.mpeg, *.mp3, *.wav, etc.. )") + file_types=["*.avi", "*.mpg", "*.mpeg", "*.ogg", "*.ogm", "*.asf", "*.divx", + "*.wmv", "*.vob", "*.m2v", "*.m4v", "*.mp2", "*.mp4", "*.ac3", + "*.ogg", "*.mp1", "*.mp2", "*.mp3", "*.wav", "*.wma"] + for elem in file_types: + filter.add_pattern( elem ) + + dialog.add_filter(filter) + + filter = gtk.FileFilter() + filter.set_name("All Files") + filter.add_pattern("*.*") + dialog.add_filter(filter) + response = dialog.run() + if response == gtk.RESPONSE_OK or response == 1 or response == 2 or response == 3: + + filename=dialog.get_filename() + dialog.destroy() + + #for scape in str_scapes: + # filename=filename.replace("%s" %scape, "\%s" %scape) + + if response == gtk.RESPONSE_OK: + if filename.find(" ") != -1: + msg=_("Not allowed white spaces in \"%s\".\nPlease rename it." %os.path.basename(filename) ) + shared.info_msg( msg ) + return + p=subprocess.Popen(["vlc", "file://%s" %filename, "--sout=#duplicate{dst=display{delay=1000},dst=\"transcode{vcodec=%s,venc=%s,acodec=%s,aenc=%s,vb=800,ab=112,channels=2,soverlay}:standard{access=%s,mux=%s,dst=%s}\"}" %(vcodec, venc, acodec, aenc, access, mux, ip_unicast), "--miface=%s" %eth, "--ttl=12", "--brightness=2.000000"], shell=False, bufsize=0, close_fds=True) + elif response == 1: + p=subprocess.Popen(["vlc", "dvdsimple:///dev/cdrom", "--sout=#duplicate{dst=display{delay=700},dst=\"transcode{vcodec=%s,venc=%s,acodec=%s,aenc=%s,vb=800,ab=112,channels=2,soverlay}:standard{access=%s,mux=%s,dst=%s}\"}" %(vcodec, venc, acodec, aenc, access, mux, ip_unicast), "--miface=%s" %eth, "--ttl=12", "--loop", "--brightness=2.000000"], shell=False, bufsize=0, close_fds=True) + elif response == 2: + p=subprocess.Popen(["vlc", "vcd:///dev/cdrom", "--sout=#duplicate{dst=display{delay=1000},dst=\"transcode{vcodec=%s,venc=%s,acodec=%s,aenc=%s,vb=800,ab=112,channels=2,soverlay}:standard{access=%s,mux=%s,dst=%s}\"}" %(vcodec, venc, acodec, aenc, access, mux, ip_unicast), "--miface=%s" %eth, "--ttl=12", "--brightness=2.000000"], shell=False, bufsize=0, close_fds=True) + elif response == 3: + p=subprocess.Popen(["vlc", "cdda:///dev/cdrom", "--sout=#duplicate{dst=display,dst=\"transcode{vcodec=%s,venc=%s,acodec=%s,aenc=%s,vb=200,ab=112,channels=2}:standard{access=%s,mux=%s,dst=%s}\"}" %(vcodec, venc, acodec, aenc, access, mux, ip_unicast), "--miface=%s" %eth, "--ttl=12"], shell=False, bufsize=0, close_fds=True) + # exec this app on client + + self.main.write_into_statusbar( _("Waiting for start video transmission...") ) + + msg=_("First select the DVD chapter or play movie\nthen press enter to send clients..." ) + shared.info_msg( msg ) + + # check if vlc is running or fail like check ping in demo mode + running = p.poll() is None + if not running: + self.main.write_into_statusbar( _("Error while exec app")) + return + + msg=_( "Lock keyboard and mouse on client?" ) + if shared.ask_msg ( msg ): + lock="enable" + + newusernames=[] + + for user in self.connected_users: + if user.find(":") != -1: + # we have a standalone user... + if access == "http": + server=self.main.xmlrpc.GetStandalone("get_server") + remote_cmd="vlc http://%s%s --aout=alsa --brightness=2.000000 --volume=300 --fullscreen --aspect-ratio=4:3 --http-reconnect --loop" %(server, ip_unicast) + self.main.xmlrpc.DBus("exec", remote_cmd ) + else: + newusernames.append(user) + + result = self.main.dbus_action.do_exec( newusernames, remote_cmd ) + + if not result: + shared.error_msg ( _("Error while exec remote app:\nReason:%s") %( self.main.dbus_action.get_error_msg() ) ) + + self.main.xmlrpc.vlc( self.main.selected_ip, volume, lock ) + + self.main.write_into_statusbar( _("Running in broadcast video transmission.") ) + # new mode to Stop Button + if len(self.vlc_count.keys()) != 0: + count=len(self.vlc_count.keys())-1 + nextkey=self.vlc_count.keys()[count]+1 + self.vlc_count[nextkey]=uip_cmd + else: + nextkey=1 + self.vlc_count[nextkey]=uip_cmd + self.add_progressbox( {"target": "vlc", "pid":p.pid, "lock":lock, "allclients":self.newallclients, "ip":uip_cmd, "iface":eth, "key":nextkey}, _("Running in broadcast video transmission to user %(host)s. Broadcast Nº %(count)s") %{"host":self.connected_users_txt, "count":nextkey} ) + else: + dialog.destroy() + + def on_progressbox_click(self, widget, args, box): + box.destroy() + print_debug("on_progressbox_click() widget=%s, args=%s, box=%s" %(widget, args, box) ) + + if not args['target']: + return + + self.main.stop_running_actions.remove(widget) + + if args['target'] == "vlc": + del self.vlc_count[args['key']] + if args['ip'] != "": + result = self.main.localdata.Route("route-del", args['ip'], "255.255.255.0", args['iface']) + if result == "error": + print_debug("Del multicast-ip route failed") + connected_users=[] + for client in args['allclients']: + self.main.localdata.newhost(client) + if self.main.localdata.IsLogged(client): + if args['lock'] == "enable": + self.main.xmlrpc.unlockcontroller("lockvlc", client) + connected_users.append(self.main.localdata.GetUsernameAndHost(client)) + + newusernames=[] + + for user in connected_users: + if user.find(":") != -1: + # we have a standalone user... in some cases or after much time need SIGKILL vlc + usern, ip = user.split(":") + self.main.xmlrpc.newhost(ip) + self.main.xmlrpc.DBus("killall", "-s KILL vlc" ) + else: + newusernames.append(user) + + result = self.main.dbus_action.do_killall( newusernames , "-s KILL vlc" ) + + if "pid" in args: + os.kill(args['pid'], signal.SIGKILL) + else: + self.main.common.exe_cmd("killall -s KILL vlc", verbose=0, background=True) + self.main.write_into_statusbar( _("Video broadcast stopped.") ) + + + def video_all(self, *args): + if not self.get_all_clients(): + return + # action sent by vidal_joshur at gva dot es + # start video broadcast mode + # search for connected users + # Stream to multiple clients + eth=self.main.config.GetVar("network_interface") + + if len(self.connected_users) == 0 or self.connected_users[0] == shared.NO_LOGIN_MSG: + shared.error_msg( _("No users logged.") ) + return + + str_scapes=[" ", "(", ")", "*", "!", "?", "\"", "`", "[", "]", "{", "}", ";", ":", ",", "=", "$"] + + if self.main.pref_vlc_method_send.get_active() == 0: + vcodec=shared.vcodecs[0] + venc=shared.vencs[0] + acodec=shared.acodecs[0] + aenc=shared.aencs[0] + access=shared.accesss[0] + mux=shared.muxs[0] + elif self.main.pref_vlc_method_send.get_active() == 1: + vcodec=shared.vcodecs[1] + venc=shared.vencs[0] + acodec=shared.acodecs[0] + aenc=shared.aencs[0] + access=shared.accesss[0] + mux=shared.muxs[0] + elif self.main.pref_vlc_method_send.get_active() == 2: + vcodec=shared.vcodecs[2] + venc=shared.vencs[1] + acodec=shared.acodecs[0] + aenc=shared.aencs[0] + access=shared.accesss[0] + mux=shared.muxs[0] + elif self.main.pref_vlc_method_send.get_active() == 3: + vcodec=shared.vcodecs[3] + venc=shared.vencs[2] + acodec=shared.acodecs[1] + aenc=shared.aencs[1] + access=shared.accesss[1] + mux=shared.muxs[1] + elif self.main.pref_vlc_method_send.get_active() == 4: + vcodec=shared.vcodecs[1] + venc=shared.vencs[0] + acodec=shared.acodecs[1] + aenc=shared.aencs[1] + access=shared.accesss[1] + mux=shared.muxs[1] + + if access == "udp": + max_uip=255 + uip=0 + while uip <= max_uip: + uip_cmd="239.254.%s.0" %(uip) + cmd=("LC_ALL=C LC_MESSAGES=C netstat -putan 2>/dev/null | grep -c %s" %(uip_cmd) ) + print_debug("Check broadcast ip %s." %(uip_cmd) ) + output=self.main.common.exe_cmd(cmd) + uip+=1 + if output == "0": + print_debug("Broadcast ip found: %s" %(uip_cmd)) + ip_broadcast="%s:1234" %uip_cmd + break + elif uip == max_uip: + print_debug("Not found an available broadcast ip") + return + else: + max_uip=50255 + uip=50000 + while uip <= max_uip: + uip_cmd=":%s" %(uip) + cmd=("LC_ALL=C LC_MESSAGES=C netstat -putan 2>/dev/null | grep -c %s" %(uip_cmd) ) + print_debug("Check broadcast ip %s." %(uip_cmd) ) + output=self.main.common.exe_cmd(cmd) + uip+=1 + if output == "0": + print_debug("Broadcast ip found: %s" %(uip_cmd)) + ip_broadcast=uip_cmd + uip_cmd="" + break + elif uip == max_uip: + print_debug("Not found an available broadcast ip") + return + + lock="disable" + volume="85" + + if uip_cmd != "": + result = self.main.localdata.Route("route-add", uip_cmd, "255.255.255.0", eth) + if result == "error": + print_debug("Add multicast-ip route failed") + return + + dialog = gtk.FileChooserDialog(_("Select audio/video file.."), + None, + gtk.FILE_CHOOSER_ACTION_OPEN, + (_("Play DVD"), 1, + _("Play SVCD/VCD"), 2, + _("Play AudioCD"), 3, + gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, + gtk.STOCK_OPEN, gtk.RESPONSE_OK)) + dialog.set_default_response(gtk.RESPONSE_OK) + self.folder = self._folder = os.environ['HOME'] + dialog.set_current_folder(self.folder) + filter = gtk.FileFilter() + filter.set_name("Media Files ( *.avi, *.mpg, *.mpeg, *.mp3, *.wav, etc.. )") + file_types=["*.avi", "*.mpg", "*.mpeg", "*.ogg", "*.ogm", "*.asf", "*.divx", + "*.wmv", "*.vob", "*.m2v", "*.m4v", "*.mp2", "*.mp4", "*.ac3", + "*.ogg", "*.mp1", "*.mp2", "*.mp3", "*.wav", "*.wma"] + for elem in file_types: + filter.add_pattern( elem ) + + dialog.add_filter(filter) + + filter = gtk.FileFilter() + filter.set_name("All Files") + filter.add_pattern("*.*") + dialog.add_filter(filter) + + response = dialog.run() + if response == gtk.RESPONSE_OK or response == 1 or response == 2 or response == 3: + + filename=dialog.get_filename() + dialog.destroy() + + #for scape in str_scapes: + # filename=filename.replace("%s" %scape, "\%s" %scape) + + if response == gtk.RESPONSE_OK: + if filename.find(" ") != -1: + msg=_("Not allowed white spaces in \"%s\".\nPlease rename it." %os.path.basename(filename) ) + shared.info_msg( msg ) + return + p=subprocess.Popen(["vlc", "file://%s" %filename, "--sout=#duplicate{dst=display{delay=1000},dst=\"transcode{vcodec=%s,venc=%s,acodec=%s,aenc=%s,vb=800,ab=112,channels=2,soverlay}:standard{access=%s,mux=%s,dst=%s}\"}" %(vcodec, venc, acodec, aenc, access, mux, ip_broadcast), "--miface=%s" %eth, "--ttl=12", "--brightness=2.000000"], shell=False, bufsize=0, close_fds=True) + elif response == 1: + p=subprocess.Popen(["vlc", "dvdsimple:///dev/cdrom", "--sout=#duplicate{dst=display{delay=700},dst=\"transcode{vcodec=%s,venc=%s,acodec=%s,aenc=%s,vb=800,ab=112,channels=2,soverlay}:standard{access=%s,mux=%s,dst=%s}\"}" %(vcodec, venc, acodec, aenc, access, mux, ip_broadcast), "--miface=%s" %eth, "--ttl=12", "--loop", "--brightness=2.000000"], shell=False, bufsize=0, close_fds=True) + elif response == 2: + p=subprocess.Popen(["vlc", "vcd:///dev/cdrom", "--sout=#duplicate{dst=display{delay=1000},dst=\"transcode{vcodec=%s,venc=%s,acodec=%s,aenc=%s,vb=800,ab=112,channels=2,soverlay}:standard{access=%s,mux=%s,dst=%s}\"}" %(vcodec, venc, acodec, aenc, access, mux, ip_broadcast), "--miface=%s" %eth, "--ttl=12", "--brightness=2.000000"], shell=False, bufsize=0, close_fds=True) + elif response == 3: + p=subprocess.Popen(["vlc", "cdda:///dev/cdrom", "--sout=#duplicate{dst=display,dst=\"transcode{vcodec=%s,venc=%s,acodec=%s,aenc=%s,vb=200,ab=112,channels=2}:standard{access=%s,mux=%s,dst=%s}\"}" %(vcodec, venc, acodec, aenc, access, mux, ip_broadcast), "--miface=%s" %eth, "--ttl=12"], shell=False, bufsize=0, close_fds=True) + # exec this app on client + + if access == "udp": + remote_cmd_standalone="vlc udp://@%s --udp-caching=1000 --aout=alsa --brightness=2.000000 --volume=300 --fullscreen --aspect-ratio=4:3 --loop" %(ip_broadcast) + remote_cmd_thin="vlc udp://@%s --udp-caching=1000 --aout=alsa --brightness=2.000000 --volume=300 --aspect-ratio=4:3 --loop" %(ip_broadcast) + + self.main.write_into_statusbar( _("Waiting for start video transmission...") ) + + msg=_("First select the DVD chapter or play movie\nthen press enter to send clients..." ) + shared.info_msg( msg ) + + # check if vlc is running or fail like check ping in demo mode + running = p.poll() is None + if not running: + self.main.write_into_statusbar( _("Error while exec app")) + return + + msg=_( "Lock keyboard and mouse on clients?" ) + if shared.ask_msg ( msg ): + lock="enable" + + newusernames=[] + + for user in self.connected_users: + if user.find(":") != -1: + # we have a standalone user... + usern, ip = user.split(":") + self.main.xmlrpc.newhost(ip) + if access == "http": + server=self.main.xmlrpc.GetStandalone("get_server") + remote_cmd_standalone="vlc http://%s%s --aout=alsa --brightness=2.000000 --volume=300 --fullscreen --aspect-ratio=4:3 --http-reconnect --loop" %(server, ip_broadcast) + self.main.xmlrpc.DBus("exec", remote_cmd_standalone ) + else: + newusernames.append(user) + + if access == "http": + remote_cmd_thin="vlc http://localhost%s --aout=alsa --brightness=2.000000 --volume=300 --aspect-ratio=4:3 --http-reconnect --loop" % (ip_broadcast) + + result = self.main.dbus_action.do_exec( newusernames, remote_cmd_thin ) + + if not result: + shared.error_msg ( _("Error while exec remote app:\nReason:%s") %( self.main.dbus_action.get_error_msg() ) ) + + for client in self.newallclients: + self.main.xmlrpc.vlc( client, volume, lock ) + + self.main.write_into_statusbar( _("Running in broadcast video transmission.") ) + # new mode Stop Button + if len(self.vlc_count.keys()) != 0: + count=len(self.vlc_count.keys())-1 + nextkey=self.vlc_count.keys()[count]+1 + self.vlc_count[nextkey]=uip_cmd + else: + nextkey=1 + self.vlc_count[nextkey]=uip_cmd + self.add_progressbox( {"target": "vlc", "pid":p.pid, "lock":lock, "allclients": self.newallclients, "ip":uip_cmd, "iface":eth, "key":nextkey}, _("Running in broadcast video transmission. Broadcast Nº %s") %(nextkey) ) + else: + dialog.destroy() + + + +__extclass__=VideoOne diff --git a/tcosmonitor/extensions/viewproc.py b/tcosmonitor/extensions/viewproc.py new file mode 100644 index 0000000..6d7923e --- /dev/null +++ b/tcosmonitor/extensions/viewproc.py @@ -0,0 +1,139 @@ +# -*- coding: UTF-8 -*- +# TcosMonitor version __VERSION__ +# +# Copyright (c) 2006-2011 Mario Izquierdo <mariodebian@gmail.com> +# +# This package is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# +# This package is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +""" template extension """ + +from gettext import gettext as _ +import sys + +from tcosmonitor import shared +from tcosmonitor.TcosExtensions import TcosExtension + +import gtk + +def print_debug(txt): + if shared.debug: + print >> sys.stderr, "%s::%s" % (__name__, txt) + #print("%s::%s" % (__name__, txt), file=sys.stderr) + + +class ViewProc(TcosExtension): + def register(self): + self.main.menus.register_simple( _("Show running apps of this client") , "menu_proc.png", 1, self.viewproc, "show") + + + def viewproc(self, widget, ip): + if not self.get_client(): + return + if len(self.connected_users) == 0 or self.connected_users[0] == shared.NO_LOGIN_MSG: + shared.error_msg ( _("Can't show runnings apps, user is not logged") ) + return + self.get_user_processes(ip) + + + def get_user_processes(self, ip): + """get user processes in session""" + print_debug( "get_user_processes(%s) __init__" %ip ) + #check user is connected + if not self.main.localdata.IsLogged(ip): + shared.info_msg( _("User not connected, no processes.") ) + return + + + if self.main.xmlrpc.IsStandalone(ip): + username=self.main.localdata.GetUsernameAndHost(ip) + tmp=self.main.xmlrpc.ReadInfo("get_process") + if tmp != "": + process=tmp.split('|')[0:-1] + else: + process=["PID COMMAND", "66000 can't read process list"] + else: + username=self.main.localdata.GetUsername(ip) + cmd="LANG=C ps U \"%s\" -o pid,command | /usr/lib/tcos/clean_string.sh " %(self.main.localdata.GetUserID(username)) + print_debug ( "get_user_processes(%s) cmd=%s " %(ip, cmd) ) + process=self.main.common.exe_cmd(cmd, verbose=0) + + self.main.datatxt.clean() + self.main.datatxt.insert_block( _("Running processes for user \"%s\": " ) %(username), image=shared.IMG_DIR + "info_proc.png" ) + + if self.main.config.GetVar("systemprocess") == "0": + self.main.datatxt.insert_block ( \ + _("ALERT: There are some system process hidden. Enable it in Preferences dialog.") \ + , image=shared.IMG_DIR + "icon_alert.png" ,\ + color="#f08196", size="medium" ) + + self.main.datatxt.insert_html ( """ + <br/><div style='margin-left: 135px; margin-right: 200px;background-color:#ead196;color:blue'>""" + _("Pid") + "\t" + + "\t" + _("Process command") +"</div>" ) + + counter=0 + self.main.kill_proc_buttons=None + self.main.kill_proc_buttons=[] + blabel=_("Kill this process") + + for proc in process: + is_hidden=False + if proc.split()[0]== "PID": + continue + pid=proc.split()[0] # not convert to int DBUS need string + name=" ".join(proc.split()[1:]) + name=name.replace('<','<').replace('>','>') + name=name.replace('&','&') + + if int(self.main.config.GetVar("systemprocess")) == 0: + for hidden in shared.system_process: + if hidden in name: + is_hidden=True + + if is_hidden: + continue + + kill_button=gtk.Button(label=blabel) + kill_button.connect("clicked", self.on_kill_button_click, pid, username) + kill_button.show() + self.main.kill_proc_buttons.append(kill_button) + + self.main.datatxt.insert_html(""" + <span style='background-color: red; margin-left: 5px; margin-right: 0px'> + <input type='button' name='self.main.kill_proc_buttons' index='%d' label='%s' /></span> + <span style='color: red; margin-left: 140px; margin-right: 0px'> %6s</span> + <span style='color: blue; margin-left: 350px; margin-right: 0px'> %s</span><br /> + """ %(counter, blabel, pid, name) ) + counter+=1 + + self.main.datatxt.display() + return + + def on_kill_button_click(self, widget, pid, username): + print_debug ( "on_kill_button_click() pid=%s username=%s" %(pid, username) ) + if shared.ask_msg ( _("Are you sure you want to stop this process?") ): + print_debug ( "KILL KILL KILL" ) + if username.find(":") != -1 : + usern, ip = username.split(":") + self.main.xmlrpc.newhost(ip) + self.main.xmlrpc.DBus("kill", str(pid) ) + else: + result = self.main.dbus_action.do_kill( [username] , str(pid) ) + if not result: + shared.error_msg ( _("Error while killing app:\nReason: %s") %( self.main.dbus_action.get_error_msg() ) ) + else: + print_debug ( "on_kill_button_click() KILLED ;)" ) + self.get_user_processes(self.main.selected_ip) + +__extclass__=ViewProc diff --git a/tcosmonitor/extensions/vnc.py b/tcosmonitor/extensions/vnc.py new file mode 100644 index 0000000..f8af01f --- /dev/null +++ b/tcosmonitor/extensions/vnc.py @@ -0,0 +1,513 @@ +# -*- coding: UTF-8 -*- +# TcosMonitor version __VERSION__ +# +# Copyright (c) 2006-2011 Mario Izquierdo <mariodebian@gmail.com> +# +# This package is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# +# This package is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +""" template extension """ + +from gettext import gettext as _ + +from tcosmonitor import shared +from tcosmonitor.TcosExtensions import TcosExtension + +import os +from random import Random +from time import sleep +import string +import subprocess +import signal + +from tcosmonitor.ping import PingPort + +import gtkvnc +import gtk +import traceback +import sys + +def print_debug(txt): + if shared.debug: + print >> sys.stderr, "%s::%s" % (__name__, txt) + #print("%s::%s" % (__name__, txt), file=sys.stderr) + + +class VNC(TcosExtension): + def register(self): + self.vnc_count={} + self.main.menus.register_simple( _("Connect to remote screen (VNC)"), "menu_remote.png", 1, self.vnc_simple, "vnc") + self.main.menus.register_simple( _("Demo mode (from this host)") , "menu_tiza.png", 1, self.vnc_demo_simple, "demo") + + self.main.menus.register_all( _("Enter demo mode, all connected users see my screen") , "menu_tiza.png", 1, self.vnc_demo_all, "demo") + self.vnc={} + self.vncwindow={} + self.is_fullscreen={} + + def vnc_demo_all(self, *args): + if not self.get_all_clients(): + return + # demo mode + #generate password vnc + if len(self.connected_users) == 0 or self.connected_users[0] == shared.NO_LOGIN_MSG: + shared.error_msg( _("No users logged.") ) + return + + msg=_( _("Do you want to start demo mode the following users: %s?" )%(self.connected_users_txt) ) + + if not shared.ask_msg ( msg ): + return + + passwd=''.join( Random().sample(string.letters+string.digits, 12) ) + self.main.common.exe_cmd("x11vnc -storepasswd %s %s >/dev/null 2>&1" \ + %(passwd, os.path.expanduser('~/.tcosvnc')), verbose=0, background=True ) + + # start x11vnc in local + p=subprocess.Popen(["x11vnc", "-shared", "-noshm", "-viewonly", "-forever", "-rfbauth", "%s" %( os.path.expanduser('~/.tcosvnc') ) ], shell=False, bufsize=0, close_fds=True) + + self.main.write_into_statusbar( _("Waiting for start demo mode...") ) + + # need to wait for start, PingPort loop + status = "CLOSED" + max_wait=10 + wait=0 + while status != "OPEN": + status=PingPort("127.0.0.1", 5900).get_status() + if status == "CLOSED": + sleep(1) + wait+=1 + if wait > max_wait: + break + + if status != "OPEN": + self.main.write_into_statusbar( _("Error while exec app")) + return + + total=0 + for client in self.newallclients: + self.main.xmlrpc.vnc("genpass", client, passwd ) + # get server ip + server_ip=self.main.xmlrpc.GetStandalone("get_server") + print_debug("menu_event_all() vnc server ip=%s" %(server_ip)) + # start vncviewer + self.main.xmlrpc.vnc("startclient", client, server_ip ) + total+=1 + + if total < 1: + self.main.write_into_statusbar( _("No users logged.") ) + # kill x11vnc + os.kill(p.pid, signal.SIGKILL) + else: + self.main.write_into_statusbar( _("Running in demo mode with %s clients.") %(total) ) + #server_ip=self.main.xmlrpc.GetStandalone("get_server") + #hostname=self.main.localdata.GetHostname(server_ip) + # new mode Stop Button + if len(self.vnc_count.keys()) != 0: + count=len(self.vnc_count.keys())-1 + nextkey=self.vnc_count.keys()[count]+1 + self.vnc_count[nextkey]=None + else: + nextkey=1 + self.vnc_count[nextkey]=None + self.add_progressbox( {"target": "vnc", "ip":"", "pid":p.pid, "allclients":self.newallclients, "key":nextkey}, _("Running in demo mode from server. Demo Nº %s") %(nextkey) ) + + + def vnc_simple(self, w, ip): + if not self.get_client(): + return + + if len(self.allclients_logged) == 0: + shared.error_msg( _("No user logged.") ) + return + + self.main.worker=shared.Workers(self.main, target=self.start_vnc, args=(self.allclients_logged) ) + self.main.worker.start() + + def start_vnc(self, ip): + # force kill x11vnc in client + self.main.xmlrpc.newhost(ip) + host=self.main.localdata.GetHostname(self.main.selected_ip) + + max_wait=5 + wait=0 + self.main.common.threads_enter("TcosActions:start_vnc print status msg") + self.main.write_into_statusbar( _("Connecting with %s to start VNC support") %(host) ) + self.main.common.threads_leave("TcosActions:start_vnc print status msg") + + status="OPEN" + while status != "CLOSED": + status=PingPort(ip, 5900).get_status() + self.main.xmlrpc.vnc("stopserver", ip ) + print_debug("start_vnc() waiting to kill x11vnc...") + sleep(1) + wait+=1 + if wait > max_wait: + print_debug("max_wait, returning") + # fixme show error message + return + + # gen password in thin client + passwd=''.join( Random().sample(string.letters+string.digits, 12) ) + + self.main.xmlrpc.vnc("genpass", ip, passwd) + os.system("x11vnc -storepasswd %s %s >/dev/null 2>&1" \ + %(passwd, os.path.expanduser('~/.tcosvnc')) ) + + try: + + # before starting server, vnc-controller.sh exec killall x11vnc, not needed to stop server + #self.main.xmlrpc.vnc("stopserver", ip ) + result=self.main.xmlrpc.vnc("startserver", ip) + if result.find("error") != -1: + self.main.common.threads_enter("TcosActions:start_vnc print error msg") + shared.error_msg ( _("Can't start VNC, error:\n%s") %(result) ) + self.main.common.threads_leave("TcosActions:start_vnc print error msg") + return + self.main.common.threads_enter("TcosActions:start_vnc print waiting msg") + self.main.write_into_statusbar( _("Waiting for start of VNC server...") ) + self.main.common.threads_leave("TcosActions:start_vnc print waiting msg") + + # need to wait for start, PingPort loop + + status = "CLOSED" + + wait=0 + while status != "OPEN": + status=PingPort(ip, 5900).get_status() + if status == "CLOSED": + sleep(1) + wait+=1 + if wait > max_wait: + break + if status == "OPEN": + #cmd=("LC_ALL=C LC_MESSAGES=C vncviewer --version 2>&1| grep built |grep -c \"4.1\"") + #output=self.main.common.exe_cmd(cmd) + #if output == "1": + # cmd = ("vncviewer " + ip + " -UseLocalCursor=0 -passwd %s" %os.path.expanduser('~/.tcosvnc') ) + #else: + # cmd = ("vncviewer " + ip + " -passwd %s" %os.path.expanduser('~/.tcosvnc') ) + #print_debug ( "start_process() threading \"%s\"" %(cmd) ) + #self.main.common.exe_cmd (cmd, verbose=0, background=True) + self.main.common.threads_enter("TcosActions:start_vnc print x11vnc support msg") + self.vncviewer(ip, passwd) + self.main.common.threads_leave("TcosActions:start_vnc print x11vnc support msg") + except Exception, err: + print_debug("start_vnc() Exception, error=%s"%err) + traceback.print_exc(file=sys.stderr) + self.main.common.threads_enter("TcosActions:start_vnc print x11vnc support msg") + shared.error_msg ( _("Can't start VNC, please add X11VNC support") ) + self.main.common.threads_leave("TcosActions:start_vnc print x11vnc support msg") + return + + self.main.common.threads_enter("TcosActions:start_vnc clean status msg") + self.main.write_into_statusbar( "" ) + self.main.common.threads_leave("TcosActions:start_vnc clean status msg") + + def vncviewer_destroy(self, window, ip): + try: + self.vncwindow[ip].hide() + self.vncwindow[ip].destroy() + except Exception, err: + print_debug("vncviewer_destroy() Cant hide/destroy vncviewer window, err=%s"%err) + print_debug("vncviewer_destroy() self.vnc=%s"%self.vnc) + if self.vnc.has_key(ip): + self.vnc[ip].close() + self.vnc.pop(ip) + if self.vncwindow.has_key(ip): + self.vncwindow.pop(ip) + + def vncviewer_fullcontrol(self, button, ip): + image=gtk.Image() + + if self.vnc[ip].get_read_only(): + self.vnc[ip].set_read_only(False) + button.set_label( _("Switch to view only") ) + image.set_from_stock('gtk-find', gtk.ICON_SIZE_BUTTON) + button.set_image(image) + else: + self.vnc[ip].set_read_only(True) + button.set_label( _("Switch to full control") ) + image.set_from_stock('gtk-find-and-replace', gtk.ICON_SIZE_BUTTON) + button.set_image(image) + + def vncviewer_force_resize(self, vnc, size, ip): + w, h = vnc.get_size_request() + if w == -1 or h == -1: + print_debug("_force_resize() returning w=%s h=%s ip=%s"%(w, h, ip)) + return + vnc.set_size_request(w/2, h/2) + + + def on_fullscreenbutton_click(self, button, ip): + image=gtk.Image() + if self.is_fullscreen[ip]: + self.vncwindow[ip].unfullscreen() + self.is_fullscreen[ip]=False + image.set_from_stock('gtk-fullscreen', gtk.ICON_SIZE_BUTTON) + else: + self.vncwindow[ip].fullscreen() + self.is_fullscreen[ip]=True + image.set_from_stock('gtk-leave-fullscreen', gtk.ICON_SIZE_BUTTON) + button.set_image(image) + + def vncviewer(self, ip, passwd, stoptarget=None, stopargs=None): + self.vncwindow[ip] = gtk.Window(gtk.WINDOW_TOPLEVEL) + self.vncwindow[ip].set_icon_from_file(shared.IMG_DIR + 'tcos-icon-32x32.png') + self.vncwindow[ip].set_title( _("VNC host %s") %(ip) ) + self.vncwindow[ip].connect("destroy", self.vncviewer_destroy, ip) + box1 = gtk.HBox(True, 10) + + button = gtk.Button( _("Switch to full control") ) + button.connect("clicked", self.vncviewer_fullcontrol, ip) + image=gtk.Image() + image.set_from_stock('gtk-find-and-replace', gtk.ICON_SIZE_BUTTON) + button.set_image(image) + box1.pack_start(button, False, False, 0) + button.show_all() + + fbutton = gtk.Button( _("Switch to fullscreen") ) + fbutton.connect("clicked", self.on_fullscreenbutton_click, ip) + image=gtk.Image() + image.set_from_stock('gtk-fullscreen', gtk.ICON_SIZE_BUTTON) + fbutton.set_image(image) + box1.pack_start(fbutton, False, False, 0) + fbutton.show_all() + + if stoptarget: + sbutton = gtk.Button( _("Stop") ) + sbutton.connect("clicked", stoptarget, stopargs, None) + image=gtk.Image() + image.set_from_stock('gtk-stop', gtk.ICON_SIZE_BUTTON) + sbutton.set_image(image) + box1.pack_start(sbutton, False, False, 0) + sbutton.show_all() + + lastbutton = gtk.Button( _("Quit") ) + image=gtk.Image() + image.set_from_stock('gtk-quit', gtk.ICON_SIZE_BUTTON) + lastbutton.set_image(image) + lastbutton.connect("clicked", self.vncviewer_destroy, ip) + box1.pack_start(lastbutton, False, False, 0) + lastbutton.show_all() + + self.vnc[ip]=gtkvnc.Display() + self.vnc[ip].set_credential(gtkvnc.CREDENTIAL_PASSWORD, passwd) + self.vnc[ip].set_credential(gtkvnc.CREDENTIAL_CLIENTNAME, self.main.name) + + #self.vnc[ip].connect("vnc-auth-credential", self._vnc_auth_cred, ip) + self.vnc[ip].connect("size-request", self.vncviewer_force_resize, ip) + #self.vnc[ip].connect("vnc-connected", self._vnc_connected, ip) + # this freeze GUI, search another way + #self.vnc[ip].set_tooltip_text("%s"%ip) + + self.vnc[ip].open_host(ip, '5900') + self.vnc[ip].set_scaling(True) + self.vnc[ip].set_read_only(True) + self.vnc[ip].show() + + # Show the box + box1.show() + + box2 = gtk.VBox(False, 0) + box2.pack_start(box1, False, False, 0) + box2.pack_start(self.vnc[ip], True, True, 0) + + + # Show the window + self.vncwindow[ip].add(box2) + self.vncwindow[ip].show_all() + self.is_fullscreen[ip]=False + + + def vnc_demo_simple(self, widget, ip): + if not self.get_client(): + return + + client_simple=self.connected_users_txt + + if len(self.connected_users) == 0 or self.connected_users[0] == shared.NO_LOGIN_MSG: + shared.error_msg ( _("Can't start demo mode, user is not logged") ) + return + + msg=_( _("Do you want demo mode from user %s?" ) %(client_simple) ) + if not shared.ask_msg ( msg ): + return + + if self.main.iconview.ismultiple(): + self.allclients=self.main.iconview.get_multiple() + + elif self.main.classview.ismultiple(): + self.allclients=self.main.classview.get_multiple() + + elif self.main.listview.isactive() and self.main.config.GetVar("selectedhosts") == 1: + self.allclients=self.main.listview.getmultiple() + if len(self.allclients) == 0: + self.allclients=self.main.localdata.allclients + else: + # get all clients connected + self.allclients=self.main.localdata.allclients + + # Allow one client + # if len(self.allclients) == 0: return + + # force kill x11vnc in client + self.main.xmlrpc.newhost(ip) + max_wait=5 + wait=0 + self.main.write_into_statusbar( _("Connecting with %s to start VNC support") %(client_simple) ) + + status="OPEN" + while status != "CLOSED": + status=PingPort(ip, 5900).get_status() + self.main.xmlrpc.vnc("stopserver", ip ) + print_debug("start_vnc() waiting to kill x11vnc...") + sleep(1) + wait+=1 + if wait > max_wait: + print_debug("max_wait, returning") + # fixme show error message + return + + #generate password vnc + passwd=''.join( Random().sample(string.letters+string.digits, 12) ) + self.main.common.exe_cmd("x11vnc -storepasswd %s %s >/dev/null 2>&1" \ + %(passwd, os.path.expanduser('~/.tcosvnc')), verbose=0, background=True ) + + # start x11vnc in remote host + self.main.xmlrpc.vnc("genpass", ip, passwd ) + self.main.xmlrpc.vnc("startserver", ip ) + + self.main.write_into_statusbar( _("Waiting for start demo mode from user %s...") %(client_simple) ) + + # need to wait for start, PingPort loop + status = "CLOSED" + max_wait=10 + wait=0 + while status != "OPEN": + status=PingPort(ip, 5900).get_status() + if status == "CLOSED": + sleep(1) + wait+=1 + if wait > max_wait: + break + + if status != "OPEN": + self.main.write_into_statusbar( _("Error while exec app")) + return + + # start in 1 (teacher) + newallclients=[] + total=1 + for client in self.allclients: + self.main.localdata.newhost(client) + if self.main.localdata.IsLogged(client) and client != ip: + self.main.xmlrpc.vnc("genpass", client, passwd ) + self.main.xmlrpc.vnc("startclient", client, ip ) + total+=1 + newallclients.append(client) + + if total < 1: + self.main.write_into_statusbar( _("No users logged.") ) + # kill x11vnc in host + self.main.xmlrpc.vnc("stopserver", ip ) + else: + self.main.write_into_statusbar( _("Running in demo mode with %s clients.") %(total) ) + #cmd=("LC_ALL=C LC_MESSAGES=C vncviewer --version 2>&1| grep built |grep -c \"4.1\"") + #output=self.main.common.exe_cmd(cmd) + #if output == "1": + # p=subprocess.Popen(["vncviewer", ip, "-UseLocalCursor=0", "-PasswordFile", "%s" %os.path.expanduser('~/.tcosvnc')], shell=False, bufsize=0, close_fds=True) + #else: + # p=subprocess.Popen(["vncviewer", ip, "-passwd", "%s" %os.path.expanduser('~/.tcosvnc')], shell=False, bufsize=0, close_fds=True) + + # new mode for stop button + if len(self.vnc_count.keys()) != 0: + count=len(self.vnc_count.keys())-1 + nextkey=self.vnc_count.keys()[count]+1 + self.vnc_count[nextkey]=None + else: + nextkey=1 + self.vnc_count[nextkey]=None + + stopargs={"target": "vnc", "ip": ip, "allclients":newallclients, "key":nextkey} + self.vncviewer(ip, passwd, stoptarget=self.on_progressbox_click, stopargs=stopargs) + #self.add_progressbox( {"target": "vnc", "pid":p.pid, "ip": ip, "allclients":newallclients, "key":nextkey}, _("Running in demo mode from user %(host)s. Demo Nº %(count)s") %{"host":client_simple, "count":nextkey} ) + self.add_progressbox( stopargs, _("Running in demo mode from user %(host)s. Demo Nº %(count)s") %{"host":client_simple, "count":nextkey} ) + + def on_progressbox_click(self, widget, args, box): + if box: + box.destroy() + else: + for table in self.main.progressbox.get_children(): + #[<gtk.Label>, <gtk.Button>] + # read key from label + tlabel=table.get_children()[0] + tbutton=table.get_children()[1] + key=int(tlabel.get_text().split('Nº ')[1]) + if args['key'] == key: + # we have found IP in label !!! destroy table + table.destroy() + widget=tbutton + print_debug("on_progressbox_click() widget=%s, args=%s, box=%s" %(widget, args, box) ) + + if not args['target']: + return + + try: + self.main.stop_running_actions.remove(widget) + except Exception, err: + print_debug("on_progressbox_click() can't remove widget=%s err=%s"%(widget, err)) + + if args['target'] == "vnc": + del self.vnc_count[args['key']] + if args['ip'] != "": + for client in args['allclients']: + self.main.localdata.newhost(client) + if self.main.localdata.IsLogged(client): + self.main.xmlrpc.newhost(client) + self.main.xmlrpc.vnc("stopclient", client) + # kill only in server one vncviewer + #if "pid" in args: + # os.kill(args['pid'], signal.SIGKILL) + #else: + # self.main.common.exe_cmd("killall -s KILL vncviewer", verbose=0, background=True) + + self.vncviewer_destroy(None, args['ip']) + + self.main.xmlrpc.newhost(args['ip']) + self.main.xmlrpc.vnc("stopserver", args['ip'] ) + else: + # get all users at this demo mode and not kill others demo modes, in some cases need SIGKILL + for client in args['allclients']: + self.main.localdata.newhost(client) + if self.main.localdata.IsLogged(client): + self.main.xmlrpc.newhost(client) + self.main.xmlrpc.vnc("stopclient", client) + if "pid" in args: + os.kill(args['pid'], signal.SIGKILL) + else: + self.main.common.exe_cmd("killall -s KILL x11vnc", verbose=0, background=True) + + self.main.write_into_statusbar( _("Demo mode off.") ) + + + + + +__extclass__=VNC + + + + + + diff --git a/tcosmonitor/extensions/wakeonlan.py b/tcosmonitor/extensions/wakeonlan.py new file mode 100644 index 0000000..0f827f8 --- /dev/null +++ b/tcosmonitor/extensions/wakeonlan.py @@ -0,0 +1,100 @@ +# -*- coding: UTF-8 -*- +# TcosMonitor version __VERSION__ +# +# Copyright (c) 2006-2011 Mario Izquierdo <mariodebian@gmail.com> +# +# This package is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# +# This package is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +""" template extension """ + +from gettext import gettext as _ +import sys + +from tcosmonitor import shared +from tcosmonitor.TcosExtensions import TcosExtension + +from tcosmonitor.WakeOnLan import WakeOnLan + +def print_debug(txt): + if shared.debug: + print >> sys.stderr, "%s::%s" % (__name__, txt) + #print("%s::%s" % (__name__, txt), file=sys.stderr) + + +class WOL(TcosExtension): + def register(self): + self.main.menus.register_simple( _("Boot client (WakeOnLan)") , "menu_wol.png", 0, self.wol_one, "wakeonlan") + self.main.menus.register_all( _("Boot All clients (WakeOnLan)") , "menu_wol.png", 0, self.wol_all, "wakeonlan") + + + def wol_one(self, widget, ip): + if not self.get_client(): + print_debug("wol_one() no client") + return + if self.main.config.GetVar("scan_network_method") != "static": + msg=(_("Wake On Lan only works with static list.\n\nEnable scan method \"static\" in Preferences\nand (wake on lan) support in bios of clients." )) + shared.info_msg ( msg ) + return + + msg=_( _("Do you want boot %s client?" %ip)) + if shared.ask_msg ( msg ): + data=[] + hostslist=self.main.config.GetVar("statichosts") + #eth=self.main.config.GetVar("network_interface") + if hostslist == "": + return + data=hostslist.split("#") + data=data[:-1] + for host in data: + mip, mac=host.split("|") + print_debug("wol_one() ip=%s mac=%s" %(mip, mac) ) + if mip == self.main.selected_ip: + if mac == "": + self.main.write_into_statusbar(_("No register MAC address for ip: \"%s\"")%ip) + continue + print_debug("Send magic packet to mac=%s" %mac) + if not WakeOnLan("%s"%mac): + self.main.write_into_statusbar(_("Not valid MAC address: \"%s\"")%mac) + + def wol_all(self, *args): + if self.main.config.GetVar("scan_network_method") != "static": + msg=(_("Wake On Lan only works with static list.\n\nEnable scan method \"static\" in Preferences\nand (wake on lan) support in bios of clients." )) + shared.info_msg ( msg ) + return + + msg=_( _("Do you want boot all clients?" )) + if shared.ask_msg ( msg ): + data=[] + hostslist=self.main.config.GetVar("statichosts") + #eth=self.main.config.GetVar("network_interface") + if hostslist == "": + return + data=hostslist.split("#") + data=data[:-1] + errors=[] + for host in data: + mac=host.split("|")[1] + if mac == "": + self.main.write_into_statusbar(_("No register MAC address for ip: \"%s\"")%host) + continue + print_debug("Send magic packet to mac=%s" %mac) + if not WakeOnLan("%s"%mac): + errors.append(mac) + if len(errors) >1: + print_debug("menu_event_all() errors=%s"%errors) + self.main.write_into_statusbar(_("Not valid MAC address: \"%s\"")%" ".join(errors)) + + +__extclass__=WOL |