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