laditools/ladi-system-log

222 lines
7.7 KiB
Python
Executable File

#!/usr/bin/python
# LADITools - Linux Audio Desktop Integration Tools
# ladi-system-log - A log viewer for your Linux Audio Desktop
# Copyright (C) 2011-2012 Alessio Treglia <quadrispro@ubuntu.com>
# Copyright (C) 2007-2010, Marc-Olivier Barre <marco@marcochapeau.org>
# Copyright (C) 2007-2009, Nedko Arnaudov <nedko@arnaudov.name>
#
# This program 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 3 of the License, or
# (at your option) any later version.
#
# This program 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, see <http://www.gnu.org/licenses/>.
import os
import sys
import signal
from subprocess import Popen, PIPE
import pty
import termios
import tty
import gettext
import argparse
from laditools import _gettext_domain
gettext.install(_gettext_domain)
from laditools import get_version_string
from laditools import LadiConfiguration
from laditools import LadiApp
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import GLib
from gi.repository import Gtk
from gi.repository import GObject
gi.require_version('Vte', '2.91')
from gi.repository import Vte
from laditools.gtk import find_data_file
timeout_add = GLib.timeout_add
# Default configuration
max_lines_default = 100
# Output the last <lines> lines
def read_last(lfile, lines):
chunk_size = lines * 60
lfile.seek(0, 2)
endpos = lfile.tell()
pos = endpos - chunk_size
if pos < 0:
pos = 0
backlog = ''
backlog_size = 0
lines += 1
while pos >= 0 and backlog_size <= lines:
lfile.seek(pos, 0)
s = lfile.read(chunk_size)
pos = pos - chunk_size
backlog_size += s.count("\n")
backlog = s + backlog
backlog = backlog.strip().split("\n")
if len(backlog) > lines:
backlog = backlog[-lines:]
lfile.seek(endpos, 0)
return backlog
class LadiSystemLog(LadiApp):
_appname = 'ladi-system-log'
_appname_long = _("LADI Log Viewer")
_appid = 'org.linuxaudio.ladi.logviewer'
_default_config = { 'max_lines' : max_lines_default }
def __init__ (self):
LadiApp.__init__(self)
self.log_files = [
{
'name': 'JACK',
'config_name': 'jackdbus_log',
'config_default': os.sep.join([os.environ['HOME'], ".log", "jack", "jackdbus.log"])
},
{
'name': 'LADISH',
'config_name': 'ladish_log',
'config_default': os.sep.join([os.environ['HOME'], ".log", "ladish", "ladish.log"])
},
{
'name': 'A2J',
'config_name': 'a2j_log',
'config_default': os.sep.join([os.environ['HOME'], ".log", "a2j", "a2j.log"])
},
]
# Handle the configuration
for log in self.log_files:
self._default_config[log['config_name']] = log['config_default']
self.global_config = LadiConfiguration (self.appname, self._default_config)
self.param_dict = self.global_config.get_config_section (self.appname)
self.connect_signals_quit()
for log in self.log_files[:]:
log['logfile_path'] = self.param_dict[log['config_name']]
# skip logfiles that dont exist
if not os.access(log['logfile_path'], os.R_OK):
self.log_files.remove(log)
sys.stderr.write( _("Skipping '%s' because it does not exist\n") % log['logfile_path'])
else:
sys.stderr.write( _("Watching %s\n") % log['logfile_path'])
sys.stderr.flush()
max_lines_text = self.param_dict['max_lines']
self.max_lines = int (max_lines_text)
# Load the glade file
uifile = find_data_file('ladi-system-log.ui')
builder = Gtk.Builder()
builder.add_from_file(uifile)
sys.stderr.write( _("Loading interface from %s\n") % uifile)
sys.stderr.flush()
# Get the ui ready for action
self.event_dict = {"on_ladilog_ui_destroy" : self.quit,
"on_ladilog_ui_delete" : self.on_delete,
"on_close_button_clicked" : self.quit,
"on_clear_button_clicked" : self.on_clear_text,
"on_purge_button_clicked" : self.on_purge}
builder.connect_signals(self.event_dict)
self.ui = ui = builder.get_object("ladilog_ui")
self.logview_notebook = builder.get_object ("ladilog_notebook")
# Create our terminal and display it
for log in self.log_files:
log['scrolled_window'] = sw = Gtk.ScrolledWindow()
log['term'] = term = Vte.Terminal.new ()
sw.set_policy(hscrollbar_policy=Gtk.PolicyType.AUTOMATIC,
vscrollbar_policy=Gtk.PolicyType.ALWAYS)
sw.add(term)
sw.show()
term.set_scroll_on_output(True)
log["tab_label"] = Gtk.Label(label=log["name"])
self.logview_notebook.append_page(log["scrolled_window"],
log["tab_label"])
# Make it do something...
for log in self.log_files:
try:
log['log_file'] = open(log['logfile_path'], "r")
sys.stderr.write (_("Opening %s...\n") % log['logfile_path'])
lines = read_last(log['log_file'], self.max_lines)
for line in lines:
line = line.strip('\r\n') + '\r\n';
log["term"].feed(bytes(line, "utf-8"))
except ValueError:
sys.stderr.write( _("You called Popen with invalid arguments... dumbass\n") )
except:
sys.stderr.write( _("Unexpected error: %s\n") % (sys.exc_info ()[0]))
finally:
sys.stderr.flush()
self.auto_updater = timeout_add(250, self.update, None)
def update(self, user_data = None):
# Append latest output to the buffer
for log in self.log_files:
line = log['log_file'].readline()
while line:
log["term"].feed(bytes(line + '\r', "utf-8"))
line = log['log_file'].readline()
log['log_file'].seek(log['log_file'].tell())
return True
def on_delete(self, widget=None, data=None):
return False
def quit (self, *args, **kwargs):
self.global_config.set_config_section (self.appname, self.param_dict)
self.global_config.save ()
Gtk.main_quit ()
def on_clear_text (self, data=None):
current_view = self.logview_notebook.get_current_page ()
self.log_files[current_view]["term"].feed(bytes("\033[2J\033[;f", "utf-8"))
def on_purge (self, data=None):
current_view = self.logview_notebook.get_current_page ()
# Opens the file in write anew mode thus clearing the file and close it right away
open (self.log_files[current_view]['logfile_path'], "w+")
self.log_files[current_view]["term"].feed(bytes("\033[2J\033[;f", "utf-8"))
def run (self):
self.ui.show_all()
Gtk.main ()
if __name__ == '__main__':
parser = argparse.ArgumentParser(description=_('JACK, ladish and a2jmidid log viewer'),
epilog=_('This program is part of the LADITools suite.'))
parser.add_argument('--version', action='version', version="%(prog)s " + get_version_string())
parser.parse_args()
Gtk.init(None)
LadiSystemLog().run()
sys.exit(0)