1 /* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2003-2004 XangXiu Yang, Mathieu Desnoyers
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License Version 2 as
6 * published by the Free Software Foundation;
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
23 #include <limits.h> // for PATH_MAX
31 #include "callbacks.h"
32 #include "interface.h"
34 #include <ltt/trace.h>
36 #include <ltt/event.h>
37 #include <lttv/lttv.h>
38 #include <lttv/module.h>
39 #include <lttv/iattribute.h>
40 #include <lttv/stats.h>
41 #include <lttv/filter.h>
42 #include <lttvwindow/mainwindow.h>
43 #include <lttvwindow/mainwindow-private.h>
44 #include <lttvwindow/menu.h>
45 #include <lttvwindow/toolbar.h>
46 #include <lttvwindow/lttvwindow.h>
47 #include <lttvwindow/lttvwindowtraces.h>
48 #include <lttvwindow/lttv_plugin_tab.h>
50 static LttTime lttvwindow_default_time_width
= { 1, 0 };
51 #define CLIP_BUF 256 // size of clipboard buffer
53 extern LttvTrace
*g_init_trace
;
56 /** Array containing instanced objects. */
57 extern GSList
* g_main_window_list
;
59 /** MD : keep old directory. */
60 static char remember_plugins_dir
[PATH_MAX
] = "";
61 static char remember_trace_dir
[PATH_MAX
] = "";
63 void tab_destructor(LttvPluginTab
* ptab
);
65 MainWindow
* get_window_data_struct(GtkWidget
* widget
);
66 char * get_load_module(MainWindow
*mw
,
67 char ** load_module_name
, int nb_module
);
68 char * get_unload_module(MainWindow
*mw
,
69 char ** loaded_module_name
, int nb_module
);
70 char * get_remove_trace(MainWindow
*mw
, char ** all_trace_name
, int nb_trace
);
71 char * get_selection(MainWindow
*mw
,
72 char ** all_name
, int nb
, char *title
, char * column_title
);
73 void init_tab(Tab
*tab
, MainWindow
* mw
, Tab
*copy_tab
,
74 GtkNotebook
* notebook
, char * label
);
76 static void insert_viewer(GtkWidget
* widget
, lttvwindow_viewer_constructor constructor
);
78 LttvPluginTab
*create_new_tab(GtkWidget
* widget
, gpointer user_data
);
80 static gboolean
lttvwindow_process_pending_requests(Tab
*tab
);
94 /* Pasting routines */
96 static void MEventBox1a_receive(GtkClipboard
*clipboard
,
100 if(text
== NULL
) return;
101 Tab
*tab
= (Tab
*)data
;
102 gchar buffer
[CLIP_BUF
];
103 gchar
*ptr
= buffer
, *ptr_ssec
, *ptr_snsec
, *ptr_esec
, *ptr_ensec
;
105 strncpy(buffer
, text
, CLIP_BUF
);
108 while(!isdigit(*ptr
) && ptr
< buffer
+CLIP_BUF
-1) ptr
++;
109 /* remove leading junk */
111 while(isdigit(*ptr
) && ptr
< buffer
+CLIP_BUF
-1) ptr
++;
112 /* read all the first number */
116 while(!isdigit(*ptr
) && ptr
< buffer
+CLIP_BUF
-1) ptr
++;
117 /* remove leading junk */
119 while(isdigit(*ptr
) && ptr
< buffer
+CLIP_BUF
-1) ptr
++;
120 /* read all the first number */
124 while(!isdigit(*ptr
) && ptr
< buffer
+CLIP_BUF
-1) ptr
++;
125 /* remove leading junk */
127 while(isdigit(*ptr
) && ptr
< buffer
+CLIP_BUF
-1) ptr
++;
128 /* read all the first number */
132 while(!isdigit(*ptr
) && ptr
< buffer
+CLIP_BUF
-1) ptr
++;
133 /* remove leading junk */
135 while(isdigit(*ptr
) && ptr
< buffer
+CLIP_BUF
-1) ptr
++;
136 /* read all the first number */
139 gtk_spin_button_set_value(GTK_SPIN_BUTTON(tab
->MEntry1
),
140 (double)strtoul(ptr_ssec
, NULL
, 10));
141 gtk_spin_button_set_value(GTK_SPIN_BUTTON(tab
->MEntry2
),
142 (double)strtoul(ptr_snsec
, NULL
, 10));
143 gtk_spin_button_set_value(GTK_SPIN_BUTTON(tab
->MEntry3
),
144 (double)strtoul(ptr_esec
, NULL
, 10));
145 gtk_spin_button_set_value(GTK_SPIN_BUTTON(tab
->MEntry4
),
146 (double)strtoul(ptr_ensec
, NULL
, 10));
149 static gboolean
on_MEventBox1a_paste(GtkWidget
*widget
, GdkEventButton
*event
,
152 Tab
*tab
= (Tab
*)data
;
154 GtkClipboard
*clip
= gtk_clipboard_get_for_display(gdk_display_get_default(),
155 GDK_SELECTION_PRIMARY
);
156 gtk_clipboard_request_text(clip
,
157 (GtkClipboardTextReceivedFunc
)MEventBox1a_receive
,
164 static void MEventBox1b_receive(GtkClipboard
*clipboard
,
168 if(text
== NULL
) return;
169 Tab
*tab
= (Tab
*)data
;
170 gchar buffer
[CLIP_BUF
];
171 gchar
*ptr
= buffer
, *ptr_sec
, *ptr_nsec
;
173 strncpy(buffer
, text
, CLIP_BUF
);
175 while(!isdigit(*ptr
) && ptr
< buffer
+CLIP_BUF
-1) ptr
++;
176 /* remove leading junk */
178 while(isdigit(*ptr
) && ptr
< buffer
+CLIP_BUF
-1) ptr
++;
179 /* read all the first number */
183 while(!isdigit(*ptr
) && ptr
< buffer
+CLIP_BUF
-1) ptr
++;
184 /* remove leading junk */
186 while(isdigit(*ptr
) && ptr
< buffer
+CLIP_BUF
-1) ptr
++;
187 /* read all the first number */
190 gtk_spin_button_set_value(GTK_SPIN_BUTTON(tab
->MEntry1
),
191 (double)strtoul(ptr_sec
, NULL
, 10));
192 gtk_spin_button_set_value(GTK_SPIN_BUTTON(tab
->MEntry2
),
193 (double)strtoul(ptr_nsec
, NULL
, 10));
197 static gboolean
on_MEventBox1b_paste(GtkWidget
*widget
, GdkEventButton
*event
,
200 Tab
*tab
= (Tab
*)data
;
202 GtkClipboard
*clip
= gtk_clipboard_get_for_display(gdk_display_get_default(),
203 GDK_SELECTION_PRIMARY
);
204 gtk_clipboard_request_text(clip
,
205 (GtkClipboardTextReceivedFunc
)MEventBox1b_receive
,
211 static void MEventBox3b_receive(GtkClipboard
*clipboard
,
215 if(text
== NULL
) return;
216 Tab
*tab
= (Tab
*)data
;
217 gchar buffer
[CLIP_BUF
];
218 gchar
*ptr
= buffer
, *ptr_sec
, *ptr_nsec
;
220 strncpy(buffer
, text
, CLIP_BUF
);
222 while(!isdigit(*ptr
) && ptr
< buffer
+CLIP_BUF
-1) ptr
++;
223 /* remove leading junk */
225 while(isdigit(*ptr
) && ptr
< buffer
+CLIP_BUF
-1) ptr
++;
226 /* read all the first number */
230 while(!isdigit(*ptr
) && ptr
< buffer
+CLIP_BUF
-1) ptr
++;
231 /* remove leading junk */
233 while(isdigit(*ptr
) && ptr
< buffer
+CLIP_BUF
-1) ptr
++;
234 /* read all the first number */
237 gtk_spin_button_set_value(GTK_SPIN_BUTTON(tab
->MEntry3
),
238 (double)strtoul(ptr_sec
, NULL
, 10));
239 gtk_spin_button_set_value(GTK_SPIN_BUTTON(tab
->MEntry4
),
240 (double)strtoul(ptr_nsec
, NULL
, 10));
244 static gboolean
on_MEventBox3b_paste(GtkWidget
*widget
, GdkEventButton
*event
,
247 Tab
*tab
= (Tab
*)data
;
249 GtkClipboard
*clip
= gtk_clipboard_get_for_display(gdk_display_get_default(),
250 GDK_SELECTION_PRIMARY
);
251 gtk_clipboard_request_text(clip
,
252 (GtkClipboardTextReceivedFunc
)MEventBox3b_receive
,
258 static void MEventBox5b_receive(GtkClipboard
*clipboard
,
262 if(text
== NULL
) return;
263 Tab
*tab
= (Tab
*)data
;
264 gchar buffer
[CLIP_BUF
];
265 gchar
*ptr
= buffer
, *ptr_sec
, *ptr_nsec
;
267 strncpy(buffer
, text
, CLIP_BUF
);
269 while(!isdigit(*ptr
) && ptr
< buffer
+CLIP_BUF
-1) ptr
++;
270 /* remove leading junk */
272 while(isdigit(*ptr
) && ptr
< buffer
+CLIP_BUF
-1) ptr
++;
273 /* read all the first number */
277 while(!isdigit(*ptr
) && ptr
< buffer
+CLIP_BUF
-1) ptr
++;
278 /* remove leading junk */
280 while(isdigit(*ptr
) && ptr
< buffer
+CLIP_BUF
-1) ptr
++;
281 /* read all the first number */
284 gtk_spin_button_set_value(GTK_SPIN_BUTTON(tab
->MEntry5
),
285 (double)strtoul(ptr_sec
, NULL
, 10));
286 gtk_spin_button_set_value(GTK_SPIN_BUTTON(tab
->MEntry6
),
287 (double)strtoul(ptr_nsec
, NULL
, 10));
291 static gboolean
on_MEventBox5b_paste(GtkWidget
*widget
, GdkEventButton
*event
,
294 Tab
*tab
= (Tab
*)data
;
296 GtkClipboard
*clip
= gtk_clipboard_get_for_display(gdk_display_get_default(),
297 GDK_SELECTION_PRIMARY
);
298 gtk_clipboard_request_text(clip
,
299 (GtkClipboardTextReceivedFunc
)MEventBox5b_receive
,
305 static void MEventBox8_receive(GtkClipboard
*clipboard
,
309 if(text
== NULL
) return;
310 Tab
*tab
= (Tab
*)data
;
311 gchar buffer
[CLIP_BUF
];
312 gchar
*ptr
= buffer
, *ptr_sec
, *ptr_nsec
;
314 strncpy(buffer
, text
, CLIP_BUF
);
316 while(!isdigit(*ptr
) && ptr
< buffer
+CLIP_BUF
-1) ptr
++;
317 /* remove leading junk */
319 while(isdigit(*ptr
) && ptr
< buffer
+CLIP_BUF
-1) ptr
++;
320 /* read all the first number */
324 while(!isdigit(*ptr
) && ptr
< buffer
+CLIP_BUF
-1) ptr
++;
325 /* remove leading junk */
327 while(isdigit(*ptr
) && ptr
< buffer
+CLIP_BUF
-1) ptr
++;
328 /* read all the first number */
331 gtk_spin_button_set_value(GTK_SPIN_BUTTON(tab
->MEntry7
),
332 (double)strtoul(ptr_sec
, NULL
, 10));
333 gtk_spin_button_set_value(GTK_SPIN_BUTTON(tab
->MEntry8
),
334 (double)strtoul(ptr_nsec
, NULL
, 10));
338 static gboolean
on_MEventBox8_paste(GtkWidget
*widget
, GdkEventButton
*event
,
341 Tab
*tab
= (Tab
*)data
;
343 GtkClipboard
*clip
= gtk_clipboard_get_for_display(gdk_display_get_default(),
344 GDK_SELECTION_PRIMARY
);
345 gtk_clipboard_request_text(clip
,
346 (GtkClipboardTextReceivedFunc
)MEventBox8_receive
,
352 static void on_top_notify(GObject
*gobject
,
356 Tab
*tab
= (Tab
*)user_data
;
357 g_message("in on_top_notify.\n");
361 static gboolean
viewer_grab_focus(GtkWidget
*widget
, GdkEventButton
*event
,
364 GtkWidget
*viewer
= GTK_WIDGET(data
);
365 GtkWidget
*viewer_container
= gtk_widget_get_parent(viewer
);
367 g_debug("FOCUS GRABBED");
368 g_object_set_data(G_OBJECT(viewer_container
), "focused_viewer", viewer
);
373 static void connect_focus_recursive(GtkWidget
*widget
,
376 if(GTK_IS_CONTAINER(widget
)) {
377 gtk_container_forall(GTK_CONTAINER(widget
),
378 (GtkCallback
)connect_focus_recursive
,
382 if(GTK_IS_TREE_VIEW(widget
)) {
383 gtk_tree_view_set_headers_clickable(GTK_TREE_VIEW(widget
), TRUE
);
385 gtk_widget_add_events(widget
, GDK_BUTTON_PRESS_MASK
);
386 g_signal_connect (G_OBJECT(widget
),
387 "button-press-event",
388 G_CALLBACK (viewer_grab_focus
),
392 /* Stop all the processings and call gtk_main_quit() */
393 static void mainwindow_quit()
395 lttvwindowtraces_unregister_requests(g_quark_from_string("stats"));
396 lttvwindowtraces_unregister_requests(g_quark_from_string("state"));
397 lttvwindowtraces_unregister_computation_hooks(g_quark_from_string("stats"));
398 lttvwindowtraces_unregister_computation_hooks(g_quark_from_string("state"));
404 /* insert_viewer function constructs an instance of a viewer first,
405 * then inserts the widget of the instance into the container of the
410 insert_viewer_wrap(GtkWidget
*menuitem
, gpointer user_data
)
412 insert_viewer((GtkWidget
*)menuitem
, (lttvwindow_viewer_constructor
)user_data
);
416 /* internal functions */
417 void insert_viewer(GtkWidget
* widget
, lttvwindow_viewer_constructor constructor
)
419 GtkWidget
* viewer_container
;
420 MainWindow
* mw_data
= get_window_data_struct(widget
);
421 GtkWidget
* notebook
= lookup_widget(widget
, "MNotebook");
423 TimeInterval
* time_interval
;
424 GtkWidget
*page
= gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook
),
425 gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook
)));
430 ptab
= create_new_tab(widget
, NULL
);
432 ptab
= (LttvPluginTab
*)g_object_get_data(G_OBJECT(page
), "Tab_Plugin");
436 viewer_container
= tab
->viewer_container
;
438 viewer
= (GtkWidget
*)constructor(ptab
);
441 //gtk_multivpaned_widget_add(GTK_MULTIVPANED(multivpaned), viewer);
443 gtk_box_pack_end(GTK_BOX(viewer_container
),
449 /* We want to connect the viewer_grab_focus to EVERY
450 * child of this widget. The little trick is to get each child
451 * of each GTK_CONTAINER, even subchildren.
453 connect_focus_recursive(viewer
, viewer
);
458 * Function to set/update traceset for the viewers
459 * @param tab viewer's tab
460 * @param traceset traceset of the main window.
462 * 0 : traceset updated
463 * 1 : no traceset hooks to update; not an error.
466 int SetTraceset(Tab
* tab
, LttvTraceset
*traceset
)
468 LttvTracesetContext
*tsc
=
469 LTTV_TRACESET_CONTEXT(tab
->traceset_info
->traceset_context
);
470 TimeInterval time_span
= tsc
->time_span
;
471 TimeWindow new_time_window
= tab
->time_window
;
472 LttTime new_current_time
= tab
->current_time
;
474 /* Set the tab's time window and current time if
476 if(ltt_time_compare(tab
->time_window
.start_time
, time_span
.start_time
) < 0
477 || ltt_time_compare(tab
->time_window
.end_time
,
478 time_span
.end_time
) > 0) {
479 new_time_window
.start_time
= time_span
.start_time
;
481 new_current_time
= time_span
.start_time
;
485 if(ltt_time_compare(lttvwindow_default_time_width
,
486 ltt_time_sub(time_span
.end_time
, time_span
.start_time
)) < 0
488 ltt_time_compare(time_span
.end_time
, time_span
.start_time
) == 0)
489 tmp_time
= lttvwindow_default_time_width
;
491 tmp_time
= time_span
.end_time
;
493 new_time_window
.time_width
= tmp_time
;
494 new_time_window
.time_width_double
= ltt_time_to_double(tmp_time
);
495 new_time_window
.end_time
= ltt_time_add(new_time_window
.start_time
,
496 new_time_window
.time_width
) ;
503 GtkAdjustment
*adjustment
= gtk_range_get_adjustment(GTK_RANGE(tab
->scrollbar
));
504 LttTime upper
= ltt_time_sub(time_span
.end_time
, time_span
.start_time
);
506 g_object_set(G_OBJECT(adjustment
),
510 ltt_time_to_double(upper
)
511 * NANOSECONDS_PER_SECOND
, /* upper */
513 ltt_time_to_double(tab
->time_window
.time_width
)
514 / SCROLL_STEP_PER_PAGE
515 * NANOSECONDS_PER_SECOND
, /* step increment */
517 ltt_time_to_double(tab
->time_window
.time_width
)
518 * NANOSECONDS_PER_SECOND
, /* page increment */
520 ltt_time_to_double(tab
->time_window
.time_width
)
521 * NANOSECONDS_PER_SECOND
, /* page size */
523 gtk_adjustment_changed(adjustment
);
525 g_object_set(G_OBJECT(adjustment
),
528 ltt_time_sub(tab
->time_window
.start_time
, time_span
.start_time
))
529 * NANOSECONDS_PER_SECOND
, /* value */
531 gtk_adjustment_value_changed(adjustment
);
533 /* set the time bar. The value callbacks will change their nsec themself */
535 gtk_spin_button_set_range(GTK_SPIN_BUTTON(tab
->MEntry1
),
536 (double)time_span
.start_time
.tv_sec
,
537 (double)time_span
.end_time
.tv_sec
);
540 gtk_spin_button_set_range(GTK_SPIN_BUTTON(tab
->MEntry3
),
541 (double)time_span
.start_time
.tv_sec
,
542 (double)time_span
.end_time
.tv_sec
);
544 /* current seconds */
545 gtk_spin_button_set_range(GTK_SPIN_BUTTON(tab
->MEntry5
),
546 (double)time_span
.start_time
.tv_sec
,
547 (double)time_span
.end_time
.tv_sec
);
550 /* Finally, call the update hooks of the viewers */
552 LttvAttributeValue value
;
556 g_assert( lttv_iattribute_find_by_path(tab
->attributes
,
557 "hooks/updatetraceset", LTTV_POINTER
, &value
));
559 tmp
= (LttvHooks
*)*(value
.v_pointer
);
560 if(tmp
== NULL
) retval
= 1;
561 else lttv_hooks_call(tmp
,traceset
);
563 time_change_manager(tab
, new_time_window
);
564 current_time_change_manager(tab
, new_current_time
);
570 * Function to set/update filter for the viewers
571 * @param tab viewer's tab
572 * @param filter filter of the main window.
575 * 0 : filters updated
576 * 1 : no filter hooks to update; not an error.
579 int SetFilter(Tab
* tab
, gpointer filter
)
582 LttvAttributeValue value
;
584 g_assert(lttv_iattribute_find_by_path(tab
->attributes
,
585 "hooks/updatefilter", LTTV_POINTER
, &value
));
587 tmp
= (LttvHooks
*)*(value
.v_pointer
);
589 if(tmp
== NULL
) return 1;
590 lttv_hooks_call(tmp
,filter
);
598 * Function to redraw each viewer belonging to the current tab
599 * @param tab viewer's tab
602 void update_traceset(Tab
*tab
)
604 LttvAttributeValue value
;
606 g_assert(lttv_iattribute_find_by_path(tab
->attributes
,
607 "hooks/updatetraceset", LTTV_POINTER
, &value
));
608 tmp
= (LttvHooks
*)*(value
.v_pointer
);
609 if(tmp
== NULL
) return;
610 lttv_hooks_call(tmp
, NULL
);
614 /* get_label function is used to get user input, it displays an input
615 * box, which allows user to input a string
618 void get_label_string (GtkWidget
* text
, gchar
* label
)
620 GtkEntry
* entry
= (GtkEntry
*)text
;
621 if(strlen(gtk_entry_get_text(entry
))!=0)
622 strcpy(label
,gtk_entry_get_text(entry
));
625 gboolean
get_label(MainWindow
* mw
, gchar
* str
, gchar
* dialogue_title
, gchar
* label_str
)
627 GtkWidget
* dialogue
;
632 dialogue
= gtk_dialog_new_with_buttons(dialogue_title
,NULL
,
634 GTK_STOCK_OK
,GTK_RESPONSE_ACCEPT
,
635 GTK_STOCK_CANCEL
,GTK_RESPONSE_REJECT
,
638 label
= gtk_label_new(label_str
);
639 gtk_widget_show(label
);
641 text
= gtk_entry_new();
642 gtk_widget_show(text
);
644 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialogue
)->vbox
), label
,TRUE
, TRUE
,0);
645 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialogue
)->vbox
), text
,FALSE
, FALSE
,0);
647 id
= gtk_dialog_run(GTK_DIALOG(dialogue
));
649 case GTK_RESPONSE_ACCEPT
:
650 get_label_string(text
,str
);
651 gtk_widget_destroy(dialogue
);
653 case GTK_RESPONSE_REJECT
:
655 gtk_widget_destroy(dialogue
);
662 /* get_window_data_struct function is actually a lookup function,
663 * given a widget which is in the tree of the main window, it will
664 * return the MainWindow data structure associated with main window
667 MainWindow
* get_window_data_struct(GtkWidget
* widget
)
670 MainWindow
* mw_data
;
672 mw
= lookup_widget(widget
, "MWindow");
674 g_info("Main window does not exist\n");
678 mw_data
= (MainWindow
*) g_object_get_data(G_OBJECT(mw
),"main_window_data");
680 g_warning("Main window data does not exist\n");
687 /* create_new_window function, just constructs a new main window
690 void create_new_window(GtkWidget
* widget
, gpointer user_data
, gboolean clone
)
692 MainWindow
* parent
= get_window_data_struct(widget
);
695 g_info("Clone : use the same traceset\n");
696 construct_main_window(parent
);
698 g_info("Empty : traceset is set to NULL\n");
699 construct_main_window(NULL
);
703 /* Get the currently focused viewer.
704 * If no viewer is focused, use the first one.
706 * If no viewer available, return NULL.
708 GtkWidget
*viewer_container_focus(GtkWidget
*container
)
712 widget
= (GtkWidget
*)g_object_get_data(G_OBJECT(container
),
716 g_debug("no widget focused");
717 GList
*children
= gtk_container_get_children(GTK_CONTAINER(container
));
720 widget
= GTK_WIDGET(children
->data
);
721 g_object_set_data(G_OBJECT(container
),
731 gint
viewer_container_position(GtkWidget
*container
, GtkWidget
*child
)
734 if(child
== NULL
) return -1;
738 memset(&value
, 0, sizeof(GValue
));
739 g_value_init(&value
, G_TYPE_INT
);
740 gtk_container_child_get_property(GTK_CONTAINER(container
),
744 pos
= g_value_get_int(&value
);
750 /* move_*_viewer functions move the selected view up/down in
754 void move_down_viewer(GtkWidget
* widget
, gpointer user_data
)
756 MainWindow
* mw
= get_window_data_struct(widget
);
757 GtkWidget
* notebook
= lookup_widget(widget
, "MNotebook");
759 GtkWidget
*page
= gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook
),
760 gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook
)));
767 ptab
= g_object_get_data(G_OBJECT(page
), "Tab_Plugin");
771 //gtk_multivpaned_widget_move_up(GTK_MULTIVPANED(tab->multivpaned));
773 /* change the position in the vbox */
774 GtkWidget
*focus_widget
;
776 focus_widget
= viewer_container_focus(tab
->viewer_container
);
777 position
= viewer_container_position(tab
->viewer_container
, focus_widget
);
780 /* can move up one position */
781 gtk_box_reorder_child(GTK_BOX(tab
->viewer_container
),
788 void move_up_viewer(GtkWidget
* widget
, gpointer user_data
)
790 MainWindow
* mw
= get_window_data_struct(widget
);
791 GtkWidget
* notebook
= lookup_widget(widget
, "MNotebook");
793 GtkWidget
*page
= gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook
),
794 gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook
)));
801 ptab
= (LttvPluginTab
*)g_object_get_data(G_OBJECT(page
), "Tab_Plugin");
805 //gtk_multivpaned_widget_move_down(GTK_MULTIVPANED(tab->multivpaned));
806 /* change the position in the vbox */
807 GtkWidget
*focus_widget
;
809 focus_widget
= viewer_container_focus(tab
->viewer_container
);
810 position
= viewer_container_position(tab
->viewer_container
, focus_widget
);
814 g_list_length(gtk_container_get_children(
815 GTK_CONTAINER(tab
->viewer_container
)))-1
817 /* can move down one position */
818 gtk_box_reorder_child(GTK_BOX(tab
->viewer_container
),
826 /* delete_viewer deletes the selected viewer in the current tab
829 void delete_viewer(GtkWidget
* widget
, gpointer user_data
)
831 MainWindow
* mw
= get_window_data_struct(widget
);
832 GtkWidget
* notebook
= lookup_widget(widget
, "MNotebook");
834 GtkWidget
*page
= gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook
),
835 gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook
)));
842 ptab
= g_object_get_data(G_OBJECT(page
), "Tab_Plugin");
846 //gtk_multivpaned_widget_delete(GTK_MULTIVPANED(tab->multivpaned));
848 GtkWidget
*focus_widget
= viewer_container_focus(tab
->viewer_container
);
850 if(focus_widget
!= NULL
)
851 gtk_widget_destroy(focus_widget
);
853 g_object_set_data(G_OBJECT(tab
->viewer_container
), "focused_viewer", NULL
);
857 /* open_traceset will open a traceset saved in a file
858 * Right now, it is not finished yet, (not working)
862 void open_traceset(GtkWidget
* widget
, gpointer user_data
)
866 LttvTraceset
* traceset
;
867 MainWindow
* mw_data
= get_window_data_struct(widget
);
868 GtkFileSelection
* file_selector
=
869 (GtkFileSelection
*)gtk_file_selection_new("Select a traceset");
871 gtk_file_selection_hide_fileop_buttons(file_selector
);
873 gtk_window_set_transient_for(GTK_WINDOW(file_selector
),
874 GTK_WINDOW(mw_data
->mwindow
));
876 id
= gtk_dialog_run(GTK_DIALOG(file_selector
));
878 case GTK_RESPONSE_ACCEPT
:
879 case GTK_RESPONSE_OK
:
880 dir
= gtk_file_selection_get_selections (file_selector
);
881 traceset
= lttv_traceset_load(dir
[0]);
882 g_info("Open a trace set %s\n", dir
[0]);
885 case GTK_RESPONSE_REJECT
:
886 case GTK_RESPONSE_CANCEL
:
888 gtk_widget_destroy((GtkWidget
*)file_selector
);
894 /* lttvwindow_process_pending_requests
896 * Process requests for parts of the trace from viewers.
898 * These requests are made by lttvwindow_events_request().
900 * This internal function gets called by g_idle, taking care of the pending
901 * requests. It is responsible for concatenation of time intervals and position
902 * requests. It does it with the following algorithm organizing process traceset
903 * calls. Here is the detailed description of the way it works :
905 * - Events Requests Servicing Algorithm
907 * Data structures necessary :
909 * List of requests added to context : list_in
910 * List of requests not added to context : list_out
915 * list_out : many events requests
917 * FIXME : insert rest of algorithm here
921 #define list_out tab->events_requests
923 gboolean
lttvwindow_process_pending_requests(Tab
*tab
)
926 LttvTracesetContext
*tsc
;
927 LttvTracefileContext
*tfc
;
928 GSList
*list_in
= NULL
;
932 LttvTracesetContextPosition
*end_position
;
934 if(lttvwindow_preempt_count
> 0) return TRUE
;
937 g_critical("Foreground processing : tab does not exist. Processing removed.");
941 /* There is no events requests pending : we should never have been called! */
942 g_assert(g_slist_length(list_out
) != 0);
944 tsc
= LTTV_TRACESET_CONTEXT(tab
->traceset_info
->traceset_context
);
946 //set the cursor to be X shape, indicating that the computer is busy in doing its job
948 new = gdk_cursor_new(GDK_X_CURSOR
);
949 widget
= lookup_widget(tab
->mw
->mwindow
, "MToolbar1");
950 win
= gtk_widget_get_parent_window(widget
);
951 gdk_window_set_cursor(win
, new);
952 gdk_cursor_unref(new);
953 gdk_window_stick(win
);
954 gdk_window_unstick(win
);
957 g_debug("SIZE events req len : %d", g_slist_length(list_out
));
959 /* Preliminary check for no trace in traceset */
960 /* Unregister the routine if empty, empty list_out too */
961 if(lttv_traceset_number(tsc
->ts
) == 0) {
963 /* - For each req in list_out */
964 GSList
*iter
= list_out
;
966 while(iter
!= NULL
) {
968 gboolean remove
= FALSE
;
969 gboolean free_data
= FALSE
;
970 EventsRequest
*events_request
= (EventsRequest
*)iter
->data
;
972 /* - Call end request for req */
973 if(events_request
->servicing
== TRUE
)
974 lttv_hooks_call(events_request
->after_request
, (gpointer
)tsc
);
976 /* - remove req from list_out */
977 /* Destroy the request */
984 GSList
*remove_iter
= iter
;
986 iter
= g_slist_next(iter
);
987 if(free_data
) events_request_free((EventsRequest
*)remove_iter
->data
);
988 list_out
= g_slist_remove_link(list_out
, remove_iter
);
989 } else { // not remove
990 iter
= g_slist_next(iter
);
995 /* 0.1 Lock Traces */
1000 iter_trace
<lttv_traceset_number(tsc
->ts
);
1002 LttvTrace
*trace_v
= lttv_traceset_get(tsc
->ts
, iter_trace
);
1004 if(lttvwindowtraces_lock(trace_v
) != 0) {
1005 g_critical("Foreground processing : Unable to get trace lock");
1006 return TRUE
; /* Cannot get lock, try later */
1011 /* 0.2 Seek tracefiles positions to context position */
1012 //g_assert(lttv_process_traceset_seek_position(tsc, sync_position) == 0);
1013 lttv_process_traceset_synchronize_tracefiles(tsc
);
1016 /* Events processing algorithm implementation */
1017 /* Warning : the gtk_events_pending takes a LOT of cpu time. So what we do
1018 * instead is to leave the control to GTK and take it back.
1020 /* A. Servicing loop */
1021 //while( (g_slist_length(list_in) != 0 || g_slist_length(list_out) != 0)) {
1022 if((g_slist_length(list_in
) != 0 || g_slist_length(list_out
) != 0)) {
1024 /* 1. If list_in is empty (need a seek) */
1025 if( g_slist_length(list_in
) == 0 ) {
1027 /* list in is empty, need a seek */
1029 /* 1.1 Add requests to list_in */
1030 GSList
*ltime
= NULL
;
1031 GSList
*lpos
= NULL
;
1032 GSList
*iter
= NULL
;
1034 /* 1.1.1 Find all time requests with the lowest start time in list_out
1037 if(g_slist_length(list_out
) > 0)
1038 ltime
= g_slist_append(ltime
, g_slist_nth_data(list_out
, 0));
1039 for(iter
=g_slist_nth(list_out
,1);iter
!=NULL
;iter
=g_slist_next(iter
)) {
1040 /* Find all time requests with the lowest start time in list_out */
1041 EventsRequest
*event_request_ltime
= (EventsRequest
*)g_slist_nth_data(ltime
, 0);
1042 EventsRequest
*event_request_list_out
= (EventsRequest
*)iter
->data
;
1045 comp
= ltt_time_compare(event_request_ltime
->start_time
,
1046 event_request_list_out
->start_time
);
1048 ltime
= g_slist_append(ltime
, event_request_list_out
);
1050 /* Remove all elements from ltime, and add current */
1051 while(ltime
!= NULL
)
1052 ltime
= g_slist_delete_link(ltime
, g_slist_nth(ltime
, 0));
1053 ltime
= g_slist_append(ltime
, event_request_list_out
);
1057 /* 1.1.2 Find all position requests with the lowest position in list_out
1060 if(g_slist_length(list_out
) > 0)
1061 lpos
= g_slist_append(lpos
, g_slist_nth_data(list_out
, 0));
1062 for(iter
=g_slist_nth(list_out
,1);iter
!=NULL
;iter
=g_slist_next(iter
)) {
1063 /* Find all position requests with the lowest position in list_out */
1064 EventsRequest
*event_request_lpos
= (EventsRequest
*)g_slist_nth_data(lpos
, 0);
1065 EventsRequest
*event_request_list_out
= (EventsRequest
*)iter
->data
;
1068 if(event_request_lpos
->start_position
!= NULL
1069 && event_request_list_out
->start_position
!= NULL
)
1071 comp
= lttv_traceset_context_pos_pos_compare
1072 (event_request_lpos
->start_position
,
1073 event_request_list_out
->start_position
);
1078 lpos
= g_slist_append(lpos
, event_request_list_out
);
1080 /* Remove all elements from lpos, and add current */
1082 lpos
= g_slist_delete_link(lpos
, g_slist_nth(lpos
, 0));
1083 lpos
= g_slist_append(lpos
, event_request_list_out
);
1088 EventsRequest
*event_request_lpos
= (EventsRequest
*)g_slist_nth_data(lpos
, 0);
1089 EventsRequest
*event_request_ltime
= (EventsRequest
*)g_slist_nth_data(ltime
, 0);
1090 LttTime lpos_start_time
;
1092 if(event_request_lpos
!= NULL
1093 && event_request_lpos
->start_position
!= NULL
) {
1094 lpos_start_time
= lttv_traceset_context_position_get_time(
1095 event_request_lpos
->start_position
);
1098 /* 1.1.3 If lpos.start time < ltime */
1099 if(event_request_lpos
!= NULL
1100 && event_request_lpos
->start_position
!= NULL
1101 && ltt_time_compare(lpos_start_time
,
1102 event_request_ltime
->start_time
)<0) {
1103 /* Add lpos to list_in, remove them from list_out */
1104 for(iter
=lpos
;iter
!=NULL
;iter
=g_slist_next(iter
)) {
1105 /* Add to list_in */
1106 EventsRequest
*event_request_lpos
=
1107 (EventsRequest
*)iter
->data
;
1109 list_in
= g_slist_append(list_in
, event_request_lpos
);
1110 /* Remove from list_out */
1111 list_out
= g_slist_remove(list_out
, event_request_lpos
);
1114 /* 1.1.4 (lpos.start time >= ltime) */
1115 /* Add ltime to list_in, remove them from list_out */
1117 for(iter
=ltime
;iter
!=NULL
;iter
=g_slist_next(iter
)) {
1118 /* Add to list_in */
1119 EventsRequest
*event_request_ltime
=
1120 (EventsRequest
*)iter
->data
;
1122 list_in
= g_slist_append(list_in
, event_request_ltime
);
1123 /* Remove from list_out */
1124 list_out
= g_slist_remove(list_out
, event_request_ltime
);
1129 g_slist_free(ltime
);
1134 tfc
= lttv_traceset_context_get_current_tfc(tsc
);
1135 g_assert(g_slist_length(list_in
)>0);
1136 EventsRequest
*events_request
= g_slist_nth_data(list_in
, 0);
1139 /* 1.2.1 If first request in list_in is a time request */
1140 if(events_request
->start_position
== NULL
) {
1141 /* - If first req in list_in start time != current time */
1142 if(tfc
== NULL
|| ltt_time_compare(events_request
->start_time
,
1143 tfc
->timestamp
) != 0)
1144 /* - Seek to that time */
1145 g_debug("SEEK TIME : %lu, %lu", events_request
->start_time
.tv_sec
,
1146 events_request
->start_time
.tv_nsec
);
1147 //lttv_process_traceset_seek_time(tsc, events_request->start_time);
1148 lttv_state_traceset_seek_time_closest(LTTV_TRACESET_STATE(tsc
),
1149 events_request
->start_time
);
1151 /* Process the traceset with only state hooks */
1153 lttv_process_traceset_middle(tsc
,
1154 events_request
->start_time
,
1157 g_assert(seek_count
< LTTV_STATE_SAVE_INTERVAL
);
1163 LttvTracefileContext
*tfc
=
1164 lttv_traceset_context_get_current_tfc(tsc
);
1165 /* Else, the first request in list_in is a position request */
1166 /* If first req in list_in pos != current pos */
1167 g_assert(events_request
->start_position
!= NULL
);
1168 g_debug("SEEK POS time : %lu, %lu",
1169 lttv_traceset_context_position_get_time(
1170 events_request
->start_position
).tv_sec
,
1171 lttv_traceset_context_position_get_time(
1172 events_request
->start_position
).tv_nsec
);
1175 g_debug("SEEK POS context time : %lu, %lu",
1176 tfc
->timestamp
.tv_sec
,
1177 tfc
->timestamp
.tv_nsec
);
1179 g_debug("SEEK POS context time : %lu, %lu",
1180 ltt_time_infinite
.tv_sec
,
1181 ltt_time_infinite
.tv_nsec
);
1183 g_assert(events_request
->start_position
!= NULL
);
1184 if(lttv_traceset_context_ctx_pos_compare(tsc
,
1185 events_request
->start_position
) != 0) {
1186 /* 1.2.2.1 Seek to that position */
1187 g_debug("SEEK POSITION");
1188 //lttv_process_traceset_seek_position(tsc, events_request->start_position);
1189 pos_time
= lttv_traceset_context_position_get_time(
1190 events_request
->start_position
);
1192 lttv_state_traceset_seek_time_closest(LTTV_TRACESET_STATE(tsc
),
1195 /* Process the traceset with only state hooks */
1197 lttv_process_traceset_middle(tsc
,
1200 events_request
->start_position
);
1201 g_assert(lttv_traceset_context_ctx_pos_compare(tsc
,
1202 events_request
->start_position
) == 0);
1209 /* 1.3 Add hooks and call before request for all list_in members */
1211 GSList
*iter
= NULL
;
1213 for(iter
=list_in
;iter
!=NULL
;iter
=g_slist_next(iter
)) {
1214 EventsRequest
*events_request
= (EventsRequest
*)iter
->data
;
1215 /* 1.3.1 If !servicing */
1216 if(events_request
->servicing
== FALSE
) {
1217 /* - begin request hooks called
1218 * - servicing = TRUE
1220 lttv_hooks_call(events_request
->before_request
, (gpointer
)tsc
);
1221 events_request
->servicing
= TRUE
;
1223 /* 1.3.2 call before chunk
1224 * 1.3.3 events hooks added
1226 if(events_request
->trace
== -1)
1227 lttv_process_traceset_begin(tsc
,
1228 events_request
->before_chunk_traceset
,
1229 events_request
->before_chunk_trace
,
1230 events_request
->before_chunk_tracefile
,
1231 events_request
->event
,
1232 events_request
->event_by_id_channel
);
1234 guint nb_trace
= lttv_traceset_number(tsc
->ts
);
1235 g_assert((guint
)events_request
->trace
< nb_trace
&&
1236 events_request
->trace
> -1);
1237 LttvTraceContext
*tc
= tsc
->traces
[events_request
->trace
];
1239 lttv_hooks_call(events_request
->before_chunk_traceset
, tsc
);
1241 lttv_trace_context_add_hooks(tc
,
1242 events_request
->before_chunk_trace
,
1243 events_request
->before_chunk_tracefile
,
1244 events_request
->event
,
1245 events_request
->event_by_id_channel
);
1250 /* 2. Else, list_in is not empty, we continue a read */
1253 /* 2.0 For each req of list_in */
1254 GSList
*iter
= list_in
;
1256 while(iter
!= NULL
) {
1258 EventsRequest
*events_request
= (EventsRequest
*)iter
->data
;
1260 /* - Call before chunk
1261 * - events hooks added
1263 if(events_request
->trace
== -1)
1264 lttv_process_traceset_begin(tsc
,
1265 events_request
->before_chunk_traceset
,
1266 events_request
->before_chunk_trace
,
1267 events_request
->before_chunk_tracefile
,
1268 events_request
->event
,
1269 events_request
->event_by_id_channel
);
1271 guint nb_trace
= lttv_traceset_number(tsc
->ts
);
1272 g_assert((guint
)events_request
->trace
< nb_trace
&&
1273 events_request
->trace
> -1);
1274 LttvTraceContext
*tc
= tsc
->traces
[events_request
->trace
];
1276 lttv_hooks_call(events_request
->before_chunk_traceset
, tsc
);
1278 lttv_trace_context_add_hooks(tc
,
1279 events_request
->before_chunk_trace
,
1280 events_request
->before_chunk_tracefile
,
1281 events_request
->event
,
1282 events_request
->event_by_id_channel
);
1285 iter
= g_slist_next(iter
);
1290 tfc
= lttv_traceset_context_get_current_tfc(tsc
);
1292 /* 2.1 For each req of list_out */
1293 GSList
*iter
= list_out
;
1295 while(iter
!= NULL
) {
1297 gboolean remove
= FALSE
;
1298 gboolean free_data
= FALSE
;
1299 EventsRequest
*events_request
= (EventsRequest
*)iter
->data
;
1301 /* if req.start time == current context time
1302 * or req.start position == current position*/
1303 if( ltt_time_compare(events_request
->start_time
,
1304 tfc
->timestamp
) == 0
1306 (events_request
->start_position
!= NULL
1308 lttv_traceset_context_ctx_pos_compare(tsc
,
1309 events_request
->start_position
) == 0)
1311 /* - Add to list_in, remove from list_out */
1312 list_in
= g_slist_append(list_in
, events_request
);
1316 /* - If !servicing */
1317 if(events_request
->servicing
== FALSE
) {
1318 /* - begin request hooks called
1319 * - servicing = TRUE
1321 lttv_hooks_call(events_request
->before_request
, (gpointer
)tsc
);
1322 events_request
->servicing
= TRUE
;
1324 /* call before chunk
1325 * events hooks added
1327 if(events_request
->trace
== -1)
1328 lttv_process_traceset_begin(tsc
,
1329 events_request
->before_chunk_traceset
,
1330 events_request
->before_chunk_trace
,
1331 events_request
->before_chunk_tracefile
,
1332 events_request
->event
,
1333 events_request
->event_by_id_channel
);
1335 guint nb_trace
= lttv_traceset_number(tsc
->ts
);
1336 g_assert((guint
)events_request
->trace
< nb_trace
&&
1337 events_request
->trace
> -1);
1338 LttvTraceContext
*tc
= tsc
->traces
[events_request
->trace
];
1340 lttv_hooks_call(events_request
->before_chunk_traceset
, tsc
);
1342 lttv_trace_context_add_hooks(tc
,
1343 events_request
->before_chunk_trace
,
1344 events_request
->before_chunk_tracefile
,
1345 events_request
->event
,
1346 events_request
->event_by_id_channel
);
1355 GSList
*remove_iter
= iter
;
1357 iter
= g_slist_next(iter
);
1358 if(free_data
) events_request_free((EventsRequest
*)remove_iter
->data
);
1359 list_out
= g_slist_remove_link(list_out
, remove_iter
);
1360 } else { // not remove
1361 iter
= g_slist_next(iter
);
1367 /* 3. Find end criterions */
1372 /* 3.1.1 Find lowest end time in list_in */
1373 g_assert(g_slist_length(list_in
)>0);
1374 end_time
= ((EventsRequest
*)g_slist_nth_data(list_in
,0))->end_time
;
1376 for(iter
=g_slist_nth(list_in
,1);iter
!=NULL
;iter
=g_slist_next(iter
)) {
1377 EventsRequest
*events_request
= (EventsRequest
*)iter
->data
;
1379 if(ltt_time_compare(events_request
->end_time
,
1381 end_time
= events_request
->end_time
;
1384 /* 3.1.2 Find lowest start time in list_out */
1385 for(iter
=list_out
;iter
!=NULL
;iter
=g_slist_next(iter
)) {
1386 EventsRequest
*events_request
= (EventsRequest
*)iter
->data
;
1388 if(ltt_time_compare(events_request
->start_time
,
1390 end_time
= events_request
->start_time
;
1395 /* 3.2 Number of events */
1397 /* 3.2.1 Find lowest number of events in list_in */
1400 end_nb_events
= ((EventsRequest
*)g_slist_nth_data(list_in
,0))->num_events
;
1402 for(iter
=g_slist_nth(list_in
,1);iter
!=NULL
;iter
=g_slist_next(iter
)) {
1403 EventsRequest
*events_request
= (EventsRequest
*)iter
->data
;
1405 if(events_request
->num_events
< end_nb_events
)
1406 end_nb_events
= events_request
->num_events
;
1409 /* 3.2.2 Use min(CHUNK_NUM_EVENTS, min num events in list_in) as
1412 end_nb_events
= MIN(CHUNK_NUM_EVENTS
, end_nb_events
);
1416 /* 3.3 End position */
1418 /* 3.3.1 Find lowest end position in list_in */
1421 end_position
=((EventsRequest
*)g_slist_nth_data(list_in
,0))->end_position
;
1423 for(iter
=g_slist_nth(list_in
,1);iter
!=NULL
;iter
=g_slist_next(iter
)) {
1424 EventsRequest
*events_request
= (EventsRequest
*)iter
->data
;
1426 if(events_request
->end_position
!= NULL
&& end_position
!= NULL
&&
1427 lttv_traceset_context_pos_pos_compare(events_request
->end_position
,
1429 end_position
= events_request
->end_position
;
1434 /* 3.3.2 Find lowest start position in list_out */
1437 for(iter
=list_out
;iter
!=NULL
;iter
=g_slist_next(iter
)) {
1438 EventsRequest
*events_request
= (EventsRequest
*)iter
->data
;
1440 if(events_request
->end_position
!= NULL
&& end_position
!= NULL
&&
1441 lttv_traceset_context_pos_pos_compare(events_request
->end_position
,
1443 end_position
= events_request
->end_position
;
1448 /* 4. Call process traceset middle */
1449 g_debug("Calling process traceset middle with %p, %lu sec %lu nsec, %u nb ev, %p end pos", tsc
, end_time
.tv_sec
, end_time
.tv_nsec
, end_nb_events
, end_position
);
1450 count
= lttv_process_traceset_middle(tsc
, end_time
, end_nb_events
, end_position
);
1452 tfc
= lttv_traceset_context_get_current_tfc(tsc
);
1454 g_debug("Context time after middle : %lu, %lu", tfc
->timestamp
.tv_sec
,
1455 tfc
->timestamp
.tv_nsec
);
1457 g_debug("End of trace reached after middle.");
1461 /* 5. After process traceset middle */
1462 tfc
= lttv_traceset_context_get_current_tfc(tsc
);
1464 /* - if current context time > traceset.end time */
1465 if(tfc
== NULL
|| ltt_time_compare(tfc
->timestamp
,
1466 tsc
->time_span
.end_time
) > 0) {
1467 /* - For each req in list_in */
1468 GSList
*iter
= list_in
;
1470 while(iter
!= NULL
) {
1472 gboolean remove
= FALSE
;
1473 gboolean free_data
= FALSE
;
1474 EventsRequest
*events_request
= (EventsRequest
*)iter
->data
;
1476 /* - Remove events hooks for req
1477 * - Call end chunk for req
1480 if(events_request
->trace
== -1)
1481 lttv_process_traceset_end(tsc
,
1482 events_request
->after_chunk_traceset
,
1483 events_request
->after_chunk_trace
,
1484 events_request
->after_chunk_tracefile
,
1485 events_request
->event
,
1486 events_request
->event_by_id_channel
);
1489 guint nb_trace
= lttv_traceset_number(tsc
->ts
);
1490 g_assert(events_request
->trace
< nb_trace
&&
1491 events_request
->trace
> -1);
1492 LttvTraceContext
*tc
= tsc
->traces
[events_request
->trace
];
1494 lttv_trace_context_remove_hooks(tc
,
1495 events_request
->after_chunk_trace
,
1496 events_request
->after_chunk_tracefile
,
1497 events_request
->event
,
1498 events_request
->event_by_id_channel
);
1499 lttv_hooks_call(events_request
->after_chunk_traceset
, tsc
);
1504 /* - Call end request for req */
1505 lttv_hooks_call(events_request
->after_request
, (gpointer
)tsc
);
1507 /* - remove req from list_in */
1508 /* Destroy the request */
1515 GSList
*remove_iter
= iter
;
1517 iter
= g_slist_next(iter
);
1518 if(free_data
) events_request_free((EventsRequest
*)remove_iter
->data
);
1519 list_in
= g_slist_remove_link(list_in
, remove_iter
);
1520 } else { // not remove
1521 iter
= g_slist_next(iter
);
1526 /* 5.1 For each req in list_in */
1527 GSList
*iter
= list_in
;
1529 while(iter
!= NULL
) {
1531 gboolean remove
= FALSE
;
1532 gboolean free_data
= FALSE
;
1533 EventsRequest
*events_request
= (EventsRequest
*)iter
->data
;
1535 /* - Remove events hooks for req
1536 * - Call end chunk for req
1538 if(events_request
->trace
== -1)
1539 lttv_process_traceset_end(tsc
,
1540 events_request
->after_chunk_traceset
,
1541 events_request
->after_chunk_trace
,
1542 events_request
->after_chunk_tracefile
,
1543 events_request
->event
,
1544 events_request
->event_by_id_channel
);
1547 guint nb_trace
= lttv_traceset_number(tsc
->ts
);
1548 g_assert(events_request
->trace
< nb_trace
&&
1549 events_request
->trace
> -1);
1550 LttvTraceContext
*tc
= tsc
->traces
[events_request
->trace
];
1552 lttv_trace_context_remove_hooks(tc
,
1553 events_request
->after_chunk_trace
,
1554 events_request
->after_chunk_tracefile
,
1555 events_request
->event
,
1556 events_request
->event_by_id_channel
);
1558 lttv_hooks_call(events_request
->after_chunk_traceset
, tsc
);
1561 /* - req.num -= count */
1562 g_assert(events_request
->num_events
>= count
);
1563 events_request
->num_events
-= count
;
1565 g_assert(tfc
!= NULL
);
1566 /* - if req.num == 0
1568 * current context time >= req.end time
1570 * req.end pos == current pos
1572 * req.stop_flag == TRUE
1574 if( events_request
->num_events
== 0
1576 events_request
->stop_flag
== TRUE
1578 ltt_time_compare(tfc
->timestamp
,
1579 events_request
->end_time
) >= 0
1581 (events_request
->end_position
!= NULL
1583 lttv_traceset_context_ctx_pos_compare(tsc
,
1584 events_request
->end_position
) == 0)
1587 g_assert(events_request
->servicing
== TRUE
);
1588 /* - Call end request for req
1589 * - remove req from list_in */
1590 lttv_hooks_call(events_request
->after_request
, (gpointer
)tsc
);
1591 /* - remove req from list_in */
1592 /* Destroy the request */
1600 GSList
*remove_iter
= iter
;
1602 iter
= g_slist_next(iter
);
1603 if(free_data
) events_request_free((EventsRequest
*)remove_iter
->data
);
1604 list_in
= g_slist_remove_link(list_in
, remove_iter
);
1605 } else { // not remove
1606 iter
= g_slist_next(iter
);
1612 /* End of removed servicing loop : leave control to GTK instead. */
1613 // if(gtk_events_pending()) break;
1616 /* B. When interrupted between chunks */
1619 GSList
*iter
= list_in
;
1621 /* 1. for each request in list_in */
1622 while(iter
!= NULL
) {
1624 gboolean remove
= FALSE
;
1625 gboolean free_data
= FALSE
;
1626 EventsRequest
*events_request
= (EventsRequest
*)iter
->data
;
1628 /* 1.1. Use current postition as start position */
1629 if(events_request
->start_position
!= NULL
)
1630 lttv_traceset_context_position_destroy(events_request
->start_position
);
1631 events_request
->start_position
= lttv_traceset_context_position_new(tsc
);
1632 lttv_traceset_context_position_save(tsc
, events_request
->start_position
);
1634 /* 1.2. Remove start time */
1635 events_request
->start_time
= ltt_time_infinite
;
1637 /* 1.3. Move from list_in to list_out */
1640 list_out
= g_slist_append(list_out
, events_request
);
1645 GSList
*remove_iter
= iter
;
1647 iter
= g_slist_next(iter
);
1648 if(free_data
) events_request_free((EventsRequest
*)remove_iter
->data
);
1649 list_in
= g_slist_remove_link(list_in
, remove_iter
);
1650 } else { // not remove
1651 iter
= g_slist_next(iter
);
1657 /* C Unlock Traces */
1659 lttv_process_traceset_get_sync_data(tsc
);
1660 //lttv_traceset_context_position_save(tsc, sync_position);
1665 iter_trace
<lttv_traceset_number(tsc
->ts
);
1667 LttvTrace
*trace_v
= lttv_traceset_get(tsc
->ts
, iter_trace
);
1669 lttvwindowtraces_unlock(trace_v
);
1673 //set the cursor back to normal
1674 gdk_window_set_cursor(win
, NULL
);
1677 g_assert(g_slist_length(list_in
) == 0);
1679 if( g_slist_length(list_out
) == 0 ) {
1680 /* Put tab's request pending flag back to normal */
1681 tab
->events_request_pending
= FALSE
;
1682 g_debug("remove the idle fct");
1683 return FALSE
; /* Remove the idle function */
1685 g_debug("leave the idle fct");
1686 return TRUE
; /* Leave the idle function */
1688 /* We do not use simili-round-robin, it may require to read 1 meg buffers
1689 * again and again if many tracesets use the same tracefiles. */
1690 /* Hack for round-robin idle functions */
1691 /* It will put the idle function at the end of the pool */
1692 /*g_idle_add_full((G_PRIORITY_HIGH_IDLE + 21),
1693 (GSourceFunc)execute_events_requests,
1703 static void lttvwindow_add_trace(Tab
*tab
, LttvTrace
*trace_v
)
1705 LttvTraceset
*traceset
= tab
->traceset_info
->traceset
;
1707 guint num_traces
= lttv_traceset_number(traceset
);
1709 //Verify if trace is already present.
1710 for(i
=0; i
<num_traces
; i
++)
1712 LttvTrace
* trace
= lttv_traceset_get(traceset
, i
);
1713 if(trace
== trace_v
)
1717 //Keep a reference to the traces so they are not freed.
1718 for(i
=0; i
<lttv_traceset_number(traceset
); i
++)
1720 LttvTrace
* trace
= lttv_traceset_get(traceset
, i
);
1721 lttv_trace_ref(trace
);
1724 //remove state update hooks
1725 lttv_state_remove_event_hooks(
1726 (LttvTracesetState
*)tab
->traceset_info
->traceset_context
);
1728 lttv_context_fini(LTTV_TRACESET_CONTEXT(
1729 tab
->traceset_info
->traceset_context
));
1730 g_object_unref(tab
->traceset_info
->traceset_context
);
1732 lttv_traceset_add(traceset
, trace_v
);
1733 lttv_trace_ref(trace_v
); /* local ref */
1735 /* Create new context */
1736 tab
->traceset_info
->traceset_context
=
1737 g_object_new(LTTV_TRACESET_STATS_TYPE
, NULL
);
1739 LTTV_TRACESET_CONTEXT(tab
->traceset_info
->
1744 //add state update hooks
1745 lttv_state_add_event_hooks(
1746 (LttvTracesetState
*)tab
->traceset_info
->traceset_context
);
1747 //Remove local reference to the traces.
1748 for(i
=0; i
<lttv_traceset_number(traceset
); i
++)
1750 LttvTrace
* trace
= lttv_traceset_get(traceset
, i
);
1751 lttv_trace_unref(trace
);
1755 //add_trace_into_traceset_selector(GTK_MULTIVPANED(tab->multivpaned), lttv_trace(trace_v));
1758 /* add_trace adds a trace into the current traceset. It first displays a
1759 * directory selection dialogue to let user choose a trace, then recreates
1760 * tracset_context, and redraws all the viewer of the current tab
1763 void add_trace(GtkWidget
* widget
, gpointer user_data
)
1766 LttvTrace
* trace_v
;
1767 LttvTraceset
* traceset
;
1769 char abs_path
[PATH_MAX
];
1771 MainWindow
* mw_data
= get_window_data_struct(widget
);
1772 GtkWidget
* notebook
= lookup_widget(widget
, "MNotebook");
1774 GtkWidget
*page
= gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook
),
1775 gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook
)));
1776 LttvPluginTab
*ptab
;
1780 ptab
= create_new_tab(widget
, NULL
);
1783 ptab
= (LttvPluginTab
*)g_object_get_data(G_OBJECT(page
), "Tab_Plugin");
1787 //GtkDirSelection * file_selector = (GtkDirSelection *)gtk_dir_selection_new("Select a trace");
1788 GtkFileSelection
* file_selector
= (GtkFileSelection
*)gtk_file_selection_new("Select a trace");
1789 gtk_widget_hide( (file_selector
)->file_list
->parent
) ;
1790 gtk_file_selection_hide_fileop_buttons(file_selector
);
1791 gtk_window_set_transient_for(GTK_WINDOW(file_selector
),
1792 GTK_WINDOW(mw_data
->mwindow
));
1794 if(remember_trace_dir
[0] != '\0')
1795 gtk_file_selection_set_filename(file_selector
, remember_trace_dir
);
1797 id
= gtk_dialog_run(GTK_DIALOG(file_selector
));
1799 case GTK_RESPONSE_ACCEPT
:
1800 case GTK_RESPONSE_OK
:
1801 dir
= gtk_file_selection_get_filename (file_selector
);
1802 strncpy(remember_trace_dir
, dir
, PATH_MAX
);
1803 strncat(remember_trace_dir
, "/", PATH_MAX
);
1804 if(!dir
|| strlen(dir
) == 0){
1805 gtk_widget_destroy((GtkWidget
*)file_selector
);
1808 get_absolute_pathname(dir
, abs_path
);
1809 trace_v
= lttvwindowtraces_get_trace_by_name(abs_path
);
1810 if(trace_v
== NULL
) {
1811 trace
= ltt_trace_open(abs_path
);
1813 g_warning("cannot open trace %s", abs_path
);
1815 GtkWidget
*dialogue
=
1816 gtk_message_dialog_new(
1817 GTK_WINDOW(gtk_widget_get_toplevel(widget
)),
1818 GTK_DIALOG_MODAL
|GTK_DIALOG_DESTROY_WITH_PARENT
,
1821 "Cannot open trace : maybe you should enter in the trace "
1822 "directory to select it ?");
1823 gtk_dialog_run(GTK_DIALOG(dialogue
));
1824 gtk_widget_destroy(dialogue
);
1827 trace_v
= lttv_trace_new(trace
);
1828 lttvwindowtraces_add_trace(trace_v
);
1829 lttvwindow_add_trace(tab
, trace_v
);
1832 lttvwindow_add_trace(tab
, trace_v
);
1835 gtk_widget_destroy((GtkWidget
*)file_selector
);
1837 //update current tab
1838 //update_traceset(mw_data);
1840 /* Call the updatetraceset hooks */
1842 traceset
= tab
->traceset_info
->traceset
;
1843 SetTraceset(tab
, traceset
);
1844 // in expose now call_pending_read_hooks(mw_data);
1846 //lttvwindow_report_current_time(mw_data,&(tab->current_time));
1848 case GTK_RESPONSE_REJECT
:
1849 case GTK_RESPONSE_CANCEL
:
1851 gtk_widget_destroy((GtkWidget
*)file_selector
);
1856 /* remove_trace removes a trace from the current traceset if all viewers in
1857 * the current tab are not interested in the trace. It first displays a
1858 * dialogue, which shows all traces in the current traceset, to let user choose
1859 * a trace, then it checks if all viewers unselect the trace, if it is true,
1860 * it will remove the trace, recreate the traceset_contex,
1861 * and redraws all the viewer of the current tab. If there is on trace in the
1862 * current traceset, it will delete all viewers of the current tab
1864 * It destroys the filter tree. FIXME... we should request for an update
1868 void remove_trace(GtkWidget
*widget
, gpointer user_data
)
1871 LttvTrace
* trace_v
;
1872 LttvTraceset
* traceset
;
1873 gint i
, j
, nb_trace
, index
=-1;
1874 char ** name
, *remove_trace_name
;
1875 MainWindow
* mw_data
= get_window_data_struct(widget
);
1876 GtkWidget
* notebook
= lookup_widget(widget
, "MNotebook");
1878 GtkWidget
*page
= gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook
),
1879 gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook
)));
1885 LttvPluginTab
*ptab
;
1886 ptab
= (LttvPluginTab
*)g_object_get_data(G_OBJECT(page
), "Tab_Plugin");
1890 nb_trace
=lttv_traceset_number(tab
->traceset_info
->traceset
);
1891 name
= g_new(char*,nb_trace
);
1892 for(i
= 0; i
< nb_trace
; i
++){
1893 trace_v
= lttv_traceset_get(tab
->traceset_info
->traceset
, i
);
1894 trace
= lttv_trace(trace_v
);
1895 name
[i
] = g_quark_to_string(ltt_trace_name(trace
));
1898 remove_trace_name
= get_remove_trace(mw_data
, name
, nb_trace
);
1901 if(remove_trace_name
){
1903 /* yuk, cut n paste from old code.. should be better (MD)*/
1904 for(i
= 0; i
<nb_trace
; i
++) {
1905 if(strcmp(remove_trace_name
,name
[i
]) == 0){
1910 traceset
= tab
->traceset_info
->traceset
;
1911 //Keep a reference to the traces so they are not freed.
1912 for(j
=0; j
<lttv_traceset_number(traceset
); j
++)
1914 LttvTrace
* trace
= lttv_traceset_get(traceset
, j
);
1915 lttv_trace_ref(trace
);
1918 //remove state update hooks
1919 lttv_state_remove_event_hooks(
1920 (LttvTracesetState
*)tab
->traceset_info
->traceset_context
);
1921 lttv_context_fini(LTTV_TRACESET_CONTEXT(tab
->traceset_info
->traceset_context
));
1922 g_object_unref(tab
->traceset_info
->traceset_context
);
1924 trace_v
= lttv_traceset_get(traceset
, index
);
1926 lttv_traceset_remove(traceset
, index
);
1927 lttv_trace_unref(trace_v
); // Remove local reference
1929 if(lttv_trace_get_ref_number(trace_v
) <= 1) {
1930 /* ref 1 : lttvwindowtraces only*/
1931 ltt_trace_close(lttv_trace(trace_v
));
1932 /* lttvwindowtraces_remove_trace takes care of destroying
1933 * the traceset linked with the trace_v and also of destroying
1934 * the trace_v at the same time.
1936 lttvwindowtraces_remove_trace(trace_v
);
1939 tab
->traceset_info
->traceset_context
=
1940 g_object_new(LTTV_TRACESET_STATS_TYPE
, NULL
);
1942 LTTV_TRACESET_CONTEXT(tab
->
1943 traceset_info
->traceset_context
),traceset
);
1944 //add state update hooks
1945 lttv_state_add_event_hooks(
1946 (LttvTracesetState
*)tab
->traceset_info
->traceset_context
);
1948 //Remove local reference to the traces.
1949 for(j
=0; j
<lttv_traceset_number(traceset
); j
++)
1951 LttvTrace
* trace
= lttv_traceset_get(traceset
, j
);
1952 lttv_trace_unref(trace
);
1955 SetTraceset(tab
, (gpointer
)traceset
);
1961 void remove_trace(GtkWidget
* widget
, gpointer user_data
)
1964 LttvTrace
* trace_v
;
1965 LttvTraceset
* traceset
;
1966 gint i
, j
, nb_trace
;
1967 char ** name
, *remove_trace_name
;
1968 MainWindow
* mw_data
= get_window_data_struct(widget
);
1969 LttvTracesetSelector
* s
;
1970 LttvTraceSelector
* t
;
1973 GtkWidget
* notebook
= lookup_widget(widget
, "MNotebook");
1975 GtkWidget
*page
= gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook
),
1976 gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook
)));
1982 tab
= (Tab
*)g_object_get_data(G_OBJECT(page
), "Tab_Info");
1985 nb_trace
=lttv_traceset_number(tab
->traceset_info
->traceset
);
1986 name
= g_new(char*,nb_trace
);
1987 for(i
= 0; i
< nb_trace
; i
++){
1988 trace_v
= lttv_traceset_get(tab
->traceset_info
->traceset
, i
);
1989 trace
= lttv_trace(trace_v
);
1990 name
[i
] = ltt_trace_name(trace
);
1993 remove_trace_name
= get_remove_trace(name
, nb_trace
);
1995 if(remove_trace_name
){
1996 for(i
=0; i
<nb_trace
; i
++){
1997 if(strcmp(remove_trace_name
,name
[i
]) == 0){
1998 //unselect the trace from the current viewer
2000 w
= gtk_multivpaned_get_widget(GTK_MULTIVPANED(tab
->multivpaned
));
2002 s
= g_object_get_data(G_OBJECT(w
), "Traceset_Selector");
2004 t
= lttv_traceset_selector_trace_get(s
,i
);
2005 lttv_trace_selector_set_selected(t
, FALSE
);
2008 //check if other viewers select the trace
2009 w
= gtk_multivpaned_get_first_widget(GTK_MULTIVPANED(tab
->multivpaned
));
2011 s
= g_object_get_data(G_OBJECT(w
), "Traceset_Selector");
2013 t
= lttv_traceset_selector_trace_get(s
,i
);
2014 selected
= lttv_trace_selector_get_selected(t
);
2017 w
= gtk_multivpaned_get_next_widget(GTK_MULTIVPANED(tab
->multivpaned
));
2019 }else selected
= FALSE
;
2021 //if no viewer selects the trace, remove it
2023 remove_trace_from_traceset_selector(GTK_MULTIVPANED(tab
->multivpaned
), i
);
2025 traceset
= tab
->traceset_info
->traceset
;
2026 //Keep a reference to the traces so they are not freed.
2027 for(j
=0; j
<lttv_traceset_number(traceset
); j
++)
2029 LttvTrace
* trace
= lttv_traceset_get(traceset
, j
);
2030 lttv_trace_ref(trace
);
2033 //remove state update hooks
2034 lttv_state_remove_event_hooks(
2035 (LttvTracesetState
*)tab
->traceset_info
->traceset_context
);
2036 lttv_context_fini(LTTV_TRACESET_CONTEXT(tab
->traceset_info
->traceset_context
));
2037 g_object_unref(tab
->traceset_info
->traceset_context
);
2040 trace_v
= lttv_traceset_get(traceset
, i
);
2042 if(lttv_trace_get_ref_number(trace_v
) <= 2) {
2043 /* ref 2 : traceset, local */
2044 lttvwindowtraces_remove_trace(trace_v
);
2045 ltt_trace_close(lttv_trace(trace_v
));
2048 lttv_traceset_remove(traceset
, i
);
2049 lttv_trace_unref(trace_v
); // Remove local reference
2051 if(!lttv_trace_get_ref_number(trace_v
))
2052 lttv_trace_destroy(trace_v
);
2054 tab
->traceset_info
->traceset_context
=
2055 g_object_new(LTTV_TRACESET_STATS_TYPE
, NULL
);
2057 LTTV_TRACESET_CONTEXT(tab
->
2058 traceset_info
->traceset_context
),traceset
);
2059 //add state update hooks
2060 lttv_state_add_event_hooks(
2061 (LttvTracesetState
*)tab
->traceset_info
->traceset_context
);
2063 //Remove local reference to the traces.
2064 for(j
=0; j
<lttv_traceset_number(traceset
); j
++)
2066 LttvTrace
* trace
= lttv_traceset_get(traceset
, j
);
2067 lttv_trace_unref(trace
);
2071 //update current tab
2072 //update_traceset(mw_data);
2075 SetTraceset(tab
, (gpointer
)traceset
);
2076 // in expose now call_pending_read_hooks(mw_data);
2078 //lttvwindow_report_current_time(mw_data,&(tab->current_time));
2081 // while(tab->multi_vpaned->num_children){
2082 // gtk_multi_vpaned_widget_delete(tab->multi_vpaned);
2096 /* Redraw all the viewers in the current tab */
2097 void redraw(GtkWidget
*widget
, gpointer user_data
)
2099 GtkWidget
* notebook
= lookup_widget(widget
, "MNotebook");
2100 GtkWidget
*page
= gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook
),
2101 gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook
)));
2106 LttvPluginTab
*ptab
;
2107 ptab
= (LttvPluginTab
*)g_object_get_data(G_OBJECT(page
), "Tab_Plugin");
2112 LttvAttributeValue value
;
2114 g_assert(lttv_iattribute_find_by_path(tab
->attributes
, "hooks/redraw", LTTV_POINTER
, &value
));
2116 tmp
= (LttvHooks
*)*(value
.v_pointer
);
2118 lttv_hooks_call(tmp
,NULL
);
2122 void continue_processing(GtkWidget
*widget
, gpointer user_data
)
2124 GtkWidget
* notebook
= lookup_widget(widget
, "MNotebook");
2125 GtkWidget
*page
= gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook
),
2126 gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook
)));
2131 LttvPluginTab
*ptab
;
2132 ptab
= (LttvPluginTab
*)g_object_get_data(G_OBJECT(page
), "Tab_Plugin");
2137 LttvAttributeValue value
;
2139 g_assert(lttv_iattribute_find_by_path(tab
->attributes
,
2140 "hooks/continue", LTTV_POINTER
, &value
));
2142 tmp
= (LttvHooks
*)*(value
.v_pointer
);
2144 lttv_hooks_call(tmp
,NULL
);
2147 /* Stop the processing for the calling main window's current tab.
2148 * It removes every processing requests that are in its list. It does not call
2149 * the end request hooks, because the request is not finished.
2152 void stop_processing(GtkWidget
*widget
, gpointer user_data
)
2154 GtkWidget
* notebook
= lookup_widget(widget
, "MNotebook");
2155 GtkWidget
*page
= gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook
),
2156 gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook
)));
2161 LttvPluginTab
*ptab
;
2162 ptab
= (LttvPluginTab
*)g_object_get_data(G_OBJECT(page
), "Tab_Plugin");
2165 GSList
*iter
= tab
->events_requests
;
2167 while(iter
!= NULL
) {
2168 GSList
*remove_iter
= iter
;
2169 iter
= g_slist_next(iter
);
2171 g_free(remove_iter
->data
);
2172 tab
->events_requests
=
2173 g_slist_remove_link(tab
->events_requests
, remove_iter
);
2175 tab
->events_request_pending
= FALSE
;
2176 tab
->stop_foreground
= TRUE
;
2177 g_idle_remove_by_data(tab
);
2178 g_assert(g_slist_length(tab
->events_requests
) == 0);
2182 /* save will save the traceset to a file
2183 * Not implemented yet FIXME
2186 void save(GtkWidget
* widget
, gpointer user_data
)
2191 void save_as(GtkWidget
* widget
, gpointer user_data
)
2193 g_info("Save as\n");
2197 /* zoom will change the time_window of all the viewers of the
2198 * current tab, and redisplay them. The main functionality is to
2199 * determine the new time_window of the current tab
2202 void zoom(GtkWidget
* widget
, double size
)
2204 TimeInterval time_span
;
2205 TimeWindow new_time_window
;
2206 LttTime current_time
, time_delta
;
2207 MainWindow
* mw_data
= get_window_data_struct(widget
);
2208 LttvTracesetContext
*tsc
;
2209 GtkWidget
* notebook
= lookup_widget(widget
, "MNotebook");
2211 GtkWidget
*page
= gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook
),
2212 gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook
)));
2218 LttvPluginTab
*ptab
;
2219 ptab
= (LttvPluginTab
*)g_object_get_data(G_OBJECT(page
), "Tab_Plugin");
2223 if(size
== 1) return;
2225 tsc
= LTTV_TRACESET_CONTEXT(tab
->traceset_info
->traceset_context
);
2226 time_span
= tsc
->time_span
;
2227 new_time_window
= tab
->time_window
;
2228 current_time
= tab
->current_time
;
2230 time_delta
= ltt_time_sub(time_span
.end_time
,time_span
.start_time
);
2232 new_time_window
.start_time
= time_span
.start_time
;
2233 new_time_window
.time_width
= time_delta
;
2234 new_time_window
.time_width_double
= ltt_time_to_double(time_delta
);
2235 new_time_window
.end_time
= ltt_time_add(new_time_window
.start_time
,
2236 new_time_window
.time_width
) ;
2238 new_time_window
.time_width
= ltt_time_div(new_time_window
.time_width
, size
);
2239 new_time_window
.time_width_double
=
2240 ltt_time_to_double(new_time_window
.time_width
);
2241 if(ltt_time_compare(new_time_window
.time_width
,time_delta
) > 0)
2242 { /* Case where zoom out is bigger than trace length */
2243 new_time_window
.start_time
= time_span
.start_time
;
2244 new_time_window
.time_width
= time_delta
;
2245 new_time_window
.time_width_double
= ltt_time_to_double(time_delta
);
2246 new_time_window
.end_time
= ltt_time_add(new_time_window
.start_time
,
2247 new_time_window
.time_width
) ;
2251 /* Center the image on the current time */
2252 new_time_window
.start_time
=
2253 ltt_time_sub(current_time
,
2254 ltt_time_from_double(new_time_window
.time_width_double
/2.0));
2255 new_time_window
.end_time
= ltt_time_add(new_time_window
.start_time
,
2256 new_time_window
.time_width
) ;
2257 /* If on borders, don't fall off */
2258 if(ltt_time_compare(new_time_window
.start_time
, time_span
.start_time
) <0
2259 || ltt_time_compare(new_time_window
.start_time
, time_span
.end_time
) >0)
2261 new_time_window
.start_time
= time_span
.start_time
;
2262 new_time_window
.end_time
= ltt_time_add(new_time_window
.start_time
,
2263 new_time_window
.time_width
) ;
2267 if(ltt_time_compare(new_time_window
.end_time
,
2268 time_span
.end_time
) > 0
2269 || ltt_time_compare(new_time_window
.end_time
,
2270 time_span
.start_time
) < 0)
2272 new_time_window
.start_time
=
2273 ltt_time_sub(time_span
.end_time
, new_time_window
.time_width
);
2275 new_time_window
.end_time
= ltt_time_add(new_time_window
.start_time
,
2276 new_time_window
.time_width
) ;
2283 if(ltt_time_compare(new_time_window
.time_width
, ltt_time_zero
) == 0) {
2284 g_warning("Zoom more than 1 ns impossible");
2286 time_change_manager(tab
, new_time_window
);
2290 void zoom_in(GtkWidget
* widget
, gpointer user_data
)
2295 void zoom_out(GtkWidget
* widget
, gpointer user_data
)
2300 void zoom_extended(GtkWidget
* widget
, gpointer user_data
)
2305 void go_to_time(GtkWidget
* widget
, gpointer user_data
)
2307 g_info("Go to time\n");
2310 void show_time_frame(GtkWidget
* widget
, gpointer user_data
)
2312 g_info("Show time frame\n");
2316 /* callback function */
2319 on_empty_traceset_activate (GtkMenuItem
*menuitem
,
2322 create_new_window((GtkWidget
*)menuitem
, user_data
, FALSE
);
2327 on_clone_traceset_activate (GtkMenuItem
*menuitem
,
2330 create_new_window((GtkWidget
*)menuitem
, user_data
, TRUE
);
2334 /* create_new_tab calls create_tab to construct a new tab in the main window
2337 LttvPluginTab
*create_new_tab(GtkWidget
* widget
, gpointer user_data
)
2339 gchar label
[PATH_MAX
];
2340 MainWindow
* mw_data
= get_window_data_struct(widget
);
2342 GtkNotebook
* notebook
= (GtkNotebook
*)lookup_widget(widget
, "MNotebook");
2343 if(notebook
== NULL
){
2344 g_info("Notebook does not exist\n");
2347 GtkWidget
*page
= gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook
),
2348 gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook
)));
2354 LttvPluginTab
*ptab
;
2355 ptab
= (LttvPluginTab
*)g_object_get_data(G_OBJECT(page
), "Tab_Plugin");
2356 copy_tab
= ptab
->tab
;
2359 strcpy(label
,"Page");
2360 if(get_label(mw_data
, label
,"Get the name of the tab","Please input tab's name")) {
2361 LttvPluginTab
*ptab
;
2363 ptab
= g_object_new(LTTV_TYPE_PLUGIN_TAB
, NULL
);
2364 init_tab (ptab
->tab
, mw_data
, copy_tab
, notebook
, label
);
2365 ptab
->parent
.top_widget
= ptab
->tab
->top_widget
;
2366 g_object_set_data_full(
2367 G_OBJECT(ptab
->tab
->vbox
),
2370 (GDestroyNotify
)tab_destructor
);
2377 on_tab_activate (GtkMenuItem
*menuitem
,
2380 create_new_tab((GtkWidget
*)menuitem
, user_data
);
2385 on_open_activate (GtkMenuItem
*menuitem
,
2388 open_traceset((GtkWidget
*)menuitem
, user_data
);
2393 on_close_activate (GtkMenuItem
*menuitem
,
2396 MainWindow
* mw_data
= get_window_data_struct((GtkWidget
*)menuitem
);
2397 main_window_destructor(mw_data
);
2401 /* remove the current tab from the main window
2405 on_close_tab_activate (GtkWidget
*widget
,
2409 GtkWidget
* notebook
;
2411 MainWindow
* mw_data
= get_window_data_struct(widget
);
2412 notebook
= lookup_widget(widget
, "MNotebook");
2413 if(notebook
== NULL
){
2414 g_info("Notebook does not exist\n");
2418 page_num
= gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook
));
2420 gtk_notebook_remove_page(GTK_NOTEBOOK(notebook
), page_num
);
2425 on_close_tab_X_clicked (GtkWidget
*widget
,
2429 GtkWidget
*notebook
= lookup_widget(widget
, "MNotebook");
2430 if(notebook
== NULL
){
2431 g_info("Notebook does not exist\n");
2435 if((page_num
= gtk_notebook_page_num(GTK_NOTEBOOK(notebook
), widget
)) != -1)
2436 gtk_notebook_remove_page(GTK_NOTEBOOK(notebook
), page_num
);
2442 on_add_trace_activate (GtkMenuItem
*menuitem
,
2445 add_trace((GtkWidget
*)menuitem
, user_data
);
2450 on_remove_trace_activate (GtkMenuItem
*menuitem
,
2453 remove_trace((GtkWidget
*)menuitem
, user_data
);
2458 on_save_activate (GtkMenuItem
*menuitem
,
2461 save((GtkWidget
*)menuitem
, user_data
);
2466 on_save_as_activate (GtkMenuItem
*menuitem
,
2469 save_as((GtkWidget
*)menuitem
, user_data
);
2474 on_quit_activate (GtkMenuItem
*menuitem
,
2482 on_cut_activate (GtkMenuItem
*menuitem
,
2490 on_copy_activate (GtkMenuItem
*menuitem
,
2498 on_paste_activate (GtkMenuItem
*menuitem
,
2506 on_delete_activate (GtkMenuItem
*menuitem
,
2514 on_zoom_in_activate (GtkMenuItem
*menuitem
,
2517 zoom_in((GtkWidget
*)menuitem
, user_data
);
2522 on_zoom_out_activate (GtkMenuItem
*menuitem
,
2525 zoom_out((GtkWidget
*)menuitem
, user_data
);
2530 on_zoom_extended_activate (GtkMenuItem
*menuitem
,
2533 zoom_extended((GtkWidget
*)menuitem
, user_data
);
2538 on_go_to_time_activate (GtkMenuItem
*menuitem
,
2541 go_to_time((GtkWidget
*)menuitem
, user_data
);
2546 on_show_time_frame_activate (GtkMenuItem
*menuitem
,
2549 show_time_frame((GtkWidget
*)menuitem
, user_data
);
2554 on_move_viewer_up_activate (GtkMenuItem
*menuitem
,
2557 move_up_viewer((GtkWidget
*)menuitem
, user_data
);
2562 on_move_viewer_down_activate (GtkMenuItem
*menuitem
,
2565 move_down_viewer((GtkWidget
*)menuitem
, user_data
);
2570 on_remove_viewer_activate (GtkMenuItem
*menuitem
,
2573 delete_viewer((GtkWidget
*)menuitem
, user_data
);
2577 on_trace_facility_activate (GtkMenuItem
*menuitem
,
2580 g_info("Trace facility selector: %s\n", "");
2584 /* Dispaly a file selection dialogue to let user select a library, then call
2585 * lttv_library_load().
2589 on_load_library_activate (GtkMenuItem
*menuitem
,
2592 GError
*error
= NULL
;
2593 MainWindow
* mw_data
= get_window_data_struct((GtkWidget
*)menuitem
);
2595 gchar load_module_path_alter
[PATH_MAX
];
2599 gchar
*load_module_path
;
2600 name
= g_ptr_array_new();
2601 nb
= lttv_library_path_number();
2602 /* ask for the library path */
2606 path
= lttv_library_path_get(i
);
2607 g_ptr_array_add(name
, path
);
2610 load_module_path
= get_selection(mw_data
,
2611 (char **)(name
->pdata
), name
->len
,
2612 "Select a library path", "Library paths");
2613 if(load_module_path
!= NULL
)
2614 strncpy(load_module_path_alter
, load_module_path
, PATH_MAX
-1); // -1 for /
2616 g_ptr_array_free(name
, TRUE
);
2618 if(load_module_path
== NULL
) return;
2622 /* Make sure the module path ends with a / */
2623 gchar
*ptr
= load_module_path_alter
;
2625 ptr
= strchr(ptr
, '\0');
2627 if(*(ptr
-1) != '/') {
2634 /* Ask for the library to load : list files in the previously selected
2636 gchar str
[PATH_MAX
];
2639 GtkFileSelection
* file_selector
=
2640 (GtkFileSelection
*)gtk_file_selection_new("Select a module");
2641 gtk_file_selection_set_filename(file_selector
, load_module_path_alter
);
2642 gtk_file_selection_hide_fileop_buttons(file_selector
);
2644 gtk_window_set_transient_for(GTK_WINDOW(file_selector
),
2645 GTK_WINDOW(mw_data
->mwindow
));
2648 id
= gtk_dialog_run(GTK_DIALOG(file_selector
));
2650 case GTK_RESPONSE_ACCEPT
:
2651 case GTK_RESPONSE_OK
:
2652 dir
= gtk_file_selection_get_selections (file_selector
);
2653 strncpy(str
,dir
[0],PATH_MAX
);
2654 strncpy(remember_plugins_dir
,dir
[0],PATH_MAX
);
2655 /* only keep file name */
2657 str1
= strrchr(str
,'/');
2660 str1
= strrchr(str
,'\\');
2665 if(*str1
== 'l' && *(str1
+1)== 'i' && *(str1
+2)=='b')
2667 remove info after
. */
2671 str2
= strrchr(str2
, '.');
2672 if(str2
!= NULL
) *str2
= '\0';
2674 lttv_module_require(str1
, &error
);
2676 lttv_library_load(str1
, &error
);
2677 if(error
!= NULL
) g_warning("%s", error
->message
);
2678 else g_info("Load library: %s\n", str
);
2680 case GTK_RESPONSE_REJECT
:
2681 case GTK_RESPONSE_CANCEL
:
2683 gtk_widget_destroy((GtkWidget
*)file_selector
);
2694 /* Display all loaded modules, let user to select a module to unload
2695 * by calling lttv_module_unload
2699 on_unload_library_activate (GtkMenuItem
*menuitem
,
2702 MainWindow
* mw_data
= get_window_data_struct((GtkWidget
*)menuitem
);
2704 LttvLibrary
*library
= NULL
;
2709 name
= g_ptr_array_new();
2710 nb
= lttv_library_number();
2711 LttvLibraryInfo
*lib_info
= g_new(LttvLibraryInfo
,nb
);
2712 /* ask for the library name */
2715 LttvLibrary
*iter_lib
= lttv_library_get(i
);
2716 lttv_library_info(iter_lib
, &lib_info
[i
]);
2718 gchar
*path
= lib_info
[i
].name
;
2719 g_ptr_array_add(name
, path
);
2721 lib_name
= get_selection(mw_data
, (char **)(name
->pdata
), name
->len
,
2722 "Select a library", "Libraries");
2723 if(lib_name
!= NULL
) {
2725 if(strcmp(lib_name
, lib_info
[i
].name
) == 0) {
2726 library
= lttv_library_get(i
);
2731 g_ptr_array_free(name
, TRUE
);
2734 if(lib_name
== NULL
) return;
2736 if(library
!= NULL
) lttv_library_unload(library
);
2740 /* Dispaly a file selection dialogue to let user select a module, then call
2741 * lttv_module_require().
2745 on_load_module_activate (GtkMenuItem
*menuitem
,
2748 GError
*error
= NULL
;
2749 MainWindow
* mw_data
= get_window_data_struct((GtkWidget
*)menuitem
);
2751 LttvLibrary
*library
= NULL
;
2756 name
= g_ptr_array_new();
2757 nb
= lttv_library_number();
2758 LttvLibraryInfo
*lib_info
= g_new(LttvLibraryInfo
,nb
);
2759 /* ask for the library name */
2762 LttvLibrary
*iter_lib
= lttv_library_get(i
);
2763 lttv_library_info(iter_lib
, &lib_info
[i
]);
2765 gchar
*path
= lib_info
[i
].name
;
2766 g_ptr_array_add(name
, path
);
2768 lib_name
= get_selection(mw_data
,(char **)(name
->pdata
), name
->len
,
2769 "Select a library", "Libraries");
2770 if(lib_name
!= NULL
) {
2772 if(strcmp(lib_name
, lib_info
[i
].name
) == 0) {
2773 library
= lttv_library_get(i
);
2778 g_ptr_array_free(name
, TRUE
);
2781 if(lib_name
== NULL
) return;
2784 //LttvModule *module;
2785 gchar module_name_out
[PATH_MAX
];
2787 /* Ask for the module to load : list modules in the selected lib */
2791 nb
= lttv_library_module_number(library
);
2792 LttvModuleInfo
*module_info
= g_new(LttvModuleInfo
,nb
);
2793 name
= g_ptr_array_new();
2794 /* ask for the module name */
2797 LttvModule
*iter_module
= lttv_library_module_get(library
, i
);
2798 lttv_module_info(iter_module
, &module_info
[i
]);
2800 gchar
*path
= module_info
[i
].name
;
2801 g_ptr_array_add(name
, path
);
2803 module_name
= get_selection(mw_data
, (char **)(name
->pdata
), name
->len
,
2804 "Select a module", "Modules");
2805 if(module_name
!= NULL
) {
2807 if(strcmp(module_name
, module_info
[i
].name
) == 0) {
2808 strncpy(module_name_out
, module_name
, PATH_MAX
);
2809 //module = lttv_library_module_get(i);
2815 g_ptr_array_free(name
, TRUE
);
2816 g_free(module_info
);
2818 if(module_name
== NULL
) return;
2821 lttv_module_require(module_name_out
, &error
);
2822 if(error
!= NULL
) g_warning("%s", error
->message
);
2823 else g_info("Load module: %s", module_name_out
);
2830 gchar str
[PATH_MAX
];
2833 GtkFileSelection
* file_selector
=
2834 (GtkFileSelection
*)gtk_file_selection_new("Select a module");
2835 gtk_file_selection_set_filename(file_selector
, load_module_path_alter
);
2836 gtk_file_selection_hide_fileop_buttons(file_selector
);
2839 id
= gtk_dialog_run(GTK_DIALOG(file_selector
));
2841 case GTK_RESPONSE_ACCEPT
:
2842 case GTK_RESPONSE_OK
:
2843 dir
= gtk_file_selection_get_selections (file_selector
);
2844 strncpy(str
,dir
[0],PATH_MAX
);
2845 strncpy(remember_plugins_dir
,dir
[0],PATH_MAX
);
2847 /* only keep file name */
2849 str1
= strrchr(str
,'/');
2852 str1
= strrchr(str
,'\\');
2857 if(*str1
== 'l' && *(str1
+1)== 'i' && *(str1
+2)=='b')
2859 remove info after
. */
2863 str2
= strrchr(str2
, '.');
2864 if(str2
!= NULL
) *str2
= '\0';
2866 lttv_module_require(str1
, &error
);
2868 lttv_library_load(str1
, &error
);
2869 if(error
!= NULL
) g_warning(error
->message
);
2870 else g_info("Load library: %s\n", str
);
2872 case GTK_RESPONSE_REJECT
:
2873 case GTK_RESPONSE_CANCEL
:
2875 gtk_widget_destroy((GtkWidget
*)file_selector
);
2887 /* Display all loaded modules, let user to select a module to unload
2888 * by calling lttv_module_unload
2892 on_unload_module_activate (GtkMenuItem
*menuitem
,
2895 GError
*error
= NULL
;
2896 MainWindow
* mw_data
= get_window_data_struct((GtkWidget
*)menuitem
);
2898 LttvLibrary
*library
= NULL
;
2903 name
= g_ptr_array_new();
2904 nb
= lttv_library_number();
2905 LttvLibraryInfo
*lib_info
= g_new(LttvLibraryInfo
,nb
);
2906 /* ask for the library name */
2909 LttvLibrary
*iter_lib
= lttv_library_get(i
);
2910 lttv_library_info(iter_lib
, &lib_info
[i
]);
2912 gchar
*path
= lib_info
[i
].name
;
2913 g_ptr_array_add(name
, path
);
2915 lib_name
= get_selection(mw_data
, (char **)(name
->pdata
), name
->len
,
2916 "Select a library", "Libraries");
2917 if(lib_name
!= NULL
) {
2919 if(strcmp(lib_name
, lib_info
[i
].name
) == 0) {
2920 library
= lttv_library_get(i
);
2925 g_ptr_array_free(name
, TRUE
);
2928 if(lib_name
== NULL
) return;
2931 LttvModule
*module
= NULL
;
2933 /* Ask for the module to load : list modules in the selected lib */
2937 nb
= lttv_library_module_number(library
);
2938 LttvModuleInfo
*module_info
= g_new(LttvModuleInfo
,nb
);
2939 name
= g_ptr_array_new();
2940 /* ask for the module name */
2943 LttvModule
*iter_module
= lttv_library_module_get(library
, i
);
2944 lttv_module_info(iter_module
, &module_info
[i
]);
2946 gchar
*path
= module_info
[i
].name
;
2947 if(module_info
[i
].use_count
> 0) g_ptr_array_add(name
, path
);
2949 module_name
= get_selection(mw_data
, (char **)(name
->pdata
), name
->len
,
2950 "Select a module", "Modules");
2951 if(module_name
!= NULL
) {
2953 if(strcmp(module_name
, module_info
[i
].name
) == 0) {
2954 module
= lttv_library_module_get(library
, i
);
2960 g_ptr_array_free(name
, TRUE
);
2961 g_free(module_info
);
2963 if(module_name
== NULL
) return;
2966 LttvModuleInfo module_info
;
2967 lttv_module_info(module
, &module_info
);
2968 g_info("Release module: %s\n", module_info
.name
);
2970 lttv_module_release(module
);
2974 /* Display a directory dialogue to let user select a path for library searching
2978 on_add_library_search_path_activate (GtkMenuItem
*menuitem
,
2981 MainWindow
* mw_data
= get_window_data_struct((GtkWidget
*)menuitem
);
2982 //GtkDirSelection * file_selector = (GtkDirSelection *)gtk_dir_selection_new("Select library path");
2983 GtkFileSelection
* file_selector
= (GtkFileSelection
*)gtk_file_selection_new("Select a trace");
2984 gtk_widget_hide( (file_selector
)->file_list
->parent
) ;
2986 gtk_window_set_transient_for(GTK_WINDOW(file_selector
),
2987 GTK_WINDOW(mw_data
->mwindow
));
2992 if(remember_plugins_dir
[0] != '\0')
2993 gtk_file_selection_set_filename(file_selector
, remember_plugins_dir
);
2995 id
= gtk_dialog_run(GTK_DIALOG(file_selector
));
2997 case GTK_RESPONSE_ACCEPT
:
2998 case GTK_RESPONSE_OK
:
2999 dir
= gtk_file_selection_get_filename (file_selector
);
3000 strncpy(remember_plugins_dir
,dir
,PATH_MAX
);
3001 strncat(remember_plugins_dir
,"/",PATH_MAX
);
3002 lttv_library_path_add(dir
);
3003 case GTK_RESPONSE_REJECT
:
3004 case GTK_RESPONSE_CANCEL
:
3006 gtk_widget_destroy((GtkWidget
*)file_selector
);
3012 /* Display a directory dialogue to let user select a path for library searching
3016 on_remove_library_search_path_activate (GtkMenuItem
*menuitem
,
3019 MainWindow
* mw_data
= get_window_data_struct((GtkWidget
*)menuitem
);
3021 const char *lib_path
;
3026 name
= g_ptr_array_new();
3027 nb
= lttv_library_path_number();
3028 /* ask for the library name */
3031 gchar
*path
= lttv_library_path_get(i
);
3032 g_ptr_array_add(name
, path
);
3034 lib_path
= get_selection(mw_data
, (char **)(name
->pdata
), name
->len
,
3035 "Select a library path", "Library paths");
3037 g_ptr_array_free(name
, TRUE
);
3039 if(lib_path
== NULL
) return;
3042 lttv_library_path_remove(lib_path
);
3046 on_color_activate (GtkMenuItem
*menuitem
,
3054 on_save_configuration_activate (GtkMenuItem
*menuitem
,
3057 g_info("Save configuration\n");
3062 on_content_activate (GtkMenuItem
*menuitem
,
3065 g_info("Content\n");
3070 on_about_close_activate (GtkButton
*button
,
3073 GtkWidget
*about_widget
= GTK_WIDGET(user_data
);
3075 gtk_widget_destroy(about_widget
);
3079 on_about_activate (GtkMenuItem
*menuitem
,
3082 MainWindow
*main_window
= get_window_data_struct(GTK_WIDGET(menuitem
));
3083 GtkWidget
*window_widget
= main_window
->mwindow
;
3084 GtkWidget
*about_widget
= gtk_window_new(GTK_WINDOW_TOPLEVEL
);
3085 GtkWindow
*about_window
= GTK_WINDOW(about_widget
);
3086 gint window_width
, window_height
;
3088 gtk_window_set_title(about_window
, "About Linux Trace Toolkit");
3090 gtk_window_set_resizable(about_window
, FALSE
);
3091 gtk_window_set_transient_for(about_window
, GTK_WINDOW(window_widget
));
3092 gtk_window_set_destroy_with_parent(about_window
, TRUE
);
3093 gtk_window_set_modal(about_window
, FALSE
);
3095 /* Put the about window at the center of the screen */
3096 gtk_window_get_size(about_window
, &window_width
, &window_height
);
3097 gtk_window_move (about_window
,
3098 (gdk_screen_width() - window_width
)/2,
3099 (gdk_screen_height() - window_height
)/2);
3101 GtkWidget
*vbox
= gtk_vbox_new(FALSE
, 1);
3103 gtk_container_add(GTK_CONTAINER(about_widget
), vbox
);
3107 GtkWidget
*label1
= gtk_label_new("");
3108 gtk_misc_set_padding(GTK_MISC(label1
), 10, 20);
3109 gtk_label_set_markup(GTK_LABEL(label1
), "\
3110 <big>Linux Trace Toolkit " VERSION
"</big>");
3111 gtk_label_set_justify(GTK_LABEL(label1
), GTK_JUSTIFY_CENTER
);
3113 GtkWidget
*label2
= gtk_label_new("");
3114 gtk_misc_set_padding(GTK_MISC(label2
), 10, 20);
3115 gtk_label_set_markup(GTK_LABEL(label2
), "\
3118 Michel Dagenais (New trace format, lttv main)\n\
3119 Mathieu Desnoyers (Kernel Tracer, Directory structure, build with automake/conf,\n\
3120 lttv gui, control flow view, gui cooperative trace reading\n\
3121 scheduler with interruptible foreground and background\n\
3122 computation, detailed event list (rewrite), trace reading\n\
3123 library (rewrite))\n\
3124 Benoit Des Ligneris, Eric Clement (Cluster adaptation, work in progress)\n\
3125 Xang-Xiu Yang (new trace reading library and converter, lttv gui, \n\
3126 detailed event list and statistics view)\n\
3127 Tom Zanussi (RelayFS)\n\
3129 Inspired from the original Linux Trace Toolkit Visualizer made by\n\
3132 GtkWidget
*label3
= gtk_label_new("");
3133 gtk_label_set_markup(GTK_LABEL(label3
), "\
3134 Linux Trace Toolkit Viewer, Copyright (C) 2004, 2005, 2006\n\
3136 Mathieu Desnoyers\n\
3138 Linux Trace Toolkit comes with ABSOLUTELY NO WARRANTY.\n\
3139 This is free software, and you are welcome to redistribute it\n\
3140 under certain conditions. See COPYING for details.");
3141 gtk_misc_set_padding(GTK_MISC(label3
), 10, 20);
3143 gtk_box_pack_start_defaults(GTK_BOX(vbox
), label1
);
3144 gtk_box_pack_start_defaults(GTK_BOX(vbox
), label2
);
3145 gtk_box_pack_start_defaults(GTK_BOX(vbox
), label3
);
3147 GtkWidget
*hbox
= gtk_hbox_new(TRUE
, 0);
3148 gtk_box_pack_end(GTK_BOX(vbox
), hbox
, FALSE
, FALSE
, 0);
3149 GtkWidget
*close_button
= gtk_button_new_with_mnemonic("_Close");
3150 gtk_box_pack_end(GTK_BOX(hbox
), close_button
, FALSE
, FALSE
, 0);
3151 gtk_container_set_border_width(GTK_CONTAINER(close_button
), 20);
3153 g_signal_connect(G_OBJECT(close_button
), "clicked",
3154 G_CALLBACK(on_about_close_activate
),
3155 (gpointer
)about_widget
);
3157 gtk_widget_show_all(about_widget
);
3162 on_button_new_clicked (GtkButton
*button
,
3165 create_new_window((GtkWidget
*)button
, user_data
, TRUE
);
3169 on_button_new_tab_clicked (GtkButton
*button
,
3172 create_new_tab((GtkWidget
*)button
, user_data
);
3176 on_button_open_clicked (GtkButton
*button
,
3179 open_traceset((GtkWidget
*)button
, user_data
);
3184 on_button_add_trace_clicked (GtkButton
*button
,
3187 add_trace((GtkWidget
*)button
, user_data
);
3192 on_button_remove_trace_clicked (GtkButton
*button
,
3195 remove_trace((GtkWidget
*)button
, user_data
);
3199 on_button_redraw_clicked (GtkButton
*button
,
3202 redraw((GtkWidget
*)button
, user_data
);
3206 on_button_continue_processing_clicked (GtkButton
*button
,
3209 continue_processing((GtkWidget
*)button
, user_data
);
3213 on_button_stop_processing_clicked (GtkButton
*button
,
3216 stop_processing((GtkWidget
*)button
, user_data
);
3222 on_button_save_clicked (GtkButton
*button
,
3225 save((GtkWidget
*)button
, user_data
);
3230 on_button_save_as_clicked (GtkButton
*button
,
3233 save_as((GtkWidget
*)button
, user_data
);
3238 on_button_zoom_in_clicked (GtkButton
*button
,
3241 zoom_in((GtkWidget
*)button
, user_data
);
3246 on_button_zoom_out_clicked (GtkButton
*button
,
3249 zoom_out((GtkWidget
*)button
, user_data
);
3254 on_button_zoom_extended_clicked (GtkButton
*button
,
3257 zoom_extended((GtkWidget
*)button
, user_data
);
3262 on_button_go_to_time_clicked (GtkButton
*button
,
3265 go_to_time((GtkWidget
*)button
, user_data
);
3270 on_button_show_time_frame_clicked (GtkButton
*button
,
3273 show_time_frame((GtkWidget
*)button
, user_data
);
3278 on_button_move_up_clicked (GtkButton
*button
,
3281 move_up_viewer((GtkWidget
*)button
, user_data
);
3286 on_button_move_down_clicked (GtkButton
*button
,
3289 move_down_viewer((GtkWidget
*)button
, user_data
);
3294 on_button_delete_viewer_clicked (GtkButton
*button
,
3297 delete_viewer((GtkWidget
*)button
, user_data
);
3301 on_MWindow_destroy (GtkWidget
*widget
,
3304 MainWindow
*main_window
= get_window_data_struct(widget
);
3305 LttvIAttribute
*attributes
= main_window
->attributes
;
3306 LttvAttributeValue value
;
3308 //This is unnecessary, since widgets will be destroyed
3309 //by the main window widget anyway.
3310 //remove_all_menu_toolbar_constructors(main_window, NULL);
3312 g_assert(lttv_iattribute_find_by_path(attributes
,
3313 "viewers/menu", LTTV_POINTER
, &value
));
3314 lttv_menus_destroy((LttvMenus
*)*(value
.v_pointer
));
3316 g_assert(lttv_iattribute_find_by_path(attributes
,
3317 "viewers/toolbar", LTTV_POINTER
, &value
));
3318 lttv_toolbars_destroy((LttvToolbars
*)*(value
.v_pointer
));
3320 g_object_unref(main_window
->attributes
);
3321 g_main_window_list
= g_slist_remove(g_main_window_list
, main_window
);
3323 g_info("There are now : %d windows\n",g_slist_length(g_main_window_list
));
3324 if(g_slist_length(g_main_window_list
) == 0)
3329 on_MWindow_configure (GtkWidget
*widget
,
3330 GdkEventConfigure
*event
,
3333 MainWindow
* mw_data
= get_window_data_struct((GtkWidget
*)widget
);
3335 // MD : removed time width modification upon resizing of the main window.
3336 // The viewers will redraw themselves completely, without time interval
3339 if(mw_data->window_width){
3340 time_span = LTTV_TRACESET_CONTEXT(tab->traceset_info->traceset_context)->Time_Span ;
3341 time_win = tab->time_window;
3342 ratio = width / mw_data->window_width;
3343 tab->time_window.time_width = ltt_time_mul(time_win.time_width,ratio);
3344 time = ltt_time_sub(time_span->endTime, time_win.start_time);
3345 if(ltt_time_compare(time, tab->time_window.time_width) < 0){
3346 tab->time_window.time_width = time;
3352 mw_data->window_width = (int)width;
3361 on_MNotebook_switch_page (GtkNotebook
*notebook
,
3362 GtkNotebookPage
*page
,
3370 void time_change_manager (Tab
*tab
,
3371 TimeWindow new_time_window
)
3373 /* Only one source of time change */
3374 if(tab
->time_manager_lock
== TRUE
) return;
3376 tab
->time_manager_lock
= TRUE
;
3378 LttvTracesetContext
*tsc
= LTTV_TRACESET_CONTEXT(tab
->traceset_info
->traceset_context
);
3379 TimeInterval time_span
= tsc
->time_span
;
3380 LttTime start_time
= new_time_window
.start_time
;
3381 LttTime end_time
= new_time_window
.end_time
;
3382 LttTime time_width
= new_time_window
.time_width
;
3384 g_assert(ltt_time_compare(start_time
, end_time
) < 0);
3387 GtkAdjustment
*adjustment
= gtk_range_get_adjustment(GTK_RANGE(tab
->scrollbar
));
3388 LttTime upper
= ltt_time_sub(time_span
.end_time
, time_span
.start_time
);
3390 gtk_range_set_increments(GTK_RANGE(tab
->scrollbar
),
3391 ltt_time_to_double(new_time_window
.time_width
)
3392 / SCROLL_STEP_PER_PAGE
3393 * NANOSECONDS_PER_SECOND
, /* step increment */
3394 ltt_time_to_double(new_time_window
.time_width
)
3395 * NANOSECONDS_PER_SECOND
); /* page increment */
3396 gtk_range_set_range(GTK_RANGE(tab
->scrollbar
),
3398 ltt_time_to_double(upper
)
3399 * NANOSECONDS_PER_SECOND
); /* upper */
3401 g_object_set(G_OBJECT(adjustment
),
3405 ltt_time_to_double(upper
), /* upper */
3407 new_time_window
.time_width_double
3408 / SCROLL_STEP_PER_PAGE
, /* step increment */
3410 new_time_window
.time_width_double
,
3411 /* page increment */
3413 new_time_window
.time_width_double
, /* page size */
3415 gtk_adjustment_changed(adjustment
);
3417 // g_object_set(G_OBJECT(adjustment),
3419 // ltt_time_to_double(
3420 // ltt_time_sub(start_time, time_span.start_time))
3423 //gtk_adjustment_value_changed(adjustment);
3424 gtk_range_set_value(GTK_RANGE(tab
->scrollbar
),
3426 ltt_time_sub(start_time
, time_span
.start_time
)) /* value */);
3428 /* set the time bar. */
3430 gtk_spin_button_set_range(GTK_SPIN_BUTTON(tab
->MEntry1
),
3431 (double)time_span
.start_time
.tv_sec
,
3432 (double)time_span
.end_time
.tv_sec
);
3433 gtk_spin_button_set_value(GTK_SPIN_BUTTON(tab
->MEntry1
),
3434 (double)start_time
.tv_sec
);
3436 /* start nanoseconds */
3437 if(start_time
.tv_sec
== time_span
.start_time
.tv_sec
) {
3438 /* can be both beginning and end at the same time. */
3439 if(start_time
.tv_sec
== time_span
.end_time
.tv_sec
) {
3440 /* If we are at the end, max nsec to end.. -1 (not zero length) */
3441 gtk_spin_button_set_range(GTK_SPIN_BUTTON(tab
->MEntry2
),
3442 (double)time_span
.start_time
.tv_nsec
,
3443 (double)time_span
.end_time
.tv_nsec
-1);
3445 gtk_spin_button_set_range(GTK_SPIN_BUTTON(tab
->MEntry2
),
3446 (double)time_span
.start_time
.tv_nsec
,
3447 (double)NANOSECONDS_PER_SECOND
-1);
3449 } else if(start_time
.tv_sec
== time_span
.end_time
.tv_sec
) {
3450 /* If we are at the end, max nsec to end.. -1 (not zero length) */
3451 gtk_spin_button_set_range(GTK_SPIN_BUTTON(tab
->MEntry2
),
3453 (double)time_span
.end_time
.tv_nsec
-1);
3454 } else /* anywhere else */
3455 gtk_spin_button_set_range(GTK_SPIN_BUTTON(tab
->MEntry2
),
3457 (double)NANOSECONDS_PER_SECOND
-1);
3458 gtk_spin_button_set_value(GTK_SPIN_BUTTON(tab
->MEntry2
),
3459 (double)start_time
.tv_nsec
);
3462 gtk_spin_button_set_range(GTK_SPIN_BUTTON(tab
->MEntry3
),
3463 (double)time_span
.start_time
.tv_sec
,
3464 (double)time_span
.end_time
.tv_sec
);
3465 gtk_spin_button_set_value(GTK_SPIN_BUTTON(tab
->MEntry3
),
3466 (double)end_time
.tv_sec
);
3468 /* end nanoseconds */
3469 if(end_time
.tv_sec
== time_span
.start_time
.tv_sec
) {
3470 /* can be both beginning and end at the same time. */
3471 if(end_time
.tv_sec
== time_span
.end_time
.tv_sec
) {
3472 /* If we are at the end, max nsec to end.. */
3473 gtk_spin_button_set_range(GTK_SPIN_BUTTON(tab
->MEntry4
),
3474 (double)time_span
.start_time
.tv_nsec
+1,
3475 (double)time_span
.end_time
.tv_nsec
);
3477 gtk_spin_button_set_range(GTK_SPIN_BUTTON(tab
->MEntry4
),
3478 (double)time_span
.start_time
.tv_nsec
+1,
3479 (double)NANOSECONDS_PER_SECOND
-1);
3482 else if(end_time
.tv_sec
== time_span
.end_time
.tv_sec
) {
3483 /* If we are at the end, max nsec to end.. */
3484 gtk_spin_button_set_range(GTK_SPIN_BUTTON(tab
->MEntry4
),
3486 (double)time_span
.end_time
.tv_nsec
);
3488 else /* anywhere else */
3489 gtk_spin_button_set_range(GTK_SPIN_BUTTON(tab
->MEntry4
),
3491 (double)NANOSECONDS_PER_SECOND
-1);
3492 gtk_spin_button_set_value(GTK_SPIN_BUTTON(tab
->MEntry4
),
3493 (double)end_time
.tv_nsec
);
3496 if(time_width
.tv_nsec
== 0) {
3497 gtk_spin_button_set_range(GTK_SPIN_BUTTON(tab
->MEntry7
),
3499 (double)upper
.tv_sec
);
3501 gtk_spin_button_set_range(GTK_SPIN_BUTTON(tab
->MEntry7
),
3503 (double)upper
.tv_sec
);
3505 gtk_spin_button_set_value(GTK_SPIN_BUTTON(tab
->MEntry7
),
3506 (double)time_width
.tv_sec
);
3508 /* width nanoseconds */
3509 if(time_width
.tv_sec
== upper
.tv_sec
) {
3510 if(time_width
.tv_sec
== 0) {
3511 gtk_spin_button_set_range(GTK_SPIN_BUTTON(tab
->MEntry8
),
3513 (double)upper
.tv_nsec
);
3515 gtk_spin_button_set_range(GTK_SPIN_BUTTON(tab
->MEntry8
),
3517 (double)upper
.tv_nsec
);
3520 else if(time_width
.tv_sec
== 0) {
3521 gtk_spin_button_set_range(GTK_SPIN_BUTTON(tab
->MEntry8
),
3523 (double)upper
.tv_nsec
);
3525 else /* anywhere else */
3526 gtk_spin_button_set_range(GTK_SPIN_BUTTON(tab
->MEntry8
),
3528 (double)NANOSECONDS_PER_SECOND
-1);
3529 gtk_spin_button_set_value(GTK_SPIN_BUTTON(tab
->MEntry8
),
3530 (double)time_width
.tv_nsec
);
3532 /* call viewer hooks for new time window */
3533 set_time_window(tab
, &new_time_window
);
3535 tab
->time_manager_lock
= FALSE
;
3539 /* value changed for frame start s
3541 * Check time span : if ns is out of range, clip it the nearest good value.
3544 on_MEntry1_value_changed (GtkSpinButton
*spinbutton
,
3547 Tab
*tab
=(Tab
*)user_data
;
3548 LttvTracesetContext
* tsc
=
3549 LTTV_TRACESET_CONTEXT(tab
->traceset_info
->traceset_context
);
3550 TimeInterval time_span
= tsc
->time_span
;
3551 gint value
= gtk_spin_button_get_value_as_int(spinbutton
);
3553 TimeWindow new_time_window
= tab
->time_window
;
3555 LttTime end_time
= new_time_window
.end_time
;
3557 new_time_window
.start_time
.tv_sec
= value
;
3559 /* start nanoseconds */
3560 if(new_time_window
.start_time
.tv_sec
== time_span
.start_time
.tv_sec
) {
3561 if(new_time_window
.start_time
.tv_sec
== time_span
.end_time
.tv_sec
) {
3562 if(new_time_window
.start_time
.tv_nsec
> time_span
.end_time
.tv_nsec
)
3563 new_time_window
.start_time
.tv_nsec
= time_span
.end_time
.tv_nsec
-1;
3564 if(new_time_window
.start_time
.tv_nsec
< time_span
.start_time
.tv_nsec
)
3565 new_time_window
.start_time
.tv_nsec
= time_span
.start_time
.tv_nsec
;
3567 if(new_time_window
.start_time
.tv_nsec
< time_span
.start_time
.tv_nsec
)
3568 new_time_window
.start_time
.tv_nsec
= time_span
.start_time
.tv_nsec
;
3571 else if(new_time_window
.start_time
.tv_sec
== time_span
.end_time
.tv_sec
) {
3572 if(new_time_window
.start_time
.tv_nsec
> time_span
.end_time
.tv_nsec
)
3573 new_time_window
.start_time
.tv_nsec
= time_span
.end_time
.tv_nsec
-1;
3576 if(ltt_time_compare(new_time_window
.start_time
, end_time
) >= 0) {
3577 /* Then, we must push back end time : keep the same time width
3578 * if possible, else end traceset time */
3579 end_time
= LTT_TIME_MIN(ltt_time_add(new_time_window
.start_time
,
3580 new_time_window
.time_width
),
3581 time_span
.end_time
);
3584 /* Fix the time width to fit start time and end time */
3585 new_time_window
.time_width
= ltt_time_sub(end_time
,
3586 new_time_window
.start_time
);
3587 new_time_window
.time_width_double
=
3588 ltt_time_to_double(new_time_window
.time_width
);
3590 new_time_window
.end_time
= end_time
;
3592 time_change_manager(tab
, new_time_window
);
3597 on_MEntry2_value_changed (GtkSpinButton
*spinbutton
,
3600 Tab
*tab
=(Tab
*)user_data
;
3601 LttvTracesetContext
* tsc
=
3602 LTTV_TRACESET_CONTEXT(tab
->traceset_info
->traceset_context
);
3603 TimeInterval time_span
= tsc
->time_span
;
3604 gint value
= gtk_spin_button_get_value_as_int(spinbutton
);
3606 TimeWindow new_time_window
= tab
->time_window
;
3608 LttTime end_time
= new_time_window
.end_time
;
3610 new_time_window
.start_time
.tv_nsec
= value
;
3612 if(ltt_time_compare(new_time_window
.start_time
, end_time
) >= 0) {
3613 /* Then, we must push back end time : keep the same time width
3614 * if possible, else end traceset time */
3615 end_time
= LTT_TIME_MIN(ltt_time_add(new_time_window
.start_time
,
3616 new_time_window
.time_width
),
3617 time_span
.end_time
);
3620 /* Fix the time width to fit start time and end time */
3621 new_time_window
.time_width
= ltt_time_sub(end_time
,
3622 new_time_window
.start_time
);
3623 new_time_window
.time_width_double
=
3624 ltt_time_to_double(new_time_window
.time_width
);
3626 new_time_window
.end_time
= end_time
;
3628 time_change_manager(tab
, new_time_window
);
3633 on_MEntry3_value_changed (GtkSpinButton
*spinbutton
,
3636 Tab
*tab
=(Tab
*)user_data
;
3637 LttvTracesetContext
* tsc
=
3638 LTTV_TRACESET_CONTEXT(tab
->traceset_info
->traceset_context
);
3639 TimeInterval time_span
= tsc
->time_span
;
3640 gint value
= gtk_spin_button_get_value_as_int(spinbutton
);
3642 TimeWindow new_time_window
= tab
->time_window
;
3644 LttTime end_time
= new_time_window
.end_time
;
3646 end_time
.tv_sec
= value
;
3648 /* end nanoseconds */
3649 if(end_time
.tv_sec
== time_span
.start_time
.tv_sec
) {
3650 if(end_time
.tv_sec
== time_span
.end_time
.tv_sec
) {
3651 if(end_time
.tv_nsec
> time_span
.end_time
.tv_nsec
)
3652 end_time
.tv_nsec
= time_span
.end_time
.tv_nsec
;
3653 if(end_time
.tv_nsec
< time_span
.start_time
.tv_nsec
)
3654 end_time
.tv_nsec
= time_span
.start_time
.tv_nsec
+1;
3656 if(end_time
.tv_nsec
< time_span
.start_time
.tv_nsec
)
3657 end_time
.tv_nsec
= time_span
.start_time
.tv_nsec
+1;
3660 else if(end_time
.tv_sec
== time_span
.end_time
.tv_sec
) {
3661 if(end_time
.tv_nsec
> time_span
.end_time
.tv_nsec
)
3662 end_time
.tv_nsec
= time_span
.end_time
.tv_nsec
;
3665 if(ltt_time_compare(new_time_window
.start_time
, end_time
) >= 0) {
3666 /* Then, we must push front start time : keep the same time width
3667 * if possible, else end traceset time */
3668 new_time_window
.start_time
= LTT_TIME_MAX(
3669 ltt_time_sub(end_time
,
3670 new_time_window
.time_width
),
3671 time_span
.start_time
);
3674 /* Fix the time width to fit start time and end time */
3675 new_time_window
.time_width
= ltt_time_sub(end_time
,
3676 new_time_window
.start_time
);
3677 new_time_window
.time_width_double
=
3678 ltt_time_to_double(new_time_window
.time_width
);
3680 new_time_window
.end_time
= end_time
;
3682 time_change_manager(tab
, new_time_window
);
3687 on_MEntry4_value_changed (GtkSpinButton
*spinbutton
,
3690 Tab
*tab
=(Tab
*)user_data
;
3691 LttvTracesetContext
* tsc
=
3692 LTTV_TRACESET_CONTEXT(tab
->traceset_info
->traceset_context
);
3693 TimeInterval time_span
= tsc
->time_span
;
3694 gint value
= gtk_spin_button_get_value_as_int(spinbutton
);
3696 TimeWindow new_time_window
= tab
->time_window
;
3698 LttTime end_time
= new_time_window
.end_time
;
3700 end_time
.tv_nsec
= value
;
3702 if(ltt_time_compare(new_time_window
.start_time
, end_time
) >= 0) {
3703 /* Then, we must push front start time : keep the same time width
3704 * if possible, else end traceset time */
3705 new_time_window
.start_time
= LTT_TIME_MAX(
3706 ltt_time_sub(end_time
,
3707 new_time_window
.time_width
),
3708 time_span
.start_time
);
3711 /* Fix the time width to fit start time and end time */
3712 new_time_window
.time_width
= ltt_time_sub(end_time
,
3713 new_time_window
.start_time
);
3714 new_time_window
.time_width_double
=
3715 ltt_time_to_double(new_time_window
.time_width
);
3716 new_time_window
.end_time
= end_time
;
3718 time_change_manager(tab
, new_time_window
);
3722 /* value changed for time frame interval s
3724 * Check time span : if ns is out of range, clip it the nearest good value.
3727 on_MEntry7_value_changed (GtkSpinButton
*spinbutton
,
3730 Tab
*tab
=(Tab
*)user_data
;
3731 LttvTracesetContext
* tsc
=
3732 LTTV_TRACESET_CONTEXT(tab
->traceset_info
->traceset_context
);
3733 TimeInterval time_span
= tsc
->time_span
;
3734 gint value
= gtk_spin_button_get_value_as_int(spinbutton
);
3735 LttTime current_time
, time_delta
;
3736 TimeWindow new_time_window
= tab
->time_window
;
3737 current_time
= tab
->current_time
;
3739 time_delta
= ltt_time_sub(time_span
.end_time
,time_span
.start_time
);
3740 new_time_window
.time_width
.tv_sec
= value
;
3741 new_time_window
.time_width_double
=
3742 ltt_time_to_double(new_time_window
.time_width
);
3743 if(ltt_time_compare(new_time_window
.time_width
,time_delta
) > 0)
3744 { /* Case where zoom out is bigger than trace length */
3745 new_time_window
.start_time
= time_span
.start_time
;
3746 new_time_window
.time_width
= time_delta
;
3747 new_time_window
.time_width_double
= ltt_time_to_double(time_delta
);
3748 new_time_window
.end_time
= ltt_time_add(new_time_window
.start_time
,
3749 new_time_window
.time_width
) ;
3753 /* Center the image on the current time */
3754 new_time_window
.start_time
=
3755 ltt_time_sub(current_time
,
3756 ltt_time_from_double(new_time_window
.time_width_double
/2.0));
3757 new_time_window
.end_time
= ltt_time_add(new_time_window
.start_time
,
3758 new_time_window
.time_width
) ;
3759 /* If on borders, don't fall off */
3760 if(ltt_time_compare(new_time_window
.start_time
, time_span
.start_time
) <0
3761 || ltt_time_compare(new_time_window
.start_time
, time_span
.end_time
) >0)
3763 new_time_window
.start_time
= time_span
.start_time
;
3764 new_time_window
.end_time
= ltt_time_add(new_time_window
.start_time
,
3765 new_time_window
.time_width
) ;
3769 if(ltt_time_compare(new_time_window
.end_time
,
3770 time_span
.end_time
) > 0
3771 || ltt_time_compare(new_time_window
.end_time
,
3772 time_span
.start_time
) < 0)
3774 new_time_window
.start_time
=
3775 ltt_time_sub(time_span
.end_time
, new_time_window
.time_width
);
3777 new_time_window
.end_time
= ltt_time_add(new_time_window
.start_time
,
3778 new_time_window
.time_width
) ;
3784 if(ltt_time_compare(new_time_window
.time_width
, ltt_time_zero
) == 0) {
3785 g_warning("Zoom more than 1 ns impossible");
3787 time_change_manager(tab
, new_time_window
);
3792 on_MEntry8_value_changed (GtkSpinButton
*spinbutton
,
3795 Tab
*tab
=(Tab
*)user_data
;
3796 LttvTracesetContext
* tsc
=
3797 LTTV_TRACESET_CONTEXT(tab
->traceset_info
->traceset_context
);
3798 TimeInterval time_span
= tsc
->time_span
;
3799 gint value
= gtk_spin_button_get_value_as_int(spinbutton
);
3800 LttTime current_time
, time_delta
;
3801 TimeWindow new_time_window
= tab
->time_window
;
3802 current_time
= tab
->current_time
;
3804 time_delta
= ltt_time_sub(time_span
.end_time
,time_span
.start_time
);
3805 new_time_window
.time_width
.tv_nsec
= value
;
3806 new_time_window
.time_width_double
=
3807 ltt_time_to_double(new_time_window
.time_width
);
3808 if(ltt_time_compare(new_time_window
.time_width
,time_delta
) > 0)
3809 { /* Case where zoom out is bigger than trace length */
3810 new_time_window
.start_time
= time_span
.start_time
;
3811 new_time_window
.time_width
= time_delta
;
3812 new_time_window
.time_width_double
= ltt_time_to_double(time_delta
);
3813 new_time_window
.end_time
= ltt_time_add(new_time_window
.start_time
,
3814 new_time_window
.time_width
) ;
3818 /* Center the image on the current time */
3819 new_time_window
.start_time
=
3820 ltt_time_sub(current_time
,
3821 ltt_time_from_double(new_time_window
.time_width_double
/2.0));
3822 new_time_window
.end_time
= ltt_time_add(new_time_window
.start_time
,
3823 new_time_window
.time_width
) ;
3824 /* If on borders, don't fall off */
3825 if(ltt_time_compare(new_time_window
.start_time
, time_span
.start_time
) <0
3826 || ltt_time_compare(new_time_window
.start_time
, time_span
.end_time
) >0)
3828 new_time_window
.start_time
= time_span
.start_time
;
3829 new_time_window
.end_time
= ltt_time_add(new_time_window
.start_time
,
3830 new_time_window
.time_width
) ;
3834 if(ltt_time_compare(new_time_window
.end_time
,
3835 time_span
.end_time
) > 0
3836 || ltt_time_compare(new_time_window
.end_time
,
3837 time_span
.start_time
) < 0)
3839 new_time_window
.start_time
=
3840 ltt_time_sub(time_span
.end_time
, new_time_window
.time_width
);
3842 new_time_window
.end_time
= ltt_time_add(new_time_window
.start_time
,
3843 new_time_window
.time_width
) ;
3849 if(ltt_time_compare(new_time_window
.time_width
, ltt_time_zero
) == 0) {
3850 g_warning("Zoom more than 1 ns impossible");
3852 time_change_manager(tab
, new_time_window
);
3858 void current_time_change_manager (Tab
*tab
,
3859 LttTime new_current_time
)
3861 /* Only one source of time change */
3862 if(tab
->current_time_manager_lock
== TRUE
) return;
3864 tab
->current_time_manager_lock
= TRUE
;
3866 LttvTracesetContext
*tsc
= LTTV_TRACESET_CONTEXT(tab
->traceset_info
->traceset_context
);
3867 TimeInterval time_span
= tsc
->time_span
;
3869 /* current seconds */
3870 gtk_spin_button_set_range(GTK_SPIN_BUTTON(tab
->MEntry5
),
3871 (double)time_span
.start_time
.tv_sec
,
3872 (double)time_span
.end_time
.tv_sec
);
3873 gtk_spin_button_set_value(GTK_SPIN_BUTTON(tab
->MEntry5
),
3874 (double)new_current_time
.tv_sec
);
3877 /* start nanoseconds */
3878 if(new_current_time
.tv_sec
== time_span
.start_time
.tv_sec
) {
3879 /* can be both beginning and end at the same time. */
3880 if(new_current_time
.tv_sec
== time_span
.end_time
.tv_sec
) {
3881 /* If we are at the end, max nsec to end.. */
3882 gtk_spin_button_set_range(GTK_SPIN_BUTTON(tab
->MEntry6
),
3883 (double)time_span
.start_time
.tv_nsec
,
3884 (double)time_span
.end_time
.tv_nsec
);
3886 gtk_spin_button_set_range(GTK_SPIN_BUTTON(tab
->MEntry6
),
3887 (double)time_span
.start_time
.tv_nsec
,
3888 (double)NANOSECONDS_PER_SECOND
-1);
3890 } else if(new_current_time
.tv_sec
== time_span
.end_time
.tv_sec
) {
3891 /* If we are at the end, max nsec to end.. */
3892 gtk_spin_button_set_range(GTK_SPIN_BUTTON(tab
->MEntry6
),
3894 (double)time_span
.end_time
.tv_nsec
);
3895 } else /* anywhere else */
3896 gtk_spin_button_set_range(GTK_SPIN_BUTTON(tab
->MEntry6
),
3898 (double)NANOSECONDS_PER_SECOND
-1);
3900 gtk_spin_button_set_value(GTK_SPIN_BUTTON(tab
->MEntry6
),
3901 (double)new_current_time
.tv_nsec
);
3903 set_current_time(tab
, &new_current_time
);
3905 tab
->current_time_manager_lock
= FALSE
;
3908 void current_position_change_manager(Tab
*tab
,
3909 LttvTracesetContextPosition
*pos
)
3911 LttvTracesetContext
*tsc
=
3912 LTTV_TRACESET_CONTEXT(tab
->traceset_info
->traceset_context
);
3913 TimeInterval time_span
= tsc
->time_span
;
3915 g_assert(lttv_process_traceset_seek_position(tsc
, pos
) == 0);
3916 LttTime new_time
= lttv_traceset_context_position_get_time(pos
);
3917 /* Put the context in a state coherent position */
3918 lttv_state_traceset_seek_time_closest((LttvTracesetState
*)tsc
, ltt_time_zero
);
3920 current_time_change_manager(tab
, new_time
);
3922 set_current_position(tab
, pos
);
3927 on_MEntry5_value_changed (GtkSpinButton
*spinbutton
,
3930 Tab
*tab
= (Tab
*)user_data
;
3931 LttvTracesetContext
* tsc
=
3932 LTTV_TRACESET_CONTEXT(tab
->traceset_info
->traceset_context
);
3933 TimeInterval time_span
= tsc
->time_span
;
3934 gint value
= gtk_spin_button_get_value_as_int(spinbutton
);
3935 LttTime new_current_time
= tab
->current_time
;
3936 new_current_time
.tv_sec
= value
;
3938 /* current nanoseconds */
3939 if(new_current_time
.tv_sec
== time_span
.start_time
.tv_sec
) {
3940 if(new_current_time
.tv_sec
== time_span
.end_time
.tv_sec
) {
3941 if(new_current_time
.tv_nsec
> time_span
.end_time
.tv_nsec
)
3942 new_current_time
.tv_nsec
= time_span
.end_time
.tv_nsec
;
3943 if(new_current_time
.tv_nsec
< time_span
.start_time
.tv_nsec
)
3944 new_current_time
.tv_nsec
= time_span
.start_time
.tv_nsec
;
3946 if(new_current_time
.tv_nsec
< time_span
.start_time
.tv_nsec
)
3947 new_current_time
.tv_nsec
= time_span
.start_time
.tv_nsec
;
3950 else if(new_current_time
.tv_sec
== time_span
.end_time
.tv_sec
) {
3951 if(new_current_time
.tv_nsec
> time_span
.end_time
.tv_nsec
)
3952 new_current_time
.tv_nsec
= time_span
.end_time
.tv_nsec
;
3955 current_time_change_manager(tab
, new_current_time
);
3959 on_MEntry6_value_changed (GtkSpinButton
*spinbutton
,
3962 Tab
*tab
= (Tab
*)user_data
;
3963 gint value
= gtk_spin_button_get_value_as_int(spinbutton
);
3964 LttTime new_current_time
= tab
->current_time
;
3965 new_current_time
.tv_nsec
= value
;
3967 current_time_change_manager(tab
, new_current_time
);
3971 void scroll_value_changed_cb(GtkWidget
*scrollbar
,
3974 Tab
*tab
= (Tab
*)user_data
;
3975 TimeWindow new_time_window
;
3977 GtkAdjustment
*adjust
= gtk_range_get_adjustment(GTK_RANGE(scrollbar
));
3978 gdouble value
= gtk_adjustment_get_value(adjust
);
3979 // gdouble upper, lower, ratio, page_size;
3981 LttvTracesetContext
* tsc
=
3982 LTTV_TRACESET_CONTEXT(tab
->traceset_info
->traceset_context
);
3983 TimeInterval time_span
= tsc
->time_span
;
3985 time
= ltt_time_add(ltt_time_from_double(value
),
3986 time_span
.start_time
);
3988 new_time_window
.start_time
= time
;
3990 page_size
= adjust
->page_size
;
3992 new_time_window
.time_width
=
3993 ltt_time_from_double(page_size
);
3995 new_time_window
.time_width_double
=
3998 new_time_window
.end_time
= ltt_time_add(new_time_window
.start_time
,
3999 new_time_window
.time_width
);
4002 time_change_manager(tab
, new_time_window
);
4004 //time_window = tab->time_window;
4006 lower
= adjust
->lower
;
4007 upper
= adjust
->upper
;
4008 ratio
= (value
- lower
) / (upper
- lower
);
4009 g_info("lower %lu, upper %lu, value %lu, ratio %lu", lower
, upper
, value
, ratio
);
4011 //time = ltt_time_sub(time_span->end_time, time_span->start_time);
4012 //time = ltt_time_mul(time, (float)ratio);
4013 //time = ltt_time_add(time_span->start_time, time);
4014 time
= ltt_time_add(ltt_time_from_double(value
),
4015 time_span
.start_time
);
4017 time_window
.start_time
= time
;
4019 page_size
= adjust
->page_size
;
4021 time_window
.time_width
=
4022 ltt_time_from_double(page_size
);
4023 //time = ltt_time_sub(time_span.end_time, time);
4024 //if(ltt_time_compare(time,time_window.time_width) < 0){
4025 // time_window.time_width = time;
4028 /* call viewer hooks for new time window */
4029 set_time_window(tab
, &time_window
);
4034 /* Display a dialogue showing all eventtypes and traces, let user to select the interested
4035 * eventtypes, tracefiles and traces (filter)
4038 /* Select a trace which will be removed from traceset
4041 char * get_remove_trace(MainWindow
*mw_data
,
4042 char ** all_trace_name
, int nb_trace
)
4044 return get_selection(mw_data
, all_trace_name
, nb_trace
,
4045 "Select a trace", "Trace pathname");
4049 /* Select a module which will be loaded
4052 char * get_load_module(MainWindow
*mw_data
,
4053 char ** load_module_name
, int nb_module
)
4055 return get_selection(mw_data
, load_module_name
, nb_module
,
4056 "Select a module to load", "Module name");
4062 /* Select a module which will be unloaded
4065 char * get_unload_module(MainWindow
*mw_data
,
4066 char ** loaded_module_name
, int nb_module
)
4068 return get_selection(mw_data
, loaded_module_name
, nb_module
,
4069 "Select a module to unload", "Module name");
4073 /* Display a dialogue which shows all selectable items, let user to
4074 * select one of them
4077 char * get_selection(MainWindow
*mw_data
,
4078 char ** loaded_module_name
, int nb_module
,
4079 char *title
, char * column_title
)
4081 GtkWidget
* dialogue
;
4082 GtkWidget
* scroll_win
;
4084 GtkListStore
* store
;
4085 GtkTreeViewColumn
* column
;
4086 GtkCellRenderer
* renderer
;
4087 GtkTreeSelection
* select
;
4090 char * unload_module_name
= NULL
;
4092 dialogue
= gtk_dialog_new_with_buttons(title
,
4095 GTK_STOCK_OK
,GTK_RESPONSE_ACCEPT
,
4096 GTK_STOCK_CANCEL
,GTK_RESPONSE_REJECT
,
4098 gtk_window_set_default_size((GtkWindow
*)dialogue
, 500, 200);
4099 gtk_window_set_transient_for(GTK_WINDOW(dialogue
),
4100 GTK_WINDOW(mw_data
->mwindow
));
4102 scroll_win
= gtk_scrolled_window_new (NULL
, NULL
);
4103 gtk_widget_show ( scroll_win
);
4104 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll_win
),
4105 GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
4107 store
= gtk_list_store_new (N_COLUMNS
,G_TYPE_STRING
);
4108 tree
= gtk_tree_view_new_with_model(GTK_TREE_MODEL (store
));
4109 gtk_widget_show ( tree
);
4110 g_object_unref (G_OBJECT (store
));
4112 renderer
= gtk_cell_renderer_text_new ();
4113 column
= gtk_tree_view_column_new_with_attributes (column_title
,
4115 "text", MODULE_COLUMN
,
4117 gtk_tree_view_column_set_alignment (column
, 0.5);
4118 gtk_tree_view_column_set_fixed_width (column
, 150);
4119 gtk_tree_view_append_column (GTK_TREE_VIEW (tree
), column
);
4121 select
= gtk_tree_view_get_selection (GTK_TREE_VIEW (tree
));
4122 gtk_tree_selection_set_mode (select
, GTK_SELECTION_SINGLE
);
4124 gtk_container_add (GTK_CONTAINER (scroll_win
), tree
);
4126 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialogue
)->vbox
), scroll_win
,TRUE
, TRUE
,0);
4128 for(i
=0;i
<nb_module
;i
++){
4129 gtk_list_store_append (store
, &iter
);
4130 gtk_list_store_set (store
, &iter
, MODULE_COLUMN
,loaded_module_name
[i
],-1);
4133 id
= gtk_dialog_run(GTK_DIALOG(dialogue
));
4134 GtkTreeModel
**store_model
= (GtkTreeModel
**)&store
;
4136 case GTK_RESPONSE_ACCEPT
:
4137 case GTK_RESPONSE_OK
:
4138 if (gtk_tree_selection_get_selected (select
, store_model
, &iter
)){
4139 gtk_tree_model_get ((GtkTreeModel
*)store
, &iter
, MODULE_COLUMN
, &unload_module_name
, -1);
4141 case GTK_RESPONSE_REJECT
:
4142 case GTK_RESPONSE_CANCEL
:
4144 gtk_widget_destroy(dialogue
);
4148 return unload_module_name
;
4152 /* Insert all menu entry and tool buttons into this main window
4157 void add_all_menu_toolbar_constructors(MainWindow
* mw
, gpointer user_data
)
4161 lttvwindow_viewer_constructor constructor
;
4162 LttvMenus
* global_menu
, * instance_menu
;
4163 LttvToolbars
* global_toolbar
, * instance_toolbar
;
4164 LttvMenuClosure
*menu_item
;
4165 LttvToolbarClosure
*toolbar_item
;
4166 LttvAttributeValue value
;
4167 LttvIAttribute
*global_attributes
= LTTV_IATTRIBUTE(lttv_global_attributes());
4168 LttvIAttribute
*attributes
= mw
->attributes
;
4169 GtkWidget
* tool_menu_title_menu
, *new_widget
, *pixmap
;
4171 g_assert(lttv_iattribute_find_by_path(global_attributes
,
4172 "viewers/menu", LTTV_POINTER
, &value
));
4173 if(*(value
.v_pointer
) == NULL
)
4174 *(value
.v_pointer
) = lttv_menus_new();
4175 global_menu
= (LttvMenus
*)*(value
.v_pointer
);
4177 g_assert(lttv_iattribute_find_by_path(attributes
,
4178 "viewers/menu", LTTV_POINTER
, &value
));
4179 if(*(value
.v_pointer
) == NULL
)
4180 *(value
.v_pointer
) = lttv_menus_new();
4181 instance_menu
= (LttvMenus
*)*(value
.v_pointer
);
4185 g_assert(lttv_iattribute_find_by_path(global_attributes
,
4186 "viewers/toolbar", LTTV_POINTER
, &value
));
4187 if(*(value
.v_pointer
) == NULL
)
4188 *(value
.v_pointer
) = lttv_toolbars_new();
4189 global_toolbar
= (LttvToolbars
*)*(value
.v_pointer
);
4191 g_assert(lttv_iattribute_find_by_path(attributes
,
4192 "viewers/toolbar", LTTV_POINTER
, &value
));
4193 if(*(value
.v_pointer
) == NULL
)
4194 *(value
.v_pointer
) = lttv_toolbars_new();
4195 instance_toolbar
= (LttvToolbars
*)*(value
.v_pointer
);
4197 /* Add missing menu entries to window instance */
4198 for(i
=0;i
<global_menu
->len
;i
++) {
4199 menu_item
= &g_array_index(global_menu
, LttvMenuClosure
, i
);
4201 //add menu_item to window instance;
4202 constructor
= menu_item
->con
;
4203 tool_menu_title_menu
= lookup_widget(mw
->mwindow
,"ToolMenuTitle_menu");
4205 gtk_menu_item_new_with_mnemonic (menu_item
->menu_text
);
4206 gtk_container_add (GTK_CONTAINER (tool_menu_title_menu
),
4208 g_signal_connect ((gpointer
) new_widget
, "activate",
4209 G_CALLBACK (insert_viewer_wrap
),
4211 gtk_widget_show (new_widget
);
4212 lttv_menus_add(instance_menu
, menu_item
->con
,
4213 menu_item
->menu_path
,
4214 menu_item
->menu_text
,
4219 /* Add missing toolbar entries to window instance */
4220 for(i
=0;i
<global_toolbar
->len
;i
++) {
4221 toolbar_item
= &g_array_index(global_toolbar
, LttvToolbarClosure
, i
);
4223 //add toolbar_item to window instance;
4224 constructor
= toolbar_item
->con
;
4225 tool_menu_title_menu
= lookup_widget(mw
->mwindow
,"MToolbar1");
4226 pixbuf
= gdk_pixbuf_new_from_xpm_data((const char**)toolbar_item
->pixmap
);
4227 pixmap
= gtk_image_new_from_pixbuf(pixbuf
);
4229 gtk_toolbar_append_element (GTK_TOOLBAR (tool_menu_title_menu
),
4230 GTK_TOOLBAR_CHILD_BUTTON
,
4233 toolbar_item
->tooltip
, NULL
,
4234 pixmap
, NULL
, NULL
);
4235 gtk_label_set_use_underline(
4236 GTK_LABEL (((GtkToolbarChild
*) (
4237 g_list_last (GTK_TOOLBAR
4238 (tool_menu_title_menu
)->children
)->data
))->label
),
4240 gtk_container_set_border_width (GTK_CONTAINER (new_widget
), 1);
4241 g_signal_connect ((gpointer
) new_widget
,
4243 G_CALLBACK (insert_viewer_wrap
),
4245 gtk_widget_show (new_widget
);
4247 lttv_toolbars_add(instance_toolbar
, toolbar_item
->con
,
4248 toolbar_item
->tooltip
,
4249 toolbar_item
->pixmap
,
4257 /* Create a main window
4260 MainWindow
*construct_main_window(MainWindow
* parent
)
4262 g_debug("construct_main_window()");
4263 GtkWidget
* new_window
; /* New generated main window */
4264 MainWindow
* new_m_window
;/* New main window structure */
4265 GtkNotebook
* notebook
;
4266 LttvIAttribute
*attributes
=
4267 LTTV_IATTRIBUTE(g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
));
4268 LttvAttributeValue value
;
4271 new_m_window
= g_new(MainWindow
, 1);
4273 // Add the object's information to the module's array
4274 g_main_window_list
= g_slist_append(g_main_window_list
, new_m_window
);
4276 new_window
= create_MWindow();
4277 gtk_widget_show (new_window
);
4279 new_m_window
->mwindow
= new_window
;
4280 new_m_window
->attributes
= attributes
;
4282 g_assert(lttv_iattribute_find_by_path(attributes
,
4283 "viewers/menu", LTTV_POINTER
, &value
));
4284 *(value
.v_pointer
) = lttv_menus_new();
4286 g_assert(lttv_iattribute_find_by_path(attributes
,
4287 "viewers/toolbar", LTTV_POINTER
, &value
));
4288 *(value
.v_pointer
) = lttv_toolbars_new();
4290 add_all_menu_toolbar_constructors(new_m_window
, NULL
);
4292 g_object_set_data_full(G_OBJECT(new_window
),
4294 (gpointer
)new_m_window
,
4295 (GDestroyNotify
)g_free
);
4296 //create a default tab
4297 notebook
= (GtkNotebook
*)lookup_widget(new_m_window
->mwindow
, "MNotebook");
4298 if(notebook
== NULL
){
4299 g_info("Notebook does not exist\n");
4300 /* FIXME : destroy partially created widgets */
4301 g_free(new_m_window
);
4304 //gtk_notebook_popup_enable (GTK_NOTEBOOK(notebook));
4305 //for now there is no name field in LttvTraceset structure
4306 //Use "Traceset" as the label for the default tab
4308 GtkWidget
* parent_notebook
= lookup_widget(parent
->mwindow
, "MNotebook");
4309 GtkWidget
*page
= gtk_notebook_get_nth_page(GTK_NOTEBOOK(parent_notebook
),
4310 gtk_notebook_get_current_page(GTK_NOTEBOOK(parent_notebook
)));
4316 LttvPluginTab
*ptab
;
4317 ptab
= (LttvPluginTab
*)g_object_get_data(G_OBJECT(page
), "Tab_Plugin");
4318 parent_tab
= ptab
->tab
;
4320 LttvPluginTab
*ptab
= g_object_new(LTTV_TYPE_PLUGIN_TAB
, NULL
);
4322 new_m_window
, parent_tab
, notebook
, "Traceset");
4323 ptab
->parent
.top_widget
= ptab
->tab
->top_widget
;
4324 g_object_set_data_full(
4325 G_OBJECT(ptab
->tab
->vbox
),
4328 (GDestroyNotify
)tab_destructor
);
4329 new_tab
= ptab
->tab
;
4331 LttvPluginTab
*ptab
= g_object_new(LTTV_TYPE_PLUGIN_TAB
, NULL
);
4332 init_tab(ptab
->tab
, new_m_window
, NULL
, notebook
, "Traceset");
4333 ptab
->parent
.top_widget
= ptab
->tab
->top_widget
;
4334 g_object_set_data_full(
4335 G_OBJECT(ptab
->tab
->vbox
),
4338 (GDestroyNotify
)tab_destructor
);
4339 new_tab
= ptab
->tab
;
4342 /* Insert default viewers */
4344 LttvAttributeType type
;
4345 LttvAttributeName name
;
4346 LttvAttributeValue value
;
4347 LttvAttribute
*attribute
;
4349 LttvIAttribute
*attributes_global
=
4350 LTTV_IATTRIBUTE(lttv_global_attributes());
4352 attribute
= LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(
4353 LTTV_IATTRIBUTE(attributes_global
),
4354 LTTV_VIEWER_CONSTRUCTORS
));
4355 g_assert(attribute
);
4357 name
= g_quark_from_string("guievents");
4358 type
= lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(attribute
),
4360 if(type
== LTTV_POINTER
) {
4361 lttvwindow_viewer_constructor viewer_constructor
=
4362 (lttvwindow_viewer_constructor
)*value
.v_pointer
;
4363 insert_viewer(new_window
, viewer_constructor
);
4366 name
= g_quark_from_string("guicontrolflow");
4367 type
= lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(attribute
),
4369 if(type
== LTTV_POINTER
) {
4370 lttvwindow_viewer_constructor viewer_constructor
=
4371 (lttvwindow_viewer_constructor
)*value
.v_pointer
;
4372 insert_viewer(new_window
, viewer_constructor
);
4375 name
= g_quark_from_string("guistatistics");
4376 type
= lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(attribute
),
4378 if(type
== LTTV_POINTER
) {
4379 lttvwindow_viewer_constructor viewer_constructor
=
4380 (lttvwindow_viewer_constructor
)*value
.v_pointer
;
4381 insert_viewer(new_window
, viewer_constructor
);
4385 g_info("There are now : %d windows\n",g_slist_length(g_main_window_list
));
4387 return new_m_window
;
4391 /* Free the memory occupied by a tab structure
4395 void tab_destructor(LttvPluginTab
* ptab
)
4397 int i
, nb
, ref_count
;
4399 Tab
*tab
= ptab
->tab
;
4401 gtk_object_destroy(GTK_OBJECT(tab
->tooltips
));
4404 g_object_unref(tab
->attributes
);
4406 if(tab
->interrupted_state
)
4407 g_object_unref(tab
->interrupted_state
);
4410 if(tab
->traceset_info
->traceset_context
!= NULL
){
4411 //remove state update hooks
4412 lttv_state_remove_event_hooks(
4413 (LttvTracesetState
*)tab
->traceset_info
->
4415 lttv_context_fini(LTTV_TRACESET_CONTEXT(tab
->traceset_info
->
4417 g_object_unref(tab
->traceset_info
->traceset_context
);
4419 if(tab
->traceset_info
->traceset
!= NULL
) {
4420 nb
= lttv_traceset_number(tab
->traceset_info
->traceset
);
4421 for(i
= 0 ; i
< nb
; i
++) {
4422 trace
= lttv_traceset_get(tab
->traceset_info
->traceset
, i
);
4423 ref_count
= lttv_trace_get_ref_number(trace
);
4425 ltt_trace_close(lttv_trace(trace
));
4429 lttv_traceset_destroy(tab
->traceset_info
->traceset
);
4430 /* Remove the idle events requests processing function of the tab */
4431 g_idle_remove_by_data(tab
);
4433 g_slist_free(tab
->events_requests
);
4434 g_free(tab
->traceset_info
);
4436 g_object_unref(ptab
);
4440 /* Create a tab and insert it into the current main window
4443 void init_tab(Tab
*tab
, MainWindow
* mw
, Tab
*copy_tab
,
4444 GtkNotebook
* notebook
, char * label
)
4448 //LttvFilter *filter = NULL;
4450 //create a new tab data structure
4451 //tab = g_new(Tab,1);
4453 //construct and initialize the traceset_info
4454 tab
->traceset_info
= g_new(TracesetInfo
,1);
4457 tab
->traceset_info
->traceset
=
4458 lttv_traceset_copy(copy_tab
->traceset_info
->traceset
);
4460 /* Copy the previous tab's filter */
4461 /* We can clone the filter, as we copy the trace set also */
4462 /* The filter must always be in sync with the trace set */
4463 tab
->filter
= lttv_filter_clone(copy_tab
->filter
);
4465 tab
->traceset_info
->traceset
= lttv_traceset_new();
4469 lttv_attribute_write_xml(
4470 lttv_traceset_attribute(tab
->traceset_info
->traceset
),
4476 tab
->time_manager_lock
= FALSE
;
4477 tab
->current_time_manager_lock
= FALSE
;
4479 //FIXME copy not implemented in lower level
4480 tab
->traceset_info
->traceset_context
=
4481 g_object_new(LTTV_TRACESET_STATS_TYPE
, NULL
);
4482 g_assert(tab
->traceset_info
->traceset_context
!= NULL
);
4484 LTTV_TRACESET_CONTEXT(tab
->traceset_info
->traceset_context
),
4485 tab
->traceset_info
->traceset
);
4486 //add state update hooks
4487 lttv_state_add_event_hooks(
4488 (LttvTracesetState
*)tab
->traceset_info
->traceset_context
);
4490 //determine the current_time and time_window of the tab
4492 if(copy_tab
!= NULL
){
4493 tab
->time_window
= copy_tab
->time_window
;
4494 tab
->current_time
= copy_tab
->current_time
;
4496 tab
->time_window
.start_time
=
4497 LTTV_TRACESET_CONTEXT(tab
->traceset_info
->traceset_context
)->
4498 time_span
.start_time
;
4499 if(DEFAULT_TIME_WIDTH_S
<
4500 LTTV_TRACESET_CONTEXT(tab
->traceset_info
->traceset_context
)->
4501 time_span
.end_time
.tv_sec
)
4502 tmp_time
.tv_sec
= DEFAULT_TIME_WIDTH_S
;
4505 LTTV_TRACESET_CONTEXT(tab
->traceset_info
->traceset_context
)->
4506 time_span
.end_time
.tv_sec
;
4507 tmp_time
.tv_nsec
= 0;
4508 tab
->time_window
.time_width
= tmp_time
;
4509 tab
->current_time
.tv_sec
=
4510 LTTV_TRACESET_CONTEXT(tab
->traceset_info
->traceset_context
)->
4511 time_span
.start_time
.tv_sec
;
4512 tab
->current_time
.tv_nsec
=
4513 LTTV_TRACESET_CONTEXT(tab
->traceset_info
->traceset_context
)->
4514 time_span
.start_time
.tv_nsec
;
4517 tab
->attributes
= LTTV_IATTRIBUTE(g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
));
4518 tab
->interrupted_state
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
4520 tab
->vbox
= gtk_vbox_new(FALSE
, 2);
4521 tab
->top_widget
= tab
->vbox
;
4522 //g_object_set_data_full(G_OBJECT(tab->top_widget), "filter",
4523 // filter, (GDestroyNotify)lttv_filter_destroy);
4525 // g_signal_connect (G_OBJECT(tab->top_widget),
4527 // G_CALLBACK (on_top_notify),
4530 tab
->viewer_container
= gtk_vbox_new(TRUE
, 2);
4531 tab
->scrollbar
= gtk_hscrollbar_new(NULL
);
4532 //tab->multivpaned = gtk_multi_vpaned_new();
4534 gtk_box_pack_start(GTK_BOX(tab
->vbox
),
4535 tab
->viewer_container
,
4537 TRUE
, /* Give the extra space to the child */
4538 0); /* No padding */
4541 // tab->time_window = copy_tab->time_window;
4542 // tab->current_time = copy_tab->current_time;
4545 /* Create the timebar */
4547 tab
->MTimebar
= gtk_hbox_new(FALSE
, 2);
4548 gtk_widget_show(tab
->MTimebar
);
4549 tab
->tooltips
= gtk_tooltips_new();
4551 tab
->MEventBox1a
= gtk_event_box_new();
4552 gtk_widget_show(tab
->MEventBox1a
);
4553 gtk_tooltips_set_tip(tab
->tooltips
, tab
->MEventBox1a
,
4554 "Paste Start and End Times Here", "");
4555 tab
->MText1a
= gtk_label_new("Time Frame ");
4556 gtk_widget_show(tab
->MText1a
);
4557 gtk_container_add(GTK_CONTAINER(tab
->MEventBox1a
), tab
->MText1a
);
4558 tab
->MEventBox1b
= gtk_event_box_new();
4559 gtk_widget_show(tab
->MEventBox1b
);
4560 gtk_tooltips_set_tip(tab
->tooltips
, tab
->MEventBox1b
,
4561 "Paste Start Time Here", "");
4562 tab
->MText1b
= gtk_label_new("start: ");
4563 gtk_widget_show(tab
->MText1b
);
4564 gtk_container_add(GTK_CONTAINER(tab
->MEventBox1b
), tab
->MText1b
);
4565 tab
->MText2
= gtk_label_new("s");
4566 gtk_widget_show(tab
->MText2
);
4567 tab
->MText3a
= gtk_label_new("ns");
4568 gtk_widget_show(tab
->MText3a
);
4570 tab
->MEventBox3b
= gtk_event_box_new();
4571 gtk_widget_show(tab
->MEventBox3b
);
4572 gtk_tooltips_set_tip(tab
->tooltips
, tab
->MEventBox3b
,
4573 "Paste End Time Here", "");
4574 tab
->MText3b
= gtk_label_new("end:");
4575 gtk_widget_show(tab
->MText3b
);
4576 gtk_container_add(GTK_CONTAINER(tab
->MEventBox3b
), tab
->MText3b
);
4577 tab
->MText4
= gtk_label_new("s");
4578 gtk_widget_show(tab
->MText4
);
4579 tab
->MText5a
= gtk_label_new("ns");
4580 gtk_widget_show(tab
->MText5a
);
4582 tab
->MEventBox8
= gtk_event_box_new();
4583 gtk_widget_show(tab
->MEventBox8
);
4584 gtk_tooltips_set_tip(tab
->tooltips
, tab
->MEventBox8
,
4585 "Paste Time Interval here", "");
4586 tab
->MText8
= gtk_label_new("Time Interval:");
4587 gtk_widget_show(tab
->MText8
);
4588 gtk_container_add(GTK_CONTAINER(tab
->MEventBox8
), tab
->MText8
);
4589 tab
->MText9
= gtk_label_new("s");
4590 gtk_widget_show(tab
->MText9
);
4591 tab
->MText10
= gtk_label_new("ns");
4592 gtk_widget_show(tab
->MText10
);
4594 tab
->MEventBox5b
= gtk_event_box_new();
4595 gtk_widget_show(tab
->MEventBox5b
);
4596 gtk_tooltips_set_tip(tab
->tooltips
, tab
->MEventBox5b
,
4597 "Paste Current Time Here", "");
4598 tab
->MText5b
= gtk_label_new("Current Time:");
4599 gtk_widget_show(tab
->MText5b
);
4600 gtk_container_add(GTK_CONTAINER(tab
->MEventBox5b
), tab
->MText5b
);
4601 tab
->MText6
= gtk_label_new("s");
4602 gtk_widget_show(tab
->MText6
);
4603 tab
->MText7
= gtk_label_new("ns");
4604 gtk_widget_show(tab
->MText7
);
4606 tab
->MEntry1
= gtk_spin_button_new_with_range(0.0, 1.0, 1.0);
4607 gtk_spin_button_set_digits(GTK_SPIN_BUTTON(tab
->MEntry1
),0);
4608 gtk_spin_button_set_snap_to_ticks(GTK_SPIN_BUTTON(tab
->MEntry1
),TRUE
);
4609 gtk_widget_show(tab
->MEntry1
);
4610 tab
->MEntry2
= gtk_spin_button_new_with_range(0.0, 1.0, 1.0);
4611 gtk_spin_button_set_digits(GTK_SPIN_BUTTON(tab
->MEntry2
),0);
4612 gtk_spin_button_set_snap_to_ticks(GTK_SPIN_BUTTON(tab
->MEntry2
),TRUE
);
4613 gtk_widget_show(tab
->MEntry2
);
4614 tab
->MEntry3
= gtk_spin_button_new_with_range(0.0, 1.0, 1.0);
4615 gtk_spin_button_set_digits(GTK_SPIN_BUTTON(tab
->MEntry3
),0);
4616 gtk_spin_button_set_snap_to_ticks(GTK_SPIN_BUTTON(tab
->MEntry3
),TRUE
);
4617 gtk_widget_show(tab
->MEntry3
);
4618 tab
->MEntry4
= gtk_spin_button_new_with_range(0.0, 1.0, 1.0);
4619 gtk_spin_button_set_digits(GTK_SPIN_BUTTON(tab
->MEntry4
),0);
4620 gtk_spin_button_set_snap_to_ticks(GTK_SPIN_BUTTON(tab
->MEntry4
),TRUE
);
4621 gtk_widget_show(tab
->MEntry4
);
4622 tab
->MEntry5
= gtk_spin_button_new_with_range(0.0, 1.0, 1.0);
4623 gtk_spin_button_set_digits(GTK_SPIN_BUTTON(tab
->MEntry5
),0);
4624 gtk_spin_button_set_snap_to_ticks(GTK_SPIN_BUTTON(tab
->MEntry5
),TRUE
);
4625 gtk_widget_show(tab
->MEntry5
);
4626 tab
->MEntry6
= gtk_spin_button_new_with_range(0.0, 1.0, 1.0);
4627 gtk_spin_button_set_digits(GTK_SPIN_BUTTON(tab
->MEntry6
),0);
4628 gtk_spin_button_set_snap_to_ticks(GTK_SPIN_BUTTON(tab
->MEntry6
),TRUE
);
4629 gtk_widget_show(tab
->MEntry6
);
4630 tab
->MEntry7
= gtk_spin_button_new_with_range(0.0, 1.0, 1.0);
4631 gtk_spin_button_set_digits(GTK_SPIN_BUTTON(tab
->MEntry7
),0);
4632 gtk_spin_button_set_snap_to_ticks(GTK_SPIN_BUTTON(tab
->MEntry7
),TRUE
);
4633 gtk_widget_show(tab
->MEntry7
);
4634 tab
->MEntry8
= gtk_spin_button_new_with_range(0.0, 1.0, 1.0);
4635 gtk_spin_button_set_digits(GTK_SPIN_BUTTON(tab
->MEntry8
),0);
4636 gtk_spin_button_set_snap_to_ticks(GTK_SPIN_BUTTON(tab
->MEntry8
),TRUE
);
4637 gtk_widget_show(tab
->MEntry8
);
4639 GtkWidget
*temp_widget
;
4641 gtk_box_pack_start (GTK_BOX (tab
->MTimebar
), tab
->MEventBox1a
, FALSE
,
4643 gtk_box_pack_start (GTK_BOX (tab
->MTimebar
), tab
->MEventBox1b
, FALSE
,
4645 gtk_box_pack_start (GTK_BOX (tab
->MTimebar
), tab
->MEntry1
, FALSE
, FALSE
, 0);
4646 gtk_box_pack_start (GTK_BOX (tab
->MTimebar
), tab
->MText2
, FALSE
, FALSE
, 0);
4647 gtk_box_pack_start (GTK_BOX (tab
->MTimebar
), tab
->MEntry2
, FALSE
, FALSE
, 0);
4648 gtk_box_pack_start (GTK_BOX (tab
->MTimebar
), tab
->MText3a
, FALSE
, FALSE
, 0);
4649 temp_widget
= gtk_vseparator_new();
4650 gtk_widget_show(temp_widget
);
4651 gtk_box_pack_start (GTK_BOX (tab
->MTimebar
), temp_widget
, FALSE
, FALSE
, 0);
4652 gtk_box_pack_start (GTK_BOX (tab
->MTimebar
), tab
->MEventBox3b
, FALSE
,
4654 gtk_box_pack_start (GTK_BOX (tab
->MTimebar
), tab
->MEntry3
, FALSE
, FALSE
, 0);
4655 gtk_box_pack_start (GTK_BOX (tab
->MTimebar
), tab
->MText4
, FALSE
, FALSE
, 0);
4656 gtk_box_pack_start (GTK_BOX (tab
->MTimebar
), tab
->MEntry4
, FALSE
, FALSE
, 0);
4657 gtk_box_pack_start (GTK_BOX (tab
->MTimebar
), tab
->MText5a
, FALSE
, FALSE
, 0);
4658 temp_widget
= gtk_vseparator_new();
4659 gtk_widget_show(temp_widget
);
4660 gtk_box_pack_start (GTK_BOX (tab
->MTimebar
), temp_widget
, FALSE
, FALSE
, 0);
4661 gtk_box_pack_start (GTK_BOX (tab
->MTimebar
), tab
->MEventBox8
, FALSE
,
4663 gtk_box_pack_start (GTK_BOX (tab
->MTimebar
), tab
->MEntry7
, FALSE
, FALSE
, 0);
4664 gtk_box_pack_start (GTK_BOX (tab
->MTimebar
), tab
->MText9
, FALSE
, FALSE
, 0);
4665 gtk_box_pack_start (GTK_BOX (tab
->MTimebar
), tab
->MEntry8
, FALSE
, FALSE
, 0);
4666 gtk_box_pack_start (GTK_BOX (tab
->MTimebar
), tab
->MText10
, FALSE
, FALSE
, 0);
4668 temp_widget
= gtk_vseparator_new();
4669 gtk_widget_show(temp_widget
);
4670 gtk_box_pack_end (GTK_BOX (tab
->MTimebar
), tab
->MText7
, FALSE
, FALSE
, 0);
4671 gtk_box_pack_end (GTK_BOX (tab
->MTimebar
), tab
->MEntry6
, FALSE
, FALSE
, 0);
4672 gtk_box_pack_end (GTK_BOX (tab
->MTimebar
), tab
->MText6
, FALSE
, FALSE
, 0);
4673 gtk_box_pack_end (GTK_BOX (tab
->MTimebar
), tab
->MEntry5
, FALSE
, FALSE
, 0);
4674 gtk_box_pack_end (GTK_BOX (tab
->MTimebar
), tab
->MEventBox5b
, FALSE
,
4676 gtk_box_pack_end (GTK_BOX (tab
->MTimebar
), temp_widget
, FALSE
, FALSE
, 0);
4679 //GtkWidget *test = gtk_button_new_with_label("drop");
4680 //gtk_button_set_relief(GTK_BUTTON(test), GTK_RELIEF_NONE);
4681 //gtk_widget_show(test);
4682 //gtk_box_pack_end(GTK_BOX (tab->MTimebar), test, FALSE, FALSE, 0);
4683 //gtk_widget_add_events(tab->MText1, GDK_ALL_EVENTS_MASK);//GDK_BUTTON_PRESS_MASK);
4684 /*GtkWidget *event_box = gtk_event_box_new();
4685 gtk_widget_show(event_box);
4686 gtk_tooltips_set_tip(tooltips, event_box,
4687 "Paste Current Time Here", "");
4688 gtk_box_pack_end(GTK_BOX (tab->MTimebar), event_box, FALSE, FALSE, 0);
4689 GtkWidget *test = gtk_label_new("drop");
4690 gtk_container_add(GTK_CONTAINER(event_box), test);
4691 gtk_widget_show(test);
4692 g_signal_connect (G_OBJECT(event_box),
4693 "button-press-event",
4694 G_CALLBACK (on_MText1_paste),
4698 g_signal_connect (G_OBJECT(tab
->MEventBox1a
),
4699 "button-press-event",
4700 G_CALLBACK (on_MEventBox1a_paste
),
4703 g_signal_connect (G_OBJECT(tab
->MEventBox1b
),
4704 "button-press-event",
4705 G_CALLBACK (on_MEventBox1b_paste
),
4707 g_signal_connect (G_OBJECT(tab
->MEventBox3b
),
4708 "button-press-event",
4709 G_CALLBACK (on_MEventBox3b_paste
),
4711 g_signal_connect (G_OBJECT(tab
->MEventBox5b
),
4712 "button-press-event",
4713 G_CALLBACK (on_MEventBox5b_paste
),
4715 g_signal_connect (G_OBJECT(tab
->MEventBox8
),
4716 "button-press-event",
4717 G_CALLBACK (on_MEventBox8_paste
),
4721 gtk_box_pack_end(GTK_BOX(tab
->vbox
),
4723 FALSE
, /* Do not expand */
4724 FALSE
, /* Fill has no effect here (expand false) */
4725 0); /* No padding */
4727 gtk_box_pack_end(GTK_BOX(tab
->vbox
),
4729 FALSE
, /* Do not expand */
4730 FALSE
, /* Fill has no effect here (expand false) */
4731 0); /* No padding */
4733 g_object_set_data(G_OBJECT(tab
->viewer_container
), "focused_viewer", NULL
);
4739 // Display a label with a X
4740 GtkWidget *w_hbox = gtk_hbox_new(FALSE, 4);
4741 GtkWidget *w_label = gtk_label_new (label);
4742 GtkWidget *pixmap = create_pixmap(GTK_WIDGET(notebook), "close.png");
4743 GtkWidget *w_button = gtk_button_new ();
4744 gtk_container_add(GTK_CONTAINER(w_button), pixmap);
4745 //GtkWidget *w_button = gtk_button_new_with_label("x");
4747 gtk_button_set_relief(GTK_BUTTON(w_button), GTK_RELIEF_NONE);
4749 gtk_box_pack_start(GTK_BOX(w_hbox), w_label, TRUE, TRUE, 0);
4750 gtk_box_pack_end(GTK_BOX(w_hbox), w_button, FALSE,
4753 g_signal_connect_swapped (w_button, "clicked",
4754 G_CALLBACK (on_close_tab_X_clicked),
4757 gtk_widget_set_state(w_button, GTK_STATE_ACTIVE);
4759 gtk_widget_show (w_label);
4760 gtk_widget_show (pixmap);
4761 gtk_widget_show (w_button);
4762 gtk_widget_show (w_hbox);
4764 tab->label = w_hbox;
4768 tab
->label
= gtk_label_new (label
);
4770 gtk_widget_show(tab
->label
);
4771 gtk_widget_show(tab
->scrollbar
);
4772 gtk_widget_show(tab
->viewer_container
);
4773 gtk_widget_show(tab
->vbox
);
4774 //gtk_widget_show(tab->multivpaned);
4777 /* Start with empty events requests list */
4778 tab
->events_requests
= NULL
;
4779 tab
->events_request_pending
= FALSE
;
4780 tab
->stop_foreground
= FALSE
;
4784 g_signal_connect(G_OBJECT(tab
->scrollbar
), "value-changed",
4785 G_CALLBACK(scroll_value_changed_cb
), tab
);
4787 g_signal_connect ((gpointer
) tab
->MEntry1
, "value-changed",
4788 G_CALLBACK (on_MEntry1_value_changed
),
4790 g_signal_connect ((gpointer
) tab
->MEntry2
, "value-changed",
4791 G_CALLBACK (on_MEntry2_value_changed
),
4793 g_signal_connect ((gpointer
) tab
->MEntry3
, "value-changed",
4794 G_CALLBACK (on_MEntry3_value_changed
),
4796 g_signal_connect ((gpointer
) tab
->MEntry4
, "value-changed",
4797 G_CALLBACK (on_MEntry4_value_changed
),
4799 g_signal_connect ((gpointer
) tab
->MEntry5
, "value-changed",
4800 G_CALLBACK (on_MEntry5_value_changed
),
4802 g_signal_connect ((gpointer
) tab
->MEntry6
, "value-changed",
4803 G_CALLBACK (on_MEntry6_value_changed
),
4805 g_signal_connect ((gpointer
) tab
->MEntry7
, "value-changed",
4806 G_CALLBACK (on_MEntry7_value_changed
),
4808 g_signal_connect ((gpointer
) tab
->MEntry8
, "value-changed",
4809 G_CALLBACK (on_MEntry8_value_changed
),
4812 //g_signal_connect(G_OBJECT(tab->scrollbar), "changed",
4813 // G_CALLBACK(scroll_value_changed_cb), tab);
4816 //insert tab into notebook
4817 gtk_notebook_append_page(notebook
,
4820 list
= gtk_container_get_children(GTK_CONTAINER(notebook
));
4821 gtk_notebook_set_current_page(notebook
,g_list_length(list
)-1);
4822 // always show : not if(g_list_length(list)>1)
4823 gtk_notebook_set_show_tabs(notebook
, TRUE
);
4826 lttvwindow_report_time_window(tab
, copy_tab
->time_window
);
4827 lttvwindow_report_current_time(tab
, copy_tab
->current_time
);
4829 TimeWindow time_window
;
4831 time_window
.start_time
= ltt_time_zero
;
4832 time_window
.end_time
= ltt_time_add(time_window
.start_time
,
4833 lttvwindow_default_time_width
);
4834 time_window
.time_width
= lttvwindow_default_time_width
;
4835 time_window
.time_width_double
= ltt_time_to_double(time_window
.time_width
);
4837 lttvwindow_report_time_window(tab
, time_window
);
4838 lttvwindow_report_current_time(tab
, ltt_time_zero
);
4841 LttvTraceset
*traceset
= tab
->traceset_info
->traceset
;
4842 SetTraceset(tab
, traceset
);
4846 * execute_events_requests
4848 * Idle function that executes the pending requests for a tab.
4850 * @return return value : TRUE : keep the idle function, FALSE : remove it.
4852 gboolean
execute_events_requests(Tab
*tab
)
4854 return ( lttvwindow_process_pending_requests(tab
) );
4858 __EXPORT
void create_main_window_with_trace_list(GSList
*traces
)
4860 GSList
*iter
= NULL
;
4863 MainWindow
*mw
= construct_main_window(NULL
);
4864 GtkWidget
*widget
= mw
->mwindow
;
4866 GtkWidget
* notebook
= lookup_widget(widget
, "MNotebook");
4867 GtkWidget
*page
= gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook
),
4868 gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook
)));
4869 LttvPluginTab
*ptab
;
4873 ptab
= create_new_tab(widget
, NULL
);
4876 ptab
= (LttvPluginTab
*)g_object_get_data(G_OBJECT(page
), "Tab_Plugin");
4880 for(iter
=traces
; iter
!=NULL
; iter
=g_slist_next(iter
)) {
4881 gchar
*path
= (gchar
*)iter
->data
;
4883 gchar abs_path
[PATH_MAX
];
4887 get_absolute_pathname(path
, abs_path
);
4888 trace_v
= lttvwindowtraces_get_trace_by_name(abs_path
);
4889 if(trace_v
== NULL
) {
4890 trace
= ltt_trace_open(abs_path
);
4892 g_warning("cannot open trace %s", abs_path
);
4894 GtkWidget
*dialogue
=
4895 gtk_message_dialog_new(
4896 GTK_WINDOW(gtk_widget_get_toplevel(widget
)),
4897 GTK_DIALOG_MODAL
|GTK_DIALOG_DESTROY_WITH_PARENT
,
4900 "Cannot open trace : maybe you should enter in the directory "
4902 gtk_dialog_run(GTK_DIALOG(dialogue
));
4903 gtk_widget_destroy(dialogue
);
4905 trace_v
= lttv_trace_new(trace
);
4906 lttvwindowtraces_add_trace(trace_v
);
4907 lttvwindow_add_trace(tab
, trace_v
);
4910 lttvwindow_add_trace(tab
, trace_v
);
4914 LttvTraceset
*traceset
;
4916 traceset
= tab
->traceset_info
->traceset
;
4917 SetTraceset(tab
, traceset
);