3 # LADITools - Linux Audio Desktop Integration Tools
4 # ladilog - A log viewer for your Linux Audio Desktop
5 # Copyright (C) 2011-2012 Alessio Treglia <quadrispro@ubuntu.com>
6 # Copyright (C) 2007-2010, Marc-Olivier Barre <marco@marcochapeau.org>
7 # Copyright (C) 2007-2009, Nedko Arnaudov <nedko@arnaudov.name>
9 # This program is free software: you can redistribute it and/or modify
10 # it under the terms of the GNU General Public License as published by
11 # the Free Software Foundation, either version 3 of the License, or
12 # (at your option) any later version.
14 # This program is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 # GNU General Public License for more details.
19 # You should have received a copy of the GNU General Public License
20 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25 from subprocess
import Popen
, PIPE
27 from signal
import SIGTERM
33 sig_handler
= signal
.getsignal(signal
.SIGTERM
)
34 signal
.signal(signal
.SIGINT
, sig_handler
)
38 imp
.find_module('laditools')
40 # Running from the build tree?
41 sys
.path
.insert(0, os
.path
.join(sys
.path
[0], os
.pardir
))
43 from laditools
import _gettext_domain
44 gettext
.install(_gettext_domain
)
46 from laditools
import get_version_string
47 from laditools
import LadiConfiguration
49 from gi
.repository
import Gtk
50 from gi
.repository
import GObject
51 from gi
.repository
import Vte
53 from laditools
.gtk
import find_data_file
55 timeout_add
= GObject
.timeout_add
57 # Default configuration
58 max_lines_default
= 100
60 # Output the last <lines> lines
61 def read_last(lfile
, lines
):
62 chunk_size
= lines
* 60
65 pos
= endpos
- chunk_size
71 while pos
>= 0 and backlog_size
<= lines
:
73 s
= lfile
.read(chunk_size
)
74 pos
= pos
- chunk_size
75 backlog_size
+= s
.count("\n")
77 backlog
= backlog
.strip().split("\n")
78 if len(backlog
) > lines
:
79 backlog
= backlog
[-lines
:]
83 class ladilog(object):
88 'config_name': 'jackdbus_log',
89 'config_default': os
.sep
.join([os
.environ
['HOME'], ".log", "jack", "jackdbus.log"])
93 'config_name': 'ladish_log',
94 'config_default': os
.sep
.join([os
.environ
['HOME'], ".log", "ladish", "ladish.log"])
98 'config_name': 'a2j_log',
99 'config_default': os
.sep
.join([os
.environ
['HOME'], ".log", "a2j", "a2j.log"])
102 # Handle the configuration
103 self
.global_config
= LadiConfiguration ()
104 self
.param_dict
= self
.global_config
.get_config_section ('ladilog')
106 for log
in self
.log_files
:
107 if self
.param_dict
!= None:
108 if log
['config_name'] not in self
.param_dict
:
109 self
.param_dict
[log
['config_name']] = log
['config_default']
112 self
.param_dict
[log
['config_name']] = log
['config_default']
114 if 'max_lines' not in self
.param_dict
:
115 self
.param_dict
['max_lines'] = max_lines_default
117 for log
in self
.log_files
[:]:
118 log
['logfile_path'] = self
.param_dict
[log
['config_name']]
119 # skip logfiles that dont exist
120 if not os
.access(log
['logfile_path'], os
.R_OK
):
121 self
.log_files
.remove(log
)
122 sys
.stderr
.write( _("Skipping '%s' because it does not exist\n") % log
['logfile_path'])
124 sys
.stderr
.write( _("Watching %s\n") % log
['logfile_path'])
127 max_lines_text
= self
.param_dict
['max_lines']
128 self
.max_lines
= int (max_lines_text
)
129 # Load the glade file
130 builder
= Gtk
.Builder()
131 builder
.add_from_file(find_data_file("ladilog_ui.ui"))
132 sys
.stderr
.write( _("Loading interface from %s\n") % find_data_file("ladilog_ui.ui"))
134 # Get the ui ready for action
135 self
.event_dict
= {"on_ladilog_ui_destroy" : self
.on_quit
,
136 "on_ladilog_ui_delete" : self
.on_delete
,
137 "on_close_button_clicked" : self
.on_quit
,
138 "on_clear_button_clicked" : self
.on_clear_text
,
139 "on_purge_button_clicked" : self
.on_purge
}
140 builder
.connect_signals(self
.event_dict
)
142 self
.ui
= ui
= builder
.get_object("ladilog_ui")
143 self
.logview_notebook
= builder
.get_object ("ladilog_notebook")
144 # Create our terminal and display it
145 for log
in self
.log_files
:
146 log
['scrolled_window'] = sw
= Gtk
.ScrolledWindow()
147 log
['term'] = term
= Vte
.Terminal
.new ()
148 sw
.set_policy(hscrollbar_policy
=Gtk
.PolicyType
.AUTOMATIC
,
149 vscrollbar_policy
=Gtk
.PolicyType
.ALWAYS
)
152 term
.set_scroll_on_output(True)
153 log
["tab_label"] = Gtk
.Label(label
=log
["name"])
155 self
.logview_notebook
.append_page(log
["scrolled_window"],
158 # Make it do something...
159 for log
in self
.log_files
:
161 log
['log_file'] = open(log
['logfile_path'], "rb")
162 sys
.stderr
.write (_("Opening %s...\n") % log
['logfile_path'])
163 lines
= read_last(log
['log_file'], self
.max_lines
)
165 line
= line
.strip('\r\n') + '\r\n'
166 log
["term"].feed(line
, -1)
168 sys
.stderr
.write( _("You called Popen with invalid arguments... dumbass\n") )
170 sys
.stderr
.write( _("Unexpected error: %s\n") % (sys
.exc_info ()[0]))
175 self
.auto_updater
= timeout_add(250, self
.update
)
178 # Append latest output to the buffer
179 for log
in self
.log_files
:
180 line
= log
['log_file'].readline()
182 log
["term"].feed(line
+ '\r', -1)
183 line
= log
['log_file'].readline()
184 log
['log_file'].seek(log
['log_file'].tell())
187 def on_delete(self
, widget
=None, data
=None):
190 def on_quit (self
, data
=None):
193 def on_clear_text (self
, data
=None):
194 current_view
= self
.logview_notebook
.get_current_page ()
195 self
.log_files
[current_view
]["term"].feed ("\033[2J\033[;f", -1)
197 def on_purge (self
, data
=None):
198 current_view
= self
.logview_notebook
.get_current_page ()
199 # Opens the file in write anew mode thus clearing the file and close it right away
200 open (self
.log_files
[current_view
]['logfile_path'], "w+")
201 self
.log_files
[current_view
]["term"].feed ("\033[2J\033[;f", -1)
205 self
.global_config
.set_config_section ("ladilog", self
.param_dict
)
206 self
.global_config
.save ()
210 if __name__
== '__main__':
211 parser
= argparse
.ArgumentParser(description
=_('JACK, ladish and a2jmidid log viewer'),
212 epilog
=_('This program is part of the LADITools suite.'))
213 parser
.add_argument('--version', action
='version', version
="%(prog)s " + get_version_string())
218 #except Exception, e:
219 # error = Gtk.MessageDialog(None,
220 # Gtk.DialogFlags.MODAL,
221 # Gtk.MessageType.ERROR,
222 # Gtk.ButtonsType.OK,
223 # _("Unexpected error\n\n") + repr(e))