c1b44ff38b51c3b6d056bb7d70a896f4c4bbf876
[lttv.git] / lttv / modules / gui / detailedevents / events.c
1 /* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2003-2004 Mathieu Desnoyers and XangXiu Yang
3 * 2005 Mathieu Desnoyers
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License Version 2 as
7 * published by the Free Software Foundation;
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., 59 Temple Place - Suite 330, Boston,
17 * MA 02111-1307, USA.
18 */
19
20
21 //*! \defgroup GuiEvents libGuiEvents: The GUI Events display plugin */
22 /*\@{*/
23
24 /*! \file GuiEvents.c
25 * \brief Graphical plugin for showing events.
26 *
27 * This plugin lists all the events contained in the current time interval
28 * in a list.
29 *
30 * This plugin adds a Events Viewer functionnality to Linux TraceToolkit
31 * GUI when this plugin is loaded. The init and destroy functions add the
32 * viewer's insertion menu item and toolbar icon by calling viewer.h's
33 * API functions. Then, when a viewer's object is created, the constructor
34 * creates ans register through API functions what is needed to interact
35 * with the lttvwindow.
36 *
37 * Authors : Mathieu Desnoyers and XangXiu Yang, June to December 2003
38 * Inspired from original LTT, made by Karim Yaghmour
39 *
40 * Mostly rewritten by Mathieu Desnoyers, August 2005.
41 */
42
43 #ifdef HAVE_CONFIG_H
44 #include <config.h>
45 #endif
46
47 #include <math.h>
48
49 #include <glib.h>
50 #include <glib/gprintf.h>
51 #include <gtk/gtk.h>
52 #include <gdk/gdk.h>
53 #include <gdk/gdkx.h>
54 #include <string.h>
55
56 #include <ltt/ltt.h>
57 #include <ltt/event.h>
58 #include <ltt/trace.h>
59 #include <lttv/lttv.h>
60 #include <lttv/module.h>
61 #include <lttv/hook.h>
62 #include <lttv/traceset.h>
63 #include <lttv/state.h>
64 #ifdef BABEL_CLEANUP
65 #include <lttv/filter.h>
66 #endif //babel_cleanup
67 #include <lttv/print.h>
68 #include <lttvwindow/lttvwindow.h>
69 #include <lttvwindow/lttvwindowtraces.h>
70 #include <lttvwindow/lttv_plugin_tab.h>
71 #include <lttvwindow/support.h>
72 #include "lttv_plugin_evd.h"
73
74 #include "events.h"
75 #include "hGuiEventsInsert.xpm"
76
77 #define g_info(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, format)
78
79 #ifndef g_debug
80 #define g_debug(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, format)
81 #endif
82
83 #define abs(a) (((a)<0)?(-a):(a))
84 #define max(a,b) ((a)>(b)?(a):(b))
85 #define min(a,b) ((a)<(b)?(a):(b))
86
87 /** Array containing instanced objects. Used when module is unloaded */
88 static GSList *g_event_viewer_data_list = NULL ;
89
90 typedef enum _ScrollDirection{
91 SCROLL_STEP_UP,
92 SCROLL_STEP_DOWN,
93 SCROLL_PAGE_UP,
94 SCROLL_PAGE_DOWN,
95 SCROLL_JUMP,
96 SCROLL_NONE
97 } ScrollDirection;
98
99 /** hook functions for update time interval, current time ... */
100 gboolean update_current_time(void * hook_data, void * call_data);
101 gboolean update_current_position(void * hook_data, void * call_data);
102 //gboolean show_event_detail(void * hook_data, void * call_data);
103 gboolean traceset_changed(void * hook_data, void * call_data);
104 gboolean timespan_changed(void * hook_data, void * call_data);
105 #ifdef BABEL_CLEANUP
106 gboolean filter_changed(void * hook_data, void * call_data);
107 #endif // babel_cleanup
108 static void request_background_data(EventViewerData *event_viewer_data);
109
110 //! Event Viewer's constructor hook
111 GtkWidget *h_gui_events(LttvPlugin *plugin);
112 //! Event Viewer's constructor
113 EventViewerData *gui_events(LttvPluginTab *ptab);
114 //! Event Viewer's destructor
115 void gui_events_destructor(gpointer data);
116 void gui_events_free(gpointer data);
117
118 static gboolean
119 header_size_allocate(GtkWidget *widget,
120 GtkAllocation *allocation,
121 gpointer user_data);
122
123 void tree_v_set_cursor(EventViewerData *event_viewer_data);
124 void tree_v_get_cursor(EventViewerData *event_viewer_data);
125 static void redraw(EventViewerData *event_viewer_data);
126
127 /* Prototype for selection handler callback */
128 static void tree_selection_changed_cb (GtkTreeSelection *selection,
129 gpointer data);
130 static void v_scroll_cb (GtkAdjustment *adjustment, gpointer data);
131 static void tree_v_size_allocate_cb (GtkWidget *widget, GtkAllocation *alloc,
132 gpointer data);
133 static void tree_v_size_request_cb (GtkWidget *widget,
134 GtkRequisition *requisition, gpointer data);
135 static void tree_v_cursor_changed_cb (GtkWidget *widget, gpointer data);
136 static void tree_v_move_cursor_cb (GtkWidget *widget, GtkMovementStep arg1,
137 gint arg2, gpointer data);
138 static void filter_button (GtkToolButton *toolbutton,
139 gpointer user_data);
140 static gboolean tree_v_scroll_handler (GtkWidget *widget, GdkEventScroll *event, gpointer data);
141 static gboolean key_handler(GtkWidget *widget, GdkEventKey *event,
142 gpointer user_data);
143
144 static void adjust_event_viewer(double time, EventViewerData *event_viewer_data);
145
146 int event_hook(void *hook_data, void *call_data);
147
148 /* Enumeration of the columns */
149 enum
150 {
151 TRACE_NAME_COLUMN,
152 CPUID_COLUMN,
153 EVENT_COLUMN,
154 TIME_S_COLUMN,
155 TIME_NS_COLUMN,
156 PID_COLUMN,
157 EVENT_DESCR_COLUMN,
158 POSITION_COLUMN,
159 N_COLUMNS
160 };
161
162 /**
163 * Event Viewer's constructor hook
164 *
165 * This constructor is given as a parameter to the menuitem and toolbar button
166 * registration. It creates the list.
167 * @param parent_window A pointer to the parent window.
168 * @return The widget created.
169 */
170 GtkWidget *
171 h_gui_events(LttvPlugin *plugin)
172 {
173 LttvPluginTab *ptab = LTTV_PLUGIN_TAB(plugin);
174 EventViewerData* event_viewer_data = gui_events(ptab) ;
175 if(event_viewer_data)
176 return event_viewer_data->top_widget;
177 else return NULL;
178
179 }
180
181 /**
182 * Event Viewer's constructor
183 *
184 * This constructor is used to create EventViewerData data structure.
185 * @return The Event viewer data created.
186 */
187 EventViewerData *
188 gui_events(LttvPluginTab *ptab)
189 {
190 /*To disable the error bell when we reach the end(or the top) of the list of
191 event. Since we overload the management of the list*/
192 GtkSettings* gtk_settings = gtk_settings_get_default();
193 g_object_set(gtk_settings, "gtk-error-bell", FALSE, NULL);
194
195
196 LttTime end;
197 GtkTreeViewColumn *column;
198 GtkCellRenderer *renderer;
199 EventViewerData* event_viewer_data = g_new(EventViewerData,1);
200 LttvPluginEVD *plugin_evd = g_object_new(LTTV_TYPE_PLUGIN_EVD, NULL);
201 GtkTooltips *tooltips = gtk_tooltips_new();
202 plugin_evd->evd = event_viewer_data;
203 Tab *tab = ptab->tab;
204 event_viewer_data->tab = tab;
205 event_viewer_data->ptab = ptab;
206 GtkWidget *tmp_toolbar_icon;
207
208 LttvTraceset *ts =lttvwindow_get_traceset(event_viewer_data->tab);
209
210 event_viewer_data->event_hooks = lttv_hooks_new();
211 lttv_hooks_add(event_viewer_data->event_hooks,
212 event_hook,
213 event_viewer_data,
214 LTTV_PRIO_DEFAULT);
215
216 lttvwindow_register_current_time_notify(tab,
217 update_current_time,event_viewer_data);
218 lttvwindow_register_current_position_notify(tab,
219 update_current_position,event_viewer_data);
220 lttvwindow_register_traceset_notify(tab,
221 traceset_changed,event_viewer_data);
222 lttvwindow_register_timespan_notify(tab,
223 timespan_changed,event_viewer_data);
224 #ifdef BABEL_CLEANUP
225 lttvwindow_register_filter_notify(tab,
226 filter_changed, event_viewer_data);
227 #endif
228 lttvwindow_register_redraw_notify(tab,
229 evd_redraw_notify, event_viewer_data);
230 event_viewer_data->scroll_win = gtk_scrolled_window_new (NULL, NULL);
231 gtk_widget_show (event_viewer_data->scroll_win);
232 gtk_scrolled_window_set_policy(
233 GTK_SCROLLED_WINDOW(event_viewer_data->scroll_win),
234 GTK_POLICY_AUTOMATIC, GTK_POLICY_NEVER);
235
236 event_viewer_data->currently_selected_position =
237 lttv_traceset_create_current_position(ts);
238 event_viewer_data->first_event =
239 lttv_traceset_create_current_position(ts);
240 event_viewer_data->last_event =
241 lttv_traceset_create_current_position(ts);
242 event_viewer_data->main_win_filter = lttvwindow_get_filter(tab);
243
244 event_viewer_data->update_cursor = TRUE;
245 event_viewer_data->report_position = TRUE;
246
247 event_viewer_data->last_tree_update_time = 0;
248
249 event_viewer_data->init_done = 0;
250
251 /* Create a model for storing the data list */
252 event_viewer_data->store_m = gtk_list_store_new (
253 N_COLUMNS, /* Total number of columns */
254 G_TYPE_STRING, /* Trace name */
255 G_TYPE_UINT, /* CPUID */
256 G_TYPE_STRING, /* Event */
257 G_TYPE_UINT, /* Time s */
258 G_TYPE_UINT, /* Time ns */
259 G_TYPE_INT, /* PID */
260 G_TYPE_STRING, /* Event's description */
261 G_TYPE_POINTER);/* Position (not shown) */
262
263 event_viewer_data->pos = g_ptr_array_sized_new(10);
264
265 /* Create the viewer widget for the columned list */
266 event_viewer_data->tree_v =
267 gtk_tree_view_new_with_model (GTK_TREE_MODEL (event_viewer_data->store_m));
268
269 g_signal_connect (G_OBJECT (event_viewer_data->tree_v), "size-allocate",
270 G_CALLBACK (tree_v_size_allocate_cb),
271 event_viewer_data);
272 g_signal_connect (G_OBJECT (event_viewer_data->tree_v), "size-request",
273 G_CALLBACK (tree_v_size_request_cb),
274 event_viewer_data);
275
276 g_signal_connect (G_OBJECT (event_viewer_data->tree_v), "cursor-changed",
277 G_CALLBACK (tree_v_cursor_changed_cb),
278 event_viewer_data);
279
280 g_signal_connect (G_OBJECT (event_viewer_data->tree_v), "move-cursor",
281 G_CALLBACK (tree_v_move_cursor_cb),
282 event_viewer_data);
283
284 g_signal_connect (G_OBJECT(event_viewer_data->tree_v), "key-press-event",
285 G_CALLBACK(key_handler),
286 event_viewer_data);
287
288 g_signal_connect (G_OBJECT(event_viewer_data->tree_v), "scroll-event",
289 G_CALLBACK(tree_v_scroll_handler),
290 event_viewer_data);
291
292
293
294 // Use on each column!
295 //gtk_tree_view_column_set_sizing(event_viewer_data->tree_v,
296 //GTK_TREE_VIEW_COLUMN_FIXED);
297
298 /* The view now holds a reference. We can get rid of our own
299 * reference */
300 g_object_unref (G_OBJECT (event_viewer_data->store_m));
301
302
303 /* Create a column, associating the "text" attribute of the
304 * cell_renderer to the first column of the model */
305 /* Columns alignment : 0.0 : Left 0.5 : Center 1.0 : Right */
306 renderer = gtk_cell_renderer_text_new ();
307 column = gtk_tree_view_column_new_with_attributes ("Trace",
308 renderer,
309 "text", TRACE_NAME_COLUMN,
310 NULL);
311 gtk_tree_view_column_set_alignment (column, 0.0);
312 gtk_tree_view_column_set_fixed_width (column, 120);
313 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data->tree_v),
314 column);
315
316 event_viewer_data->button = column->button;
317
318 g_signal_connect (G_OBJECT(event_viewer_data->button),
319 "size-allocate",
320 G_CALLBACK(header_size_allocate),
321 (gpointer)event_viewer_data);
322
323 renderer = gtk_cell_renderer_text_new ();
324 column = gtk_tree_view_column_new_with_attributes ("CPUID",
325 renderer,
326 "text", CPUID_COLUMN,
327 NULL);
328 gtk_tree_view_column_set_alignment (column, 0.0);
329 gtk_tree_view_column_set_fixed_width (column, 45);
330 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data->tree_v),
331 column);
332
333 renderer = gtk_cell_renderer_text_new ();
334 column = gtk_tree_view_column_new_with_attributes ("Event",
335 renderer,
336 "text", EVENT_COLUMN,
337 NULL);
338 gtk_tree_view_column_set_alignment (column, 0.0);
339 gtk_tree_view_column_set_fixed_width (column, 120);
340 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data->tree_v),
341 column);
342
343 renderer = gtk_cell_renderer_text_new ();
344 column = gtk_tree_view_column_new_with_attributes ("Time (s)",
345 renderer,
346 "text", TIME_S_COLUMN,
347 NULL);
348 gtk_tree_view_column_set_alignment (column, 1.0);
349 gtk_tree_view_column_set_fixed_width (column, 120);
350 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data->tree_v),
351 column);
352
353 renderer = gtk_cell_renderer_text_new ();
354 column = gtk_tree_view_column_new_with_attributes ("Time (ns)",
355 renderer,
356 "text", TIME_NS_COLUMN,
357 NULL);
358 gtk_tree_view_column_set_alignment (column, 1.0);
359 gtk_tree_view_column_set_fixed_width (column, 120);
360 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data->tree_v),
361 column);
362
363
364 renderer = gtk_cell_renderer_text_new ();
365 column = gtk_tree_view_column_new_with_attributes ("PID",
366 renderer,
367 "text", PID_COLUMN,
368 NULL);
369 gtk_tree_view_column_set_alignment (column, 1.0);
370 gtk_tree_view_column_set_fixed_width (column, 45);
371 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data->tree_v),
372 column);
373
374 renderer = gtk_cell_renderer_text_new ();
375 column = gtk_tree_view_column_new_with_attributes ("Event Description",
376 renderer,
377 "text", EVENT_DESCR_COLUMN,
378 NULL);
379 gtk_tree_view_column_set_alignment (column, 0.0);
380 gtk_tree_view_append_column (GTK_TREE_VIEW (event_viewer_data->tree_v),
381 column);
382
383
384 /* Setup the selection handler */
385 event_viewer_data->select_c =
386 gtk_tree_view_get_selection (GTK_TREE_VIEW (event_viewer_data->tree_v));
387 gtk_tree_selection_set_mode (event_viewer_data->select_c,
388 GTK_SELECTION_SINGLE);
389 g_signal_connect (G_OBJECT (event_viewer_data->select_c), "changed",
390 G_CALLBACK (tree_selection_changed_cb),
391 event_viewer_data);
392
393 gtk_container_add (GTK_CONTAINER (event_viewer_data->scroll_win),
394 event_viewer_data->tree_v);
395
396 event_viewer_data->hbox_v = gtk_hbox_new(0, 0);
397 event_viewer_data->top_widget = event_viewer_data->hbox_v;
398 plugin_evd->parent.top_widget = event_viewer_data->hbox_v;
399
400 event_viewer_data->toolbar = gtk_toolbar_new();
401 gtk_toolbar_set_orientation(GTK_TOOLBAR(event_viewer_data->toolbar),
402 GTK_ORIENTATION_VERTICAL);
403
404 tmp_toolbar_icon = create_pixmap (main_window_get_widget(tab),
405 "guifilter16x16.png");
406 gtk_widget_show(tmp_toolbar_icon);
407 event_viewer_data->button_filter = gtk_tool_button_new(tmp_toolbar_icon,
408 "Filter");
409 g_signal_connect (G_OBJECT(event_viewer_data->button_filter),
410 "clicked",
411 G_CALLBACK (filter_button),
412 (gpointer)plugin_evd);
413 gtk_tool_item_set_tooltip(GTK_TOOL_ITEM(event_viewer_data->button_filter),
414 tooltips, "Open the filter window", NULL);
415 gtk_toolbar_insert(GTK_TOOLBAR(event_viewer_data->toolbar),
416 event_viewer_data->button_filter,
417 0);
418 gtk_toolbar_set_style(GTK_TOOLBAR(event_viewer_data->toolbar),
419 GTK_TOOLBAR_ICONS);
420 gtk_box_pack_start(GTK_BOX(event_viewer_data->hbox_v),
421 event_viewer_data->toolbar, FALSE, FALSE, 0);
422 event_viewer_data->filter = NULL;
423
424 gtk_box_pack_start(GTK_BOX(event_viewer_data->hbox_v),
425 event_viewer_data->scroll_win, TRUE, TRUE, 0);
426
427 gtk_container_set_border_width(GTK_CONTAINER(event_viewer_data->hbox_v), 1);
428
429 /* Create vertical scrollbar and pack it */
430 event_viewer_data->vscroll_vc = gtk_vscrollbar_new(NULL);
431 gtk_range_set_update_policy (GTK_RANGE(event_viewer_data->vscroll_vc),
432 GTK_UPDATE_CONTINUOUS);
433 // Changed by MD : more user friendly :)
434 //GTK_UPDATE_DISCONTINUOUS);
435 gtk_box_pack_start(GTK_BOX(event_viewer_data->hbox_v),
436 event_viewer_data->vscroll_vc, FALSE, TRUE, 0);
437
438 /* Get the vertical scrollbar's adjustment */
439 event_viewer_data->vadjust_c =
440 gtk_range_get_adjustment(GTK_RANGE(event_viewer_data->vscroll_vc));
441 event_viewer_data->vtree_adjust_c = gtk_tree_view_get_vadjustment(
442 GTK_TREE_VIEW (event_viewer_data->tree_v));
443
444 g_signal_connect (G_OBJECT (event_viewer_data->vadjust_c), "value-changed",
445 G_CALLBACK (v_scroll_cb),
446 event_viewer_data);
447 //TODO ybrosseau 2011-01-06: Fix comment
448 /* Set the upper bound to the last event number */
449 event_viewer_data->previous_value = 0;
450 event_viewer_data->vadjust_c->lower = 0.0;
451 //event_viewer_data->vadjust_c->upper = event_viewer_data->number_of_events;
452
453 LttTime time = lttvwindow_get_current_time(tab);
454 TimeInterval time_span = lttv_traceset_get_time_span_real(ts);
455 time = ltt_time_sub(time, time_span.start_time);
456 //TODO ybrosseau 2011-01-06: Which one do we keep?
457 #ifdef BABEL_CLEANUP
458 event_viewer_data->vadjust_c->value = ltt_time_to_double(time);
459 #endif //babel_cleanup
460 event_viewer_data->vadjust_c->value = 0.0;
461 event_viewer_data->vadjust_c->step_increment = 1.0;
462 event_viewer_data->vadjust_c->page_increment = 2.0;
463 // event_viewer_data->vtree_adjust_c->upper;
464 event_viewer_data->vadjust_c->page_size = 2.0;
465 // event_viewer_data->vtree_adjust_c->upper;
466 /* Raw event trace */
467 gtk_widget_show(GTK_WIDGET(event_viewer_data->button_filter));
468 gtk_widget_show(event_viewer_data->toolbar);
469 gtk_widget_show(event_viewer_data->hbox_v);
470 gtk_widget_show(event_viewer_data->tree_v);
471 gtk_widget_show(event_viewer_data->vscroll_vc);
472
473 /* Add the object's information to the module's array */
474 g_event_viewer_data_list = g_slist_append(g_event_viewer_data_list,
475 plugin_evd);
476
477 event_viewer_data->num_visible_events = 1;
478
479 //get the life span of the traceset and set the upper of the scroll bar
480
481 end = ltt_time_sub(time_span.end_time, time_span.start_time);
482
483 event_viewer_data->vadjust_c->upper = ltt_time_to_double(end);
484
485 /* Set the Selected Event */
486 // tree_v_set_cursor(event_viewer_data);
487
488 // event_viewer_data->current_time_updated = FALSE;
489 //
490 g_object_set_data_full(
491 G_OBJECT(event_viewer_data->hbox_v),
492 "plugin_data",
493 plugin_evd,
494 (GDestroyNotify)gui_events_free);
495
496 g_object_set_data(
497 G_OBJECT(event_viewer_data->hbox_v),
498 "event_viewer_data",
499 event_viewer_data);
500
501 event_viewer_data->background_info_waiting = 0;
502
503
504 request_background_data(event_viewer_data);
505 return event_viewer_data;
506 }
507
508
509
510 static gint background_ready(void *hook_data, void *call_data)
511 {
512 EventViewerData *event_viewer_data = (EventViewerData *)hook_data;
513
514 event_viewer_data->background_info_waiting--;
515
516 if(event_viewer_data->background_info_waiting == 0) {
517 g_message("event viewer : background computation data ready.");
518
519 evd_redraw_notify(event_viewer_data, NULL);
520 }
521
522 return 0;
523 }
524
525
526 static void request_background_data(EventViewerData *event_viewer_data)
527 {
528 LttvTraceset * ts =
529 lttvwindow_get_traceset(event_viewer_data->tab);
530 gint num_traces = ts->traces->len;
531 gint i;
532 LttvTrace *trace;
533 LttvTraceState *tstate;
534
535 LttvHooks *background_ready_hook =
536 lttv_hooks_new();
537 lttv_hooks_add(background_ready_hook, background_ready, event_viewer_data,
538 LTTV_PRIO_DEFAULT);
539 event_viewer_data->background_info_waiting = 0;
540
541 for(i=0;i<num_traces;i++) {
542 trace = g_ptr_array_index(ts->traces,i);
543 #ifdef BABEL_CLEANUP
544 tstate = LTTV_TRACE_STATE(tsc->traces[i]);
545 #endif /*babel_cleanup*/
546
547 if(lttvwindowtraces_get_ready(g_quark_from_string("state"),trace)==FALSE
548 /*&& !tstate->has_precomputed_states*/) {
549
550 if(lttvwindowtraces_get_in_progress(g_quark_from_string("state"),
551 trace) == FALSE) {
552 /* We first remove requests that could have been done for the same
553 * information. Happens when two viewers ask for it before servicing
554 * starts.
555 */
556 if(!lttvwindowtraces_background_request_find(trace, "state"))
557 lttvwindowtraces_background_request_queue(
558 main_window_get_widget(event_viewer_data->tab), trace, "state");
559 lttvwindowtraces_background_notify_queue(event_viewer_data,
560 trace,
561 ltt_time_infinite,
562 NULL,
563 background_ready_hook);
564 event_viewer_data->background_info_waiting++;
565 } else { /* in progress */
566
567 lttvwindowtraces_background_notify_current(event_viewer_data,
568 trace,
569 ltt_time_infinite,
570 NULL,
571 background_ready_hook);
572 event_viewer_data->background_info_waiting++;
573 }
574 } else {
575 /* Data ready. By its nature, this viewer doesn't need to have
576 * its data ready hook called there, because a background
577 * request is always linked with a redraw.
578 */
579 }
580
581 }
582
583 lttv_hooks_destroy(background_ready_hook);
584 }
585
586 static gboolean
587 header_size_allocate(GtkWidget *widget,
588 GtkAllocation *allocation,
589 gpointer user_data)
590 {
591 EventViewerData *event_viewer_data = (EventViewerData*)user_data;
592
593 event_viewer_data->header_height = allocation->height;
594
595 return 0;
596 }
597
598
599 void tree_v_set_cursor(EventViewerData *event_viewer_data)
600 {
601 g_debug("set cursor cb - do nothing");
602
603 }
604
605 void tree_v_get_cursor(EventViewerData *event_viewer_data)
606 {
607 g_debug("get cursor cb - do nothing");
608
609
610 }
611
612 /* Filter out the key repeats that come too fast */
613 static gboolean key_handler(GtkWidget *widget, GdkEventKey *event,
614 gpointer user_data)
615 {
616 EventViewerData *evd = (EventViewerData *)user_data;
617
618 g_debug("event time : %u , last time : %u", event->time,
619 evd->last_tree_update_time);
620
621 if(guint32_before(event->time, evd->last_tree_update_time))
622 return TRUE;
623 else
624 return FALSE;
625 }
626
627 void tree_v_move_cursor_cb (GtkWidget *widget,
628 GtkMovementStep stepType,
629 gint arg2,
630 gpointer data)
631 {
632
633 GtkTreePath *path; // = gtk_tree_path_new();
634 EventViewerData *event_viewer_data = (EventViewerData*)data;
635
636 g_debug("move cursor cb");
637 //gtk_tree_view_get_cursor(GTK_TREE_VIEW(event_viewer_data->tree_v),
638 // &path, NULL);
639 //if(path == NULL)
640 //{
641 /* No prior cursor, put it at beginning of page
642 * and let the execution do */
643 // path = gtk_tree_path_new_from_indices(0, -1);
644 // gtk_tree_view_set_cursor(GTK_TREE_VIEW(event_viewer_data->tree_v),
645 // path, NULL, FALSE);
646 //}
647
648 //indices = gtk_tree_path_get_indices(path);
649
650 //value = gtk_adjustment_get_value(event_viewer_data->vadjust_c);
651
652 /* If events request pending, do nothing*/
653 if(lttvwindow_events_request_pending(event_viewer_data->tab)) return;
654
655 /* If no prior position... */
656
657
658 g_debug("tree view move cursor : stepType is %u and arg2 is %d",
659 (guint)stepType, arg2);
660
661 switch(stepType) {
662 case GTK_MOVEMENT_DISPLAY_LINES:
663 if(arg2 == 1) {
664 /* Move one line down */
665 LttvTracesetPosition *end_pos = 0;
666 if(event_viewer_data->pos->len > 0) {
667 end_pos =
668 (LttvTracesetPosition*)g_ptr_array_index(
669 event_viewer_data->pos,
670 event_viewer_data->pos->len-1);
671 }
672 if(!end_pos || lttv_traceset_position_compare(end_pos,
673 event_viewer_data->currently_selected_position) == 0) {
674 /* Must get down one event and select the last one */
675 gtk_tree_selection_unselect_all(gtk_tree_view_get_selection(
676 GTK_TREE_VIEW(event_viewer_data->tree_v)));
677 event_viewer_data->update_cursor = FALSE;
678 gtk_adjustment_set_value(event_viewer_data->vadjust_c,
679 gtk_adjustment_get_value(event_viewer_data->vadjust_c) + 1);
680 event_viewer_data->update_cursor = TRUE;
681 if(event_viewer_data->pos->len > 0) {
682 path = gtk_tree_path_new_from_indices(
683 max(0, event_viewer_data->pos->len - 1), -1);
684 if(path) {
685 gtk_tree_view_set_cursor(GTK_TREE_VIEW(event_viewer_data->tree_v),
686 path, NULL, FALSE);
687 gtk_tree_path_free(path);
688 }
689 }
690 }
691
692 } else {
693 LttvTracesetPosition *begin_pos = 0;
694
695 if(event_viewer_data->pos->len > 0) {
696 /* Move one line up */
697 begin_pos =
698 (LttvTracesetPosition*)g_ptr_array_index(
699 event_viewer_data->pos,
700 0);
701 }
702 if(!begin_pos || lttv_traceset_position_compare(begin_pos,
703 event_viewer_data->currently_selected_position) == 0)
704
705
706 {
707 /* Must get up one event and select the first one */
708 gtk_tree_selection_unselect_all(gtk_tree_view_get_selection(
709 GTK_TREE_VIEW(event_viewer_data->tree_v)));
710 event_viewer_data->update_cursor = FALSE;
711 gtk_adjustment_set_value(event_viewer_data->vadjust_c,
712 gtk_adjustment_get_value(event_viewer_data->vadjust_c) - 1);
713 event_viewer_data->update_cursor = TRUE;
714 if(event_viewer_data->pos->len > 0) {
715 path = gtk_tree_path_new_from_indices(
716 0, -1);
717 if(path) {
718 gtk_tree_view_set_cursor(GTK_TREE_VIEW(event_viewer_data->tree_v),
719 path, NULL, FALSE);
720 gtk_tree_path_free(path);
721 }
722 }
723 }
724
725 }
726 break;
727 case GTK_MOVEMENT_PAGES:
728 if(arg2 == 1) {
729 /* Move one page down */
730 LttvTracesetPosition *end_pos = 0;
731 if(event_viewer_data->pos->len > 0) {
732 end_pos =
733 (LttvTracesetPosition*)g_ptr_array_index(
734 event_viewer_data->pos,
735 event_viewer_data->pos->len-1);
736 }
737 if(!end_pos || lttv_traceset_position_compare(end_pos,
738 event_viewer_data->currently_selected_position) == 0) {
739 /* Must get down one page and select the last one */
740 gtk_tree_selection_unselect_all(gtk_tree_view_get_selection(
741 GTK_TREE_VIEW(event_viewer_data->tree_v)));
742 event_viewer_data->update_cursor = FALSE;
743 gtk_adjustment_set_value(event_viewer_data->vadjust_c,
744 gtk_adjustment_get_value(event_viewer_data->vadjust_c) + 2);
745 event_viewer_data->update_cursor = TRUE;
746 if(event_viewer_data->pos->len > 0) {
747 path = gtk_tree_path_new_from_indices(
748 event_viewer_data->pos->len - 1, -1);
749 if(path) {
750 gtk_tree_view_set_cursor(GTK_TREE_VIEW(event_viewer_data->tree_v),
751 path, NULL, FALSE);
752 gtk_tree_path_free(path);
753 }
754 }
755 }
756 } else {
757 /* Move one page up */
758 LttvTracesetPosition *begin_pos = 0;
759
760 if(event_viewer_data->pos->len > 0) {
761 begin_pos =
762 (LttvTracesetPosition*)g_ptr_array_index(
763 event_viewer_data->pos,
764 0);
765 }
766 if(!begin_pos || lttv_traceset_position_compare(begin_pos,
767 event_viewer_data->currently_selected_position) == 0) {
768 /* Must get up one page and select the first one */
769 gtk_tree_selection_unselect_all(gtk_tree_view_get_selection(
770 GTK_TREE_VIEW(event_viewer_data->tree_v)));
771 event_viewer_data->update_cursor = FALSE;
772 gtk_adjustment_set_value(event_viewer_data->vadjust_c,
773 gtk_adjustment_get_value(event_viewer_data->vadjust_c) - 2);
774 event_viewer_data->update_cursor = TRUE;
775 if(event_viewer_data->pos->len > 0) {
776 path = gtk_tree_path_new_from_indices(
777 0, -1);
778 if(path) {
779 gtk_tree_view_set_cursor(GTK_TREE_VIEW(event_viewer_data->tree_v),
780 path, NULL, FALSE);
781 gtk_tree_path_free(path);
782 }
783 }
784 }
785 }
786 break;
787 default:
788 break;
789 }
790 //gtk_tree_path_free(path);
791
792 }
793
794 static void filter_button (GtkToolButton *toolbutton,
795 gpointer user_data)
796 {
797 LttvPluginEVD *plugin_evd = (LttvPluginEVD*)user_data;
798 LttvAttribute *attribute;
799 LttvAttributeValue value;
800 gboolean ret;
801 g_printf("Filter button clicked\n");
802
803 attribute = LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(
804 LTTV_IATTRIBUTE(lttv_global_attributes()),
805 LTTV_VIEWER_CONSTRUCTORS));
806 g_assert(attribute);
807
808 ret = lttv_iattribute_find_by_path(LTTV_IATTRIBUTE(attribute),
809 "guifilter", LTTV_POINTER, &value);
810 g_assert(ret);
811 lttvwindow_viewer_constructor constructor =
812 (lttvwindow_viewer_constructor)*(value.v_pointer);
813 if(constructor) constructor(&plugin_evd->parent);
814 else g_warning("Filter module not loaded.");
815
816 //FIXME : viewer returned.
817 }
818
819 gboolean tree_v_scroll_handler (GtkWidget *widget, GdkEventScroll *event, gpointer data)
820 {
821 EventViewerData *event_viewer_data = (EventViewerData*) data;
822
823 switch(event->direction) {
824 case GDK_SCROLL_UP:
825 gtk_adjustment_set_value(event_viewer_data->vadjust_c,
826 gtk_adjustment_get_value(event_viewer_data->vadjust_c) - 1);
827 break;
828 case GDK_SCROLL_DOWN:
829 gtk_adjustment_set_value(event_viewer_data->vadjust_c,
830 gtk_adjustment_get_value(event_viewer_data->vadjust_c) + 1);
831 break;
832 default:
833 g_error("Only scroll up and down expected");
834 }
835 return TRUE;
836 }
837
838 void tree_v_cursor_changed_cb (GtkWidget *widget, gpointer data)
839 {
840
841 EventViewerData *event_viewer_data = (EventViewerData*) data;
842
843 Tab *tab = event_viewer_data->tab;
844 GtkTreeIter iter;
845 GtkTreeModel* model = GTK_TREE_MODEL(event_viewer_data->store_m);
846 GtkTreePath *path;
847 LttvTracesetPosition *pos;
848
849 g_debug("cursor changed cb");
850
851 /* On cursor change, modify the currently selected event by calling
852 * the right API function */
853 if(event_viewer_data->report_position) {
854 if(event_viewer_data->pos->len > 0) {
855 gtk_tree_view_get_cursor(GTK_TREE_VIEW(event_viewer_data->tree_v),
856 &path, NULL);
857 if(path) {
858 if(gtk_tree_model_get_iter(model,&iter,path)){
859 gtk_tree_model_get(model, &iter, POSITION_COLUMN, &pos, -1);
860
861 if(lttv_traceset_position_compare(pos,
862 event_viewer_data->currently_selected_position) != 0) {
863 lttvwindow_report_current_position(tab, pos);
864 }
865 }else{
866 g_warning("Can not get iter\n");
867 }
868 gtk_tree_path_free(path);
869 }
870 }
871 }
872 }
873
874
875 static void tree_selection_changed_cb (GtkTreeSelection *selection,
876 gpointer data)
877 {
878 g_debug("tree sel changed cb - do nothing");
879
880
881 }
882
883 #if 0
884 static gint key_snooper(GtkWidget *grab_widget, GdkEventKey *event,
885 gpointer func_data)
886 {
887 return TRUE;
888 }
889 #endif //0
890
891 /* This callback may be recalled after a step up/down, but we don't want to lose
892 * the exact position : what we do is that we only set the value if it has
893 * changed : a step up/down that doesn't change the time value of the first
894 * event won't trigger a scrollbar change. */
895
896 void v_scroll_cb (GtkAdjustment *adjustment, gpointer data)
897 {
898 EventViewerData *event_viewer_data = (EventViewerData*)data;
899 g_debug("SCROLL begin");
900 g_debug("SCROLL values : %g , %g, %g",
901 adjustment->value, event_viewer_data->previous_value,
902 (adjustment->value - event_viewer_data->previous_value));
903
904 LttTime new_time_off = ltt_time_from_double(adjustment->value);
905 LttTime old_time_off = ltt_time_from_double(event_viewer_data->previous_value);
906 g_debug("SCROLL time values %lu.%lu, %lu.%lu", new_time_off.tv_sec,
907 new_time_off.tv_nsec, old_time_off.tv_sec, old_time_off.tv_nsec);
908 /* If same value : nothing to update */
909 if(ltt_time_compare(new_time_off, old_time_off) == 0)
910 return;
911
912 //LttTime old_time = event_viewer_data->first_event;
913
914
915 //gint snoop = gtk_key_snooper_install(key_snooper, NULL);
916
917 adjust_event_viewer(adjustment->value, event_viewer_data);
918
919 //gtk_key_snooper_remove(snoop);
920
921 g_debug("SCROLL end");
922 }
923
924 static __inline gint get_cell_height(GtkTreeView *TreeView)
925 {
926 gint height;
927 GtkTreeViewColumn *column = gtk_tree_view_get_column(TreeView, 0);
928
929 gtk_tree_view_column_cell_get_size(column, NULL, NULL, NULL, NULL, &height);
930
931 gint vertical_separator;
932 gtk_widget_style_get (GTK_WIDGET (TreeView),
933 "vertical-separator", &vertical_separator,
934 NULL);
935
936 height += vertical_separator;
937
938 return height;
939 }
940
941 void tree_v_size_allocate_cb (GtkWidget *widget, GtkAllocation *alloc, gpointer data)
942 {
943 EventViewerData *event_viewer_data = (EventViewerData*)data;
944 gint cell_height = get_cell_height(GTK_TREE_VIEW(event_viewer_data->tree_v));
945 gint last_num_visible_events = event_viewer_data->num_visible_events;
946 gdouble exact_num_visible;
947
948 exact_num_visible = ( alloc->height -
949 event_viewer_data->header_height )
950 / (double)cell_height ;
951
952 event_viewer_data->num_visible_events = ceil(exact_num_visible) ;
953
954 event_viewer_data->vadjust_c->page_increment =
955 floor(exact_num_visible);
956 event_viewer_data->vadjust_c->page_size =
957 floor(exact_num_visible);
958
959
960 g_debug("size allocate %p : last_num_visible_events : %d",
961 event_viewer_data, last_num_visible_events);
962 g_debug("num_visible_events : %d, value %f",
963 event_viewer_data->num_visible_events,
964 event_viewer_data->vadjust_c->value);
965
966 if(event_viewer_data->num_visible_events != last_num_visible_events) {
967 //TODO ybrosseau do a proper initialisation here, so we can use the redraw
968 adjust_event_viewer(event_viewer_data->vadjust_c->value, event_viewer_data);
969 //redraw(event_viewer_data);
970 }
971
972
973 }
974
975 void tree_v_size_request_cb (GtkWidget *widget, GtkRequisition *requisition, gpointer data)
976 {
977 gint h;
978 EventViewerData *event_viewer_data = (EventViewerData*)data;
979 gint cell_height = get_cell_height(GTK_TREE_VIEW(event_viewer_data->tree_v));
980
981 h = cell_height + event_viewer_data->header_height;
982 requisition->height = h;
983
984 }
985
986 static gboolean events_check_handler(guint count, gboolean *stop_flag,
987 gpointer data)
988 {
989 EventViewerData *evd = (EventViewerData*)data;
990 if(count % CHECK_GDK_INTERVAL == 0) {
991 GdkEvent *event;
992 GtkWidget *widget;
993 while((event = gdk_event_get()) != NULL) {
994 widget = gtk_get_event_widget(event);
995 if(widget ==
996 lookup_widget(main_window_get_widget(evd->tab),
997 "StopProcessingButton")
998 || widget == evd->vscroll_vc) {
999 gtk_main_do_event(event);
1000 gdk_window_process_all_updates();
1001 }
1002 gdk_event_free(event);
1003 }
1004 if(*stop_flag)
1005 return TRUE;
1006 else
1007 return FALSE;
1008 } else return FALSE;
1009 }
1010
1011
1012 /* This function will adjust the first event position for the viewer which
1013 will be used by the redraw to seek and display all the events
1014 */
1015 static void adjust_event_viewer(double new_value, EventViewerData *event_viewer_data)
1016 {
1017 #ifdef BABEL_CLEANUP
1018 LttvTracesetStats *tss =
1019 lttvwindow_get_traceset_stats(event_viewer_data->tab);
1020 #endif //babel_cleanup
1021 LttvTraceset *ts = lttvwindow_get_traceset(event_viewer_data->tab);
1022
1023 gboolean seek_by_time;
1024
1025 if(lttvwindow_preempt_count > 0) return;
1026
1027 double value = new_value - event_viewer_data->previous_value;
1028
1029 /* Set stop button status for foreground processing */
1030 event_viewer_data->tab->stop_foreground = FALSE;
1031 lttvwindow_events_request_disable();
1032
1033 /* See where we have to scroll... */
1034 ScrollDirection direction;
1035 gint relative_position;
1036
1037 if(value < -0.8) {
1038 if(value >= -1.0) direction = SCROLL_STEP_UP;
1039 else {
1040 if(value >= -2.0) direction = SCROLL_PAGE_UP;
1041 else direction = SCROLL_JUMP;
1042 }
1043 } else if(value > 0.8) {
1044 if(value <= 1.0) direction = SCROLL_STEP_DOWN;
1045 else {
1046 if(value <= 2.0) direction = SCROLL_PAGE_DOWN;
1047 else direction = SCROLL_JUMP;
1048 }
1049 } else direction = SCROLL_NONE; /* 0.0 */
1050
1051 switch(direction) {
1052 case SCROLL_STEP_UP:
1053 g_debug("adjust_event_viewer : SCROLL_STEP_UP");
1054 relative_position = -1;
1055 seek_by_time = 0;
1056 break;
1057 case SCROLL_STEP_DOWN:
1058 g_debug("adjust_event_viewer : SCROLL_STEP_DOWN");
1059 relative_position = 1;
1060 seek_by_time = 0;
1061 break;
1062 case SCROLL_PAGE_UP:
1063 g_debug("adjust_event_viewer : SCROLL_PAGE_UP");
1064 relative_position = -(event_viewer_data->num_visible_events);
1065 seek_by_time = 0;
1066 break;
1067 case SCROLL_PAGE_DOWN:
1068 g_debug("adjust_event_viewer : SCROLL_PAGE_DOWN");
1069 relative_position = event_viewer_data->num_visible_events;
1070 seek_by_time = 0;
1071 break;
1072 case SCROLL_JUMP:
1073 g_debug("adjust_event_viewer : SCROLL_JUMP");
1074 relative_position = 0;
1075 seek_by_time = 1;
1076 break;
1077 case SCROLL_NONE:
1078 g_debug("adjust_event_viewer : SCROLL_NONE");
1079 relative_position = 0;
1080 seek_by_time = 0;
1081 break;
1082 }
1083
1084 LttTime time = ltt_time_from_double(new_value);
1085 TimeInterval time_span = lttv_traceset_get_time_span_real(ts);
1086 time = ltt_time_add(time_span.start_time, time);
1087
1088 LttvTracesetPosition *timePos = lttv_traceset_create_time_position(ts,time);
1089
1090
1091 if(!seek_by_time) {
1092
1093 /* Remember the beginning position */
1094 if(event_viewer_data->pos->len > 0) {
1095
1096 if(relative_position != 0)
1097 {
1098 LttvTracesetPosition *pos = 0;
1099 pos = (LttvTracesetPosition*)g_ptr_array_index(
1100 event_viewer_data->pos,
1101 0);
1102 lttv_state_traceset_seek_position(ts,pos);
1103 }
1104 } else {
1105 lttv_state_traceset_seek_time(ts,time);
1106
1107 }
1108
1109 /* Note that, as we mess with the tsc position, this function CANNOT be called
1110 * from a hook inside the lttv_process_traceset_middle. */
1111 /* As the lttvwindow API keeps a sync_position inside the tsc to go back at
1112 * the right spot after being interrupted, it's ok to change the tsc position,
1113 * as long as we do not touch the sync_position. */
1114
1115 /* Get the beginning position of the read (with seek backward or seek forward)
1116 */
1117 if(relative_position > 0) {
1118 lttv_process_traceset_seek_n_forward(ts, relative_position,
1119 events_check_handler,
1120 &event_viewer_data->tab->stop_foreground,
1121 event_viewer_data->main_win_filter,
1122 event_viewer_data->filter, NULL, event_viewer_data);
1123 } else if(relative_position < 0) {
1124 /* Get an idea of currently shown event dispersion */
1125 guint64 first_event_time_stamp =
1126 lttv_traceset_position_get_timestamp(event_viewer_data->first_event);
1127 guint64 last_event_time_stamp =
1128 lttv_traceset_position_get_timestamp(event_viewer_data->last_event);
1129 guint64 timeSpan = (last_event_time_stamp - first_event_time_stamp);
1130 gdouble ratio = (gdouble)timeSpan / (gdouble)event_viewer_data->num_visible_events;
1131 if(ratio <= 0){
1132 ratio = SEEK_BACK_DEFAULT_RATIO;
1133 }
1134
1135 lttv_process_traceset_seek_n_backward(ts,
1136 (guint)abs(relative_position),
1137 ratio,
1138 events_check_handler,
1139 &event_viewer_data->tab->stop_foreground,
1140 event_viewer_data->main_win_filter,
1141 event_viewer_data->filter, NULL, event_viewer_data);
1142 } /* else 0 : do nothing : we are already at the beginning position */
1143
1144 /* Save the first event position */
1145
1146 event_viewer_data->first_event = lttv_traceset_create_current_position(ts);
1147
1148 time = ltt_time_from_uint64(lttv_traceset_position_get_timestamp(
1149 event_viewer_data->first_event));
1150 //if(ltt_time_compare(time, tsc->time_span.end_time) > 0)
1151 // time = tsc->time_span.end_time;
1152
1153 LttTime time_val = ltt_time_sub(time,time_span.start_time);
1154 event_viewer_data->previous_value = ltt_time_to_double(time_val);
1155
1156
1157 } else {
1158 /* Seek by time */
1159
1160 LttTime time_val = ltt_time_sub(time,time_span.start_time);
1161 event_viewer_data->previous_value = ltt_time_to_double(time_val);
1162 event_viewer_data->first_event = timePos;
1163 }
1164 lttvwindow_events_request_enable();
1165
1166 redraw(event_viewer_data);
1167 }
1168
1169 static void redraw(EventViewerData *event_viewer_data) {
1170 guint i;
1171 LttvTraceset *ts = lttvwindow_get_traceset(event_viewer_data->tab);
1172
1173 g_debug("EventViewer redraw");
1174
1175 //TODO ybrosseau verify its still required
1176 lttvwindow_events_request_disable();
1177
1178
1179 /* Clear the model (don't forget to free the TCS positions!) */
1180 gtk_list_store_clear(event_viewer_data->store_m);
1181 for(i=0;i<event_viewer_data->pos->len;i++) {
1182 LttvTracesetPosition *cur_pos =
1183 (LttvTracesetPosition*)g_ptr_array_index(event_viewer_data->pos,
1184 i);
1185 lttv_traceset_destroy_position(cur_pos);
1186 }
1187 g_ptr_array_set_size(event_viewer_data->pos, 0);
1188
1189 lttv_state_traceset_seek_position(ts, event_viewer_data->first_event);
1190
1191 /* Mathieu :
1192 * I make the choice not to use the mainwindow lttvwindow API here : the idle
1193 * loop might have a too low priority, and we want good update while
1194 * scrolling. However, we call the gdk loop to get events periodically so the
1195 * processing can be stopped.
1196 */
1197
1198 lttv_process_traceset_begin(ts,
1199 NULL, NULL, event_viewer_data->event_hooks);
1200
1201 event_viewer_data->num_events = 0;
1202
1203 lttv_process_traceset_middle(ts, ltt_time_infinite, G_MAXUINT, NULL);
1204
1205 lttv_process_traceset_end(ts, NULL, NULL, event_viewer_data->event_hooks);
1206
1207 /* Get the end position */
1208 if(event_viewer_data->pos->len > 0) {
1209 LttvTracesetPosition *cur_pos =
1210 (LttvTracesetPosition*)g_ptr_array_index(event_viewer_data->pos,
1211 event_viewer_data->pos->len - 1);
1212 event_viewer_data->last_event = cur_pos;
1213 } else
1214 event_viewer_data->last_event =lttv_traceset_create_current_position(ts);
1215
1216 gtk_adjustment_set_value(event_viewer_data->vadjust_c,
1217 event_viewer_data->previous_value);
1218
1219 //g_signal_emit_by_name(G_OBJECT (event_viewer_data->select_c),
1220 // "changed");
1221
1222 event_viewer_data->last_tree_update_time =
1223 gdk_x11_get_server_time(
1224 gtk_widget_get_parent_window(event_viewer_data->tree_v));
1225
1226 lttvwindow_events_request_enable();
1227
1228 return;
1229 }
1230
1231
1232 int event_hook(void *hook_data, void *call_data)
1233 {
1234
1235 EventViewerData *event_viewer_data = (EventViewerData*)hook_data;
1236
1237 LttvEvent * e = (LttvEvent *)call_data;
1238
1239 if(event_viewer_data->num_events % CHECK_GDK_INTERVAL == 0) {
1240 GdkEvent *event;
1241 GtkWidget *widget;
1242 while((event = gdk_event_get()) != NULL) {
1243 widget = gtk_get_event_widget(event);
1244 if(widget ==
1245 lookup_widget(main_window_get_widget(event_viewer_data->tab),
1246 "StopProcessingButton")
1247 || widget == event_viewer_data->vscroll_vc) {
1248 gtk_main_do_event(event);
1249 gdk_window_process_all_updates();
1250 }
1251 gdk_event_free(event);
1252 }
1253 //gtk_main_iteration_do(FALSE);
1254 if(event_viewer_data->tab->stop_foreground)
1255 return TRUE;
1256 }
1257
1258 event_viewer_data->num_events++;
1259 #ifdef BABEL_CLEANUP
1260 LttvFilter *filter = event_viewer_data->main_win_filter;
1261 if(filter != NULL && filter->head != NULL)
1262 if(!lttv_filter_tree_parse(filter->head,e,tfc->tf,
1263 tfc->t_context->t,tfc,NULL,NULL))
1264 return FALSE;
1265
1266 filter = event_viewer_data->filter;
1267 if(filter != NULL && filter->head != NULL)
1268 if(!lttv_filter_tree_parse(filter->head,e,tfc->tf,
1269 tfc->t_context->t,tfc,NULL,NULL))
1270 return FALSE;
1271 #endif //babel_cleanup
1272
1273 // LttFacility *facility = ltt_event_facility(e);
1274 // LttEventType *event_type = ltt_event_eventtype(e);
1275 LttTime time = lttv_event_get_timestamp(e);
1276 gint cpu = lttv_traceset_get_cpuid_from_event(e);
1277
1278 LttvTraceState *traceState = e->state;
1279 LttvProcessState *process = traceState->running_process[cpu];
1280
1281 GtkTreeIter iter;
1282
1283 GString *desc = g_string_new("");
1284 GString *name = g_string_new("");
1285
1286 LttvTracesetPosition *pos = lttv_traceset_create_current_position(traceState->trace->traceset);
1287
1288 lttv_event_to_string(e, desc, TRUE, FALSE);
1289 lttv_event_get_name(e,name);
1290
1291 g_info("detail : %s", desc->str);
1292
1293 gtk_list_store_append (event_viewer_data->store_m, &iter);
1294
1295 gtk_list_store_set (event_viewer_data->store_m, &iter,
1296 TRACE_NAME_COLUMN, "TraceName",
1297 CPUID_COLUMN, cpu,
1298 EVENT_COLUMN,name->str,
1299 TIME_S_COLUMN, time.tv_sec,
1300 TIME_NS_COLUMN, time.tv_nsec,
1301 PID_COLUMN, process->pid,
1302 EVENT_DESCR_COLUMN, desc->str,
1303 POSITION_COLUMN, pos,
1304 -1);
1305
1306 g_ptr_array_add(event_viewer_data->pos, pos);
1307
1308 g_string_free(desc, TRUE);
1309 g_string_free(name, TRUE);
1310
1311 if(event_viewer_data->update_cursor) {
1312 if(lttv_traceset_position_compare(pos,
1313 event_viewer_data->currently_selected_position) == 0) {
1314 GtkTreePath *path = gtk_tree_path_new_from_indices(
1315 event_viewer_data->pos->len - 1, -1);
1316 if(path) {
1317 gtk_tree_view_set_cursor(GTK_TREE_VIEW(event_viewer_data->tree_v),
1318 path, NULL, FALSE);
1319 gtk_tree_path_free(path);
1320 }
1321 }
1322 }
1323 if(event_viewer_data->pos->len >= event_viewer_data->num_visible_events )
1324 return TRUE;
1325 else
1326 return FALSE;
1327
1328 }
1329
1330
1331
1332 static void event_update_selection(EventViewerData *event_viewer_data)
1333 {
1334
1335 guint i;
1336 GPtrArray *positions = event_viewer_data->pos;
1337 g_info("event_update_selection");
1338
1339 int isFound = FALSE;
1340
1341
1342 for(i=0;i<positions->len;i++) {
1343 LttvTracesetPosition *cur_pos =
1344 (LttvTracesetPosition*)g_ptr_array_index(positions, i);
1345 if(lttv_traceset_position_compare(cur_pos,
1346 event_viewer_data->currently_selected_position) == 0) {
1347 GtkTreePath *path = gtk_tree_path_new_from_indices(i, -1);
1348 if(path) {
1349 gtk_tree_view_set_cursor(GTK_TREE_VIEW(event_viewer_data->tree_v),
1350 path, NULL, FALSE);
1351 gtk_widget_grab_focus(event_viewer_data->tree_v );
1352 gtk_tree_path_free(path);
1353 isFound = TRUE;
1354 break;
1355 }
1356 }
1357 }
1358 if(isFound){
1359 return;
1360 }
1361 /* If the current selection is not in the currently displayed events*/
1362 LttTime currentTime = lttv_traceset_position_get_time(
1363 event_viewer_data->currently_selected_position);
1364 LttTime time;
1365
1366 LttvTraceset * ts = lttvwindow_get_traceset(event_viewer_data->tab);
1367 TimeInterval time_span = lttv_traceset_get_time_span_real(ts);
1368 time = ltt_time_sub(currentTime, time_span.start_time);
1369 gtk_adjustment_set_value(event_viewer_data->vadjust_c,
1370 ltt_time_to_double(time));
1371 gtk_widget_grab_focus(event_viewer_data->tree_v );
1372
1373 }
1374 #ifdef BABEL_CLEANUP
1375 static int current_time_get_first_event_hook(void *hook_data, void *call_data)
1376 {
1377
1378 EventViewerData *event_viewer_data = (EventViewerData*)hook_data;
1379
1380 LttvTracefileContext *tfc = (LttvTracefileContext*)call_data;
1381 LttEvent *e = ltt_tracefile_get_event(tfc->tf);
1382
1383 LttvFilter *filter = event_viewer_data->main_win_filter;
1384 if(filter != NULL && filter->head != NULL)
1385 if(!lttv_filter_tree_parse(filter->head,e,tfc->tf,
1386 tfc->t_context->t,tfc,NULL,NULL))
1387 return FALSE;
1388
1389 filter = event_viewer_data->filter;
1390 if(filter != NULL && filter->head != NULL)
1391 if(!lttv_filter_tree_parse(filter->head,e,tfc->tf,
1392 tfc->t_context->t,tfc,NULL,NULL))
1393 return FALSE;
1394
1395 lttv_traceset_context_position_save(tfc->t_context->ts_context,
1396 event_viewer_data->current_time_get_first);
1397 return TRUE;
1398
1399
1400 }
1401 #endif // BABEL_CLEANUP
1402
1403 gboolean update_current_time(void * hook_data, void * call_data)
1404 {
1405
1406 //LttvEvent * e = (LttvEvent *)call_data;
1407 g_info("update_current_time");
1408 EventViewerData *event_viewer_data = (EventViewerData*) hook_data;
1409
1410 const LttTime * current_time = (LttTime*)call_data;
1411 LttvTraceset * ts = lttvwindow_get_traceset(event_viewer_data->tab);
1412
1413 /* If the currently selected event time != current time, set the first event
1414 * with this time as currently selected. */
1415 LttTime pos_time = lttv_traceset_position_get_time(
1416 event_viewer_data->currently_selected_position);
1417
1418 if(ltt_time_compare(pos_time, *current_time) != 0) {
1419 /*create position*/
1420 //LttvTracesetPosition *currentPosition =
1421 // lttv_traceset_create_time_position(ts,*current_time );
1422 /*seek to current position*/
1423 lttv_state_traceset_seek_time(ts, *current_time);
1424
1425 event_viewer_data->currently_selected_position =
1426 lttv_traceset_create_current_position(ts);
1427 g_debug("update_current_time: %p %d", event_viewer_data->currently_selected_position, event_viewer_data->currently_selected_position->timestamp);
1428 }
1429
1430 event_viewer_data->report_position = FALSE;
1431
1432 /* Simply update the current time : it is in the list */
1433 event_update_selection(event_viewer_data);
1434 event_viewer_data->report_position = TRUE;
1435
1436 return FALSE;
1437 }
1438
1439 gboolean update_current_position(void * hook_data, void * call_data)
1440 {
1441
1442 g_info("update_current_position");
1443 EventViewerData *event_viewer_data = (EventViewerData*) hook_data;
1444 const LttvTracesetPosition *current_pos = (LttvTracesetPosition*)call_data;
1445
1446 if(lttv_traceset_position_compare(
1447 event_viewer_data->currently_selected_position, current_pos) != 0) {
1448 g_debug("Update current pos: %p, %d", current_pos, current_pos->timestamp);
1449 event_viewer_data->currently_selected_position = current_pos;
1450 /* Simply update the current time : it is in the list */
1451 event_update_selection(event_viewer_data);
1452 }
1453 return FALSE;
1454
1455 }
1456
1457 gboolean timespan_changed(void * hook_data, void * call_data)
1458 {
1459
1460 EventViewerData *event_viewer_data = (EventViewerData*) hook_data;
1461 LttvTraceset * ts = lttvwindow_get_traceset(event_viewer_data->tab);
1462 TimeInterval time_span = lttv_traceset_get_time_span_real(ts);
1463
1464 LttTime end;
1465
1466 end = ltt_time_sub(time_span.end_time, time_span.start_time);
1467 event_viewer_data->vadjust_c->upper = ltt_time_to_double(end);
1468
1469 if(event_viewer_data->pos->len < event_viewer_data->num_visible_events ) {
1470
1471
1472 redraw(event_viewer_data);
1473
1474 request_background_data(event_viewer_data);
1475 }
1476 return FALSE;
1477 }
1478
1479 gboolean traceset_changed(void * hook_data, void * call_data)
1480 {
1481
1482 EventViewerData *event_viewer_data = (EventViewerData*) hook_data;
1483 LttvTraceset * ts = lttvwindow_get_traceset(event_viewer_data->tab);
1484 TimeInterval time_span = lttv_traceset_get_time_span_real(ts);
1485
1486 LttTime end;
1487 gtk_list_store_clear(event_viewer_data->store_m);
1488 g_ptr_array_set_size(event_viewer_data->pos, 0);
1489
1490 end = ltt_time_sub(time_span.end_time, time_span.start_time);
1491 event_viewer_data->vadjust_c->upper = ltt_time_to_double(end);
1492 #ifdef BABEL_CLEANUP
1493 /* Reset the positions */
1494 lttv_traceset_destroy_position(event_viewer_data->currently_selected_position);
1495 lttv_traceset_destroy_position(event_viewer_data->first_event);
1496 lttv_traceset_destroy_position(event_viewer_data->last_event);
1497
1498 event_viewer_data->currently_selected_position =
1499 lttv_traceset_create_current_position(ts);
1500 event_viewer_data->first_event =
1501 lttv_traceset_create_current_position(ts);
1502 event_viewer_data->last_event =
1503 lttv_traceset_create_current_position(ts);
1504
1505 redraw(event_viewer_data);
1506
1507 #endif //babel_cleanup
1508 // event_viewer_data->vadjust_c->value = 0;
1509
1510 request_background_data(event_viewer_data);
1511
1512 return FALSE;
1513 }
1514
1515 gboolean filter_changed(void * hook_data, void * call_data)
1516 {
1517 EventViewerData *event_viewer_data = (EventViewerData*) hook_data;
1518
1519 event_viewer_data->main_win_filter =
1520 (LttvFilter*)call_data;
1521 redraw(event_viewer_data);
1522
1523 return FALSE;
1524 }
1525
1526
1527 gint evd_redraw_notify(void *hook_data, void *call_data)
1528 {
1529 EventViewerData *event_viewer_data = (EventViewerData*) hook_data;
1530
1531 redraw(event_viewer_data);
1532 return 0;
1533 }
1534
1535 void gui_events_free(gpointer data)
1536 {
1537 #ifdef BABEL_CLEANUP
1538 LttvPluginEVD *plugin_evd = (LttvPluginEVD*)data;
1539 Tab *tab = plugin_evd->evd->tab;
1540 EventViewerData *event_viewer_data = plugin_evd->evd;
1541 guint i;
1542
1543 lttv_filter_destroy(plugin_evd->evd->filter);
1544
1545 if(tab != NULL){
1546 lttv_hooks_remove(event_viewer_data->event_hooks,event_hook);
1547 lttv_hooks_destroy(event_viewer_data->event_hooks);
1548
1549 for(i=0;i<event_viewer_data->pos->len;i++) {
1550 LttvTracesetContextPosition *cur_pos =
1551 (LttvTracesetContextPosition*)g_ptr_array_index(event_viewer_data->pos,
1552 i);
1553 lttv_traceset_context_position_destroy(cur_pos);
1554 }
1555 lttv_traceset_context_position_destroy(
1556 event_viewer_data->currently_selected_position);
1557 lttv_traceset_context_position_destroy(
1558 event_viewer_data->first_event);
1559 lttv_traceset_context_position_destroy(
1560 event_viewer_data->last_event);
1561 g_ptr_array_free(event_viewer_data->pos, TRUE);
1562
1563 lttvwindow_unregister_current_time_notify(tab,
1564 update_current_time, event_viewer_data);
1565 lttvwindow_unregister_current_position_notify(tab,
1566 update_current_position, event_viewer_data);
1567 //lttvwindow_unregister_show_notify(tab,
1568 // show_event_detail, event_viewer_data);
1569 lttvwindow_unregister_traceset_notify(tab,
1570 traceset_changed, event_viewer_data);
1571 lttvwindow_unregister_timespan_notify(tab,
1572 timespan_changed,event_viewer_data);
1573 lttvwindow_unregister_filter_notify(tab,
1574 filter_changed, event_viewer_data);
1575 lttvwindow_unregister_redraw_notify(tab,
1576 evd_redraw_notify, event_viewer_data);
1577
1578 }
1579 lttvwindowtraces_background_notify_remove(event_viewer_data);
1580
1581 g_event_viewer_data_list = g_slist_remove(g_event_viewer_data_list,
1582 event_viewer_data);
1583 //g_free(event_viewer_data);
1584 g_object_unref(plugin_evd);
1585 #endif // BABEL_CLEANUP
1586 }
1587
1588
1589
1590 void gui_events_destructor(gpointer data)
1591 {
1592 LttvPluginEVD *plugin_evd = (LttvPluginEVD*)data;
1593 /* May already been done by GTK window closing */
1594 if(GTK_IS_WIDGET(plugin_evd->parent.top_widget)){
1595 gtk_widget_destroy(plugin_evd->parent.top_widget);
1596 }
1597 }
1598
1599
1600
1601 /**
1602 * plugin's init function
1603 *
1604 * This function initializes the Event Viewer functionnality through the
1605 * gtkTraceSet API.
1606 */
1607 static void init() {
1608
1609 lttvwindow_register_constructor("guievents",
1610 "/",
1611 "Insert Event Viewer",
1612 hGuiEventsInsert_xpm,
1613 "Insert Event Viewer",
1614 h_gui_events);
1615 }
1616
1617 void event_destroy_walk(gpointer data, gpointer user_data)
1618 {
1619 gui_events_destructor((LttvPluginEVD*)data);
1620 }
1621
1622 /**
1623 * plugin's destroy function
1624 *
1625 * This function releases the memory reserved by the module and unregisters
1626 * everything that has been registered in the gtkTraceSet API.
1627 */
1628 static void destroy() {
1629
1630 g_slist_foreach(g_event_viewer_data_list, event_destroy_walk, NULL );
1631 g_slist_free(g_event_viewer_data_list);
1632
1633 lttvwindow_unregister_constructor(h_gui_events);
1634
1635 }
1636
1637
1638
1639
1640 LTTV_MODULE("guievents", "Detailed events view", \
1641 "Graphical module to display a detailed event list", \
1642 init, destroy, "lttvwindow", "print")
This page took 0.103252 seconds and 3 git commands to generate.