xref: /aosp_15_r20/external/trace-cmd/python/tracecmdgui.py (revision 58e6ee5f017f6a8912852c892d18457e4bafb554)
1#
2# Copyright (C) International Business Machines  Corp., 2009
3#
4# This program is free software; you can redistribute it and/or modify
5# it under the terms of the GNU General Public License as published by
6# the Free Software Foundation; either version 2 of the License, or
7# (at your option) any later version.
8#
9# This program is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12# GNU General Public License for more details.
13#
14# You should have received a copy of the GNU General Public License
15# along with this program; if not, write to the Free Software
16# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17#
18# 2009-Dec-31:	Initial version by Darren Hart <[email protected]>
19#
20
21import gobject #delete me ?
22import time
23import sys
24import gtk
25from tracecmd import *
26from ctracecmdgui import *
27
28"""
29Python interface for tracecmd GTK widgets
30
31Python tracecmd applications should be written to this interface. It will be
32updated as the tracecmd gui C API changes and try to minimze the impact to
33python applications. The ctracecmdgui Python module is automatically generated
34using SWIG and it is recommended applications not use it directly.
35"""
36
37# In a "real" app these width should be determined at runtime testing max length
38# strings in the current font.
39TS_COL_W    = 150
40CPU_COL_W   = 35
41EVENT_COL_W = 150
42PID_COL_W   = 75
43COMM_COL_W  = 250
44
45
46def timing(func):
47  def wrapper(*arg):
48      start = time.time()
49      ret = func(*arg)
50      end = time.time()
51      print('@%s took %0.3f s' % (func.func_name, (end-start)))
52      return ret
53  return wrapper
54
55
56class EventStore(gtk.GenericTreeModel):
57    # FIXME: get these from the C code: trace_view_store->column_types ...
58    @timing
59    def __init__(self, trace):
60        gtk.GenericTreeModel.__init__(self)
61        self.trace = trace
62        self.cstore = trace_view_store_new(trace.handle)
63        self.gtk_cstore = trace_view_store_as_gtk_tree_model(self.cstore)
64        num_rows = trace_view_store_num_rows_get(self.cstore)
65        print("Loaded %d events from trace" % (num_rows))
66
67    def on_get_flags(self):
68        return trace_view_store_get_flags(self.gtk_cstore)
69
70    def on_get_n_columns(self):
71        return trace_view_store_get_n_columns(self.gtk_cstore)
72
73    def on_get_column_type(self, col):
74        # I couldn't figure out how to convert the C GType into the python
75        # GType. The current typemap converts the C GType into the python type,
76        # which is what this function is supposed to return anyway.
77        pytype = trace_view_store_get_column_type(self.gtk_cstore, col)
78        return pytype
79
80    def on_get_iter(self, path):
81        if len(path) > 1 and path[1] != 1:
82            return None
83        n = path[0]
84        rec = trace_view_store_get_row(self.cstore, n)
85        return rec
86
87    def on_get_path(self, rec):
88        if not rec:
89            return None
90        start_row = trace_view_store_start_row_get(self.cstore)
91        return (trace_view_record_pos_get(rec) - start_row,)
92
93    def on_get_value(self, rec, col):
94        # FIXME: write SWIG wrapper to marshal the Gvalue and wrap the rec in an
95        # Iter
96        pass
97        #return trace_view_store_get_value_py(self.cstore, rec, col)
98
99    def on_iter_next(self, rec):
100        pos = trace_view_record_pos_get(rec)
101        start_row = trace_view_store_start_row_get(self.cstore)
102        return trace_view_store_get_row(self.cstore, pos - start_row + 1)
103
104    def on_iter_children(self, rec):
105        if rec:
106            return None
107        return trace_view_store_get_row(self.cstore, 0)
108
109    def on_iter_has_child(self, rec):
110        return False
111
112    def on_iter_n_children(self, rec):
113        if rec:
114            return 0
115        return trace_view_store_num_rows_get(self.cstore)
116
117    def on_iter_nth_child(self, rec, n):
118        if rec:
119            return None
120        return trace_view_store_get_row(self.cstore, n)
121
122    def on_iter_parent(self, child):
123        return None
124
125    def get_event(self, iter):
126        path = self.get_path(iter)
127        if not path:
128            return None
129        rec = trace_view_store_get_row(self.cstore, path[0])
130        if not rec:
131            return None
132        ev = self.trace.read_event_at(trace_view_record_offset_get(rec))
133        return ev
134
135
136class EventView(gtk.TreeView):
137    def __init__(self, model):
138        gtk.TreeView.__init__(self, model)
139        self.set_fixed_height_mode(True)
140
141        ts_col = gtk.TreeViewColumn("Time (s)")
142        ts_col.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
143        ts_col.set_fixed_width(TS_COL_W)
144        ts_cell = gtk.CellRendererText()
145        ts_col.pack_start(ts_cell, False)
146        ts_col.set_cell_data_func(ts_cell, self.data_func, "ts")
147        self.append_column(ts_col)
148
149        cpu_col = gtk.TreeViewColumn("CPU")
150        cpu_col.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
151        cpu_col.set_fixed_width(CPU_COL_W)
152        cpu_cell = gtk.CellRendererText()
153        cpu_col.pack_start(cpu_cell, False)
154        cpu_col.set_cell_data_func(cpu_cell, self.data_func, "cpu")
155        self.append_column(cpu_col)
156
157        event_col = gtk.TreeViewColumn("Event")
158        event_col.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
159        event_col.set_fixed_width(EVENT_COL_W)
160        event_cell = gtk.CellRendererText()
161        event_col.pack_start(event_cell, False)
162        event_col.set_cell_data_func(event_cell, self.data_func, "event")
163        self.append_column(event_col)
164
165        pid_col = gtk.TreeViewColumn("PID")
166        pid_col.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
167        pid_col.set_fixed_width(PID_COL_W)
168        pid_cell = gtk.CellRendererText()
169        pid_col.pack_start(pid_cell, False)
170        pid_col.set_cell_data_func(pid_cell, self.data_func, "pid")
171        self.append_column(pid_col)
172
173        comm_col = gtk.TreeViewColumn("Comm")
174        comm_col.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
175        comm_col.set_fixed_width(COMM_COL_W)
176        comm_cell = gtk.CellRendererText()
177        comm_col.pack_start(comm_cell, False)
178        comm_col.set_cell_data_func(comm_cell, self.data_func, "comm")
179        self.append_column(comm_col)
180
181    def data_func(self, col, cell, model, iter, data):
182        ev = model.get_event(iter)
183        #ev = model.get_value(iter, 0)
184        if not ev:
185            return False
186
187        if data == "ts":
188            cell.set_property("markup", "%d.%d" % (ev.ts/1000000000,
189                                                   ev.ts%1000000000))
190        elif data == "cpu":
191            cell.set_property("markup", ev.cpu)
192        elif data == "event":
193            cell.set_property("markup", ev.name)
194        elif data == "pid":
195            cell.set_property("markup", ev.pid)
196        elif data == "comm":
197            cell.set_property("markup", ev.comm)
198        else:
199            print("Unknown Column:", data)
200            return False
201
202        return True
203
204
205class EventViewerApp(gtk.Window):
206    def __init__(self, trace):
207        gtk.Window.__init__(self)
208
209        self.set_size_request(650, 400)
210        self.set_position(gtk.WIN_POS_CENTER)
211
212        self.connect("destroy", gtk.main_quit)
213        self.set_title("Event Viewer")
214
215        store = EventStore(trace)
216        view = EventView(store)
217
218        sw = gtk.ScrolledWindow()
219        sw.set_policy(gtk.POLICY_NEVER, gtk.POLICY_ALWAYS)
220        sw.add(view)
221
222        # track how often the treeview data_func is called
223        self.add(sw)
224        self.show_all()
225
226
227# Basic builtin test, execute module directly
228if __name__ == "__main__":
229    if len(sys.argv) >=2:
230        filename = sys.argv[1]
231    else:
232        filename = "trace.dat"
233
234    print("Initializing trace...")
235    trace = Trace(filename)
236    print("Initializing app...")
237    app = EventViewerApp(trace)
238    print("Go!")
239    gtk.main()
240