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/traceset.h>
41 #include <lttv/state.h>
43 #include <lttv/stats.h>
44 #include <lttv/sync/sync_chain_lttv.h>
45 #endif /* BABEL_CLEANUP */
46 #include <lttv/filter.h>
47 #include <lttvwindow/mainwindow.h>
48 #include <lttvwindow/mainwindow-private.h>
49 #include <lttvwindow/menu.h>
50 #include <lttvwindow/timebar.h>
51 #include <lttvwindow/toolbar.h>
52 #include <lttvwindow/lttvwindow.h>
53 #include <lttvwindow/lttvwindowtraces.h>
54 #include <lttvwindow/lttv_plugin_tab.h>
56 #include <babeltrace/babeltrace.h>
57 #include <babeltrace/ctf/events.h>
58 #include <babeltrace/ctf/iterator.h>
60 static LttTime lttvwindow_default_time_width
= { 1, 0 };
61 #define CLIP_BUF 256 // size of clipboard buffer
63 extern LttvTrace
*g_init_trace
;
66 /** Array containing instanced objects. */
67 extern GSList
* g_main_window_list
;
69 /** MD : keep old directory. */
70 static char remember_plugins_dir
[PATH_MAX
] = "";
71 static char remember_trace_dir
[PATH_MAX
] = "";
73 void tab_destructor(LttvPluginTab
* ptab
);
75 MainWindow
* get_window_data_struct(GtkWidget
* widget
);
76 char * get_load_module(MainWindow
*mw
,
77 char ** load_module_name
, int nb_module
);
78 char * get_unload_module(MainWindow
*mw
,
79 char ** loaded_module_name
, int nb_module
);
80 char * get_remove_trace(MainWindow
*mw
, char ** all_trace_name
, int nb_trace
);
81 char * get_selection(MainWindow
*mw
,
82 char ** all_name
, int nb
, char *title
, char * column_title
);
83 void init_tab(Tab
*tab
, MainWindow
* mw
, Tab
*copy_tab
,
84 GtkNotebook
* notebook
, char * label
);
86 int update_traceset(Tab
*tab
, LttvTraceset
*traceset
);
88 static void insert_viewer(GtkWidget
* widget
, lttvwindow_viewer_constructor constructor
);
90 LttvPluginTab
*create_new_tab(GtkWidget
* widget
, gpointer user_data
);
92 static gboolean
lttvwindow_process_pending_requests(Tab
*tab
);
94 static void on_timebar_starttime_changed(Timebar
*timebar
,
96 static void on_timebar_endtime_changed(Timebar
*timebar
,
98 static void on_timebar_currenttime_changed(Timebar
*timebar
,
115 static void on_top_notify(GObject
*gobject
,
119 Tab
*tab
= (Tab
*)user_data
;
120 g_message("in on_top_notify.\n");
124 static gboolean
viewer_grab_focus(GtkWidget
*widget
, GdkEventButton
*event
,
127 GtkWidget
*viewer
= GTK_WIDGET(data
);
128 GtkWidget
*viewer_container
= gtk_widget_get_parent(viewer
);
130 g_debug("FOCUS GRABBED");
131 g_object_set_data(G_OBJECT(viewer_container
), "focused_viewer", viewer
);
136 static void connect_focus_recursive(GtkWidget
*widget
,
139 if(GTK_IS_CONTAINER(widget
)) {
140 gtk_container_forall(GTK_CONTAINER(widget
),
141 (GtkCallback
)connect_focus_recursive
,
145 if(GTK_IS_TREE_VIEW(widget
)) {
146 gtk_tree_view_set_headers_clickable(GTK_TREE_VIEW(widget
), TRUE
);
148 gtk_widget_add_events(widget
, GDK_BUTTON_PRESS_MASK
);
149 g_signal_connect (G_OBJECT(widget
),
150 "button-press-event",
151 G_CALLBACK (viewer_grab_focus
),
155 /* Stop all the processings and call gtk_main_quit() */
156 static void mainwindow_quit()
158 lttvwindowtraces_unregister_requests(g_quark_from_string("stats"));
159 lttvwindowtraces_unregister_requests(g_quark_from_string("state"));
160 lttvwindowtraces_unregister_computation_hooks(g_quark_from_string("stats"));
161 lttvwindowtraces_unregister_computation_hooks(g_quark_from_string("state"));
167 /* insert_viewer function constructs an instance of a viewer first,
168 * then inserts the widget of the instance into the container of the
173 insert_viewer_wrap(GtkWidget
*menuitem
, gpointer user_data
)
175 insert_viewer((GtkWidget
*)menuitem
, (lttvwindow_viewer_constructor
)user_data
);
179 /* internal functions */
180 void insert_viewer(GtkWidget
* widget
, lttvwindow_viewer_constructor constructor
)
182 GtkWidget
* viewer_container
;
183 GtkWidget
* notebook
= lookup_widget(widget
, "MNotebook");
185 GtkWidget
*page
= gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook
),
186 gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook
)));
191 ptab
= create_new_tab(widget
, NULL
);
193 ptab
= (LttvPluginTab
*)g_object_get_data(G_OBJECT(page
), "Tab_Plugin");
197 viewer_container
= tab
->viewer_container
;
199 viewer
= (GtkWidget
*)constructor(&ptab
->parent
);
202 //gtk_multivpaned_widget_add(GTK_MULTIVPANED(multivpaned), viewer);
204 gtk_box_pack_end(GTK_BOX(viewer_container
),
210 /* We want to connect the viewer_grab_focus to EVERY
211 * child of this widget. The little trick is to get each child
212 * of each GTK_CONTAINER, even subchildren.
214 connect_focus_recursive(viewer
, viewer
);
219 * Function to set/update traceset for the viewers
220 * @param tab viewer's tab
221 * @param traceset traceset of the main window.
223 * 0 : traceset updated
224 * 1 : no traceset hooks to update; not an error.
227 int SetTraceset(Tab
* tab
, LttvTraceset
*traceset
)
230 TimeInterval time_span
;
231 TimeWindow new_time_window
;
232 LttTime new_current_time
;
235 // Perform time synchronization on the traces
236 if (syncTraceset(tsc
))
238 /* There is some time-dependant information that was calculated during
239 * context initialization. Destroy the old contexts and initialize new
241 * Modified from lttvwindow_add_trace()
243 // Keep a reference to the traces so they are not freed
244 for(i
= 0; i
< lttv_traceset_number(traceset
); i
++)
246 LttvTrace
*trace
= lttv_traceset_get(traceset
, i
);
247 lttv_trace_ref(trace
);
250 // Remove state update hooks
251 lttv_state_remove_event_hooks(
252 (LttvTracesetState
*)tab
->traceset_info
->traceset_context
);
254 lttv_context_fini(LTTV_TRACESET_CONTEXT(
255 tab
->traceset_info
->traceset_context
));
256 g_object_unref(tab
->traceset_info
->traceset_context
);
258 for(i
= 0; i
< lttv_traceset_number(traceset
); i
++)
260 LttvTrace
*trace
= lttv_traceset_get(traceset
, i
);
261 lttvwindowtraces_remove_trace(trace
);
262 lttvwindowtraces_add_trace(trace
);
265 // Create new context
266 tab
->traceset_info
->traceset_context
=
267 g_object_new(LTTV_TRACESET_STATS_TYPE
, NULL
);
268 lttv_context_init(LTTV_TRACESET_CONTEXT(tab
->traceset_info
->
269 traceset_context
), traceset
);
271 // Add state update hooks
272 lttv_state_add_event_hooks(
273 (LttvTracesetState
*)tab
->traceset_info
->traceset_context
);
275 // Remove local reference to the traces
276 for(i
=0; i
<lttv_traceset_number(traceset
); i
++)
278 LttvTrace
*trace
= lttv_traceset_get(traceset
, i
);
279 lttv_trace_unref(trace
);
282 tsc
= LTTV_TRACESET_CONTEXT(tab
->traceset_info
->traceset_context
);
284 #endif /*BABEL_CLEANUP*/
286 time_span
= lttv_traceset_get_time_span(traceset
);
288 tab
->traceset_info
->traceset
= traceset
;
290 new_time_window
= tab
->time_window
;
291 new_current_time
= tab
->current_time
;
293 /* Set the tab's time window and current time if
295 if(ltt_time_compare(tab
->time_window
.start_time
, time_span
.start_time
) < 0
296 || ltt_time_compare(tab
->time_window
.end_time
,
297 time_span
.end_time
) > 0) {
298 new_time_window
.start_time
= time_span
.start_time
;
300 new_current_time
= time_span
.start_time
;
304 if(ltt_time_compare(lttvwindow_default_time_width
,
305 ltt_time_sub(time_span
.end_time
, time_span
.start_time
)) < 0
307 ltt_time_compare(time_span
.end_time
, time_span
.start_time
) == 0)
308 tmp_time
= lttvwindow_default_time_width
;
310 tmp_time
= time_span
.end_time
;
312 new_time_window
.time_width
= tmp_time
;
313 new_time_window
.time_width_double
= ltt_time_to_double(tmp_time
);
314 new_time_window
.end_time
= ltt_time_add(new_time_window
.start_time
,
315 new_time_window
.time_width
) ;
317 lttv_state_add_event_hooks(traceset
);
319 //TODO ybrosseau 2012-08-03 Temporarly compute checkpoints right at the adding
321 //Compute the traceset state checkpoint
324 EventsRequest
*events_request
= g_new(EventsRequest
, 1);
326 LttvHooks
*hook_adder
= lttv_hooks_new();
327 lttv_hooks_add(hook_adder
, lttv_state_save_hook_add_event_hooks
, NULL
,
329 LttvHooks
*hook_remover
= lttv_hooks_new();
330 lttv_hooks_add(hook_remover
, lttv_state_save_hook_remove_event_hooks
,
331 NULL
, LTTV_PRIO_DEFAULT
);
333 // Fill the events request
334 events_request
->owner
= NULL
;
335 events_request
->viewer_data
= NULL
;
336 events_request
->servicing
= FALSE
;
337 events_request
->start_time
= ltt_time_zero
;
338 events_request
->start_position
= NULL
;
339 events_request
->stop_flag
= FALSE
;
340 events_request
->end_time
= ltt_time_infinite
;
341 events_request
->num_events
= G_MAXUINT
;
342 events_request
->end_position
= NULL
;
343 events_request
->trace
= 1; //fixed /* FIXME */
344 events_request
->before_chunk_traceset
= NULL
;
345 events_request
->before_chunk_trace
= NULL
;
346 events_request
->before_chunk_tracefile
= NULL
;
347 events_request
->event
= traceset
->event_hooks
;
348 events_request
->after_chunk_tracefile
= NULL
;
349 events_request
->after_chunk_trace
= NULL
;
350 events_request
->after_chunk_traceset
= NULL
;
351 events_request
->before_request
= hook_adder
;
352 events_request
->after_request
= hook_remover
;
354 lttvwindow_events_request(tab
, events_request
);
357 /* Finally, call the update hooks of the viewers */
358 gint retval
= update_traceset(tab
, traceset
);
360 time_change_manager(tab
, new_time_window
);
361 current_time_change_manager(tab
, new_current_time
);
368 * Function to set/update filter for the viewers
369 * @param tab viewer's tab
370 * @param filter filter of the main window.
373 * 0 : filters updated
374 * 1 : no filter hooks to update; not an error.
377 int SetFilter(Tab
* tab
, gpointer filter
)
380 LttvAttributeValue value
;
382 g_assert(lttv_iattribute_find_by_path(tab
->attributes
,
383 "hooks/updatefilter", LTTV_POINTER
, &value
));
385 tmp
= (LttvHooks
*)*(value
.v_pointer
);
387 if(tmp
== NULL
) return 1;
388 lttv_hooks_call(tmp
,filter
);
396 * Function to redraw each viewer belonging to the current tab
397 * @param tab viewer's tab
400 int update_traceset(Tab
*tab
, LttvTraceset
*traceset
)
402 LttvAttributeValue value
;
406 retval
= lttv_iattribute_find_by_path(tab
->attributes
,
407 "hooks/updatetraceset",
411 tmp
= (LttvHooks
*)*(value
.v_pointer
);
415 lttv_hooks_call(tmp
, traceset
);
421 Call hooks register to get update on traceset time span changes
423 int notify_time_span_changed(Tab
*tab
)
425 LttvAttributeValue value
;
429 retval
= lttv_iattribute_find_by_path(tab
->attributes
,
430 "hooks/updatetimespan",
434 tmp
= (LttvHooks
*)*(value
.v_pointer
);
438 lttv_hooks_call(tmp
, NULL
);
443 /* get_label function is used to get user input, it displays an input
444 * box, which allows user to input a string
447 void get_label_string (GtkWidget
* text
, gchar
* label
)
449 GtkEntry
* entry
= (GtkEntry
*)text
;
450 if(strlen(gtk_entry_get_text(entry
))!=0)
451 strcpy(label
,gtk_entry_get_text(entry
));
454 gboolean
get_label(MainWindow
* mw
, gchar
* str
, gchar
* dialogue_title
, gchar
* label_str
)
456 GtkWidget
* dialogue
;
461 dialogue
= gtk_dialog_new_with_buttons(dialogue_title
,NULL
,
463 GTK_STOCK_OK
,GTK_RESPONSE_ACCEPT
,
464 GTK_STOCK_CANCEL
,GTK_RESPONSE_REJECT
,
467 label
= gtk_label_new(label_str
);
468 gtk_widget_show(label
);
470 text
= gtk_entry_new();
471 gtk_widget_show(text
);
473 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialogue
)->vbox
), label
,TRUE
, TRUE
,0);
474 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialogue
)->vbox
), text
,FALSE
, FALSE
,0);
476 id
= gtk_dialog_run(GTK_DIALOG(dialogue
));
478 case GTK_RESPONSE_ACCEPT
:
479 get_label_string(text
,str
);
480 gtk_widget_destroy(dialogue
);
482 case GTK_RESPONSE_REJECT
:
484 gtk_widget_destroy(dialogue
);
491 /* get_window_data_struct function is actually a lookup function,
492 * given a widget which is in the tree of the main window, it will
493 * return the MainWindow data structure associated with main window
496 MainWindow
* get_window_data_struct(GtkWidget
* widget
)
499 MainWindow
* mw_data
;
501 mw
= lookup_widget(widget
, "MWindow");
503 g_info("Main window does not exist\n");
507 mw_data
= (MainWindow
*) g_object_get_data(G_OBJECT(mw
),"main_window_data");
509 g_warning("Main window data does not exist\n");
516 /* create_new_window function, just constructs a new main window
519 void create_new_window(GtkWidget
* widget
, gpointer user_data
, gboolean clone
)
521 MainWindow
* parent
= get_window_data_struct(widget
);
524 g_info("Clone : use the same traceset\n");
525 construct_main_window(parent
);
527 g_info("Empty : traceset is set to NULL\n");
528 construct_main_window(NULL
);
532 /* Get the currently focused viewer.
533 * If no viewer is focused, use the first one.
535 * If no viewer available, return NULL.
537 GtkWidget
*viewer_container_focus(GtkWidget
*container
)
541 widget
= (GtkWidget
*)g_object_get_data(G_OBJECT(container
),
545 g_debug("no widget focused");
546 GList
*children
= gtk_container_get_children(GTK_CONTAINER(container
));
549 widget
= GTK_WIDGET(children
->data
);
550 g_object_set_data(G_OBJECT(container
),
560 gint
viewer_container_position(GtkWidget
*container
, GtkWidget
*child
)
563 if(child
== NULL
) return -1;
567 memset(&value
, 0, sizeof(GValue
));
568 g_value_init(&value
, G_TYPE_INT
);
569 gtk_container_child_get_property(GTK_CONTAINER(container
),
573 pos
= g_value_get_int(&value
);
579 /* move_*_viewer functions move the selected view up/down in
583 void move_down_viewer(GtkWidget
* widget
, gpointer user_data
)
585 GtkWidget
* notebook
= lookup_widget(widget
, "MNotebook");
587 GtkWidget
*page
= gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook
),
588 gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook
)));
595 ptab
= g_object_get_data(G_OBJECT(page
), "Tab_Plugin");
599 //gtk_multivpaned_widget_move_up(GTK_MULTIVPANED(tab->multivpaned));
601 /* change the position in the vbox */
602 GtkWidget
*focus_widget
;
604 focus_widget
= viewer_container_focus(tab
->viewer_container
);
605 position
= viewer_container_position(tab
->viewer_container
, focus_widget
);
608 /* can move up one position */
609 gtk_box_reorder_child(GTK_BOX(tab
->viewer_container
),
616 void move_up_viewer(GtkWidget
* widget
, gpointer user_data
)
618 GtkWidget
* notebook
= lookup_widget(widget
, "MNotebook");
620 GtkWidget
*page
= gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook
),
621 gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook
)));
628 ptab
= (LttvPluginTab
*)g_object_get_data(G_OBJECT(page
), "Tab_Plugin");
632 //gtk_multivpaned_widget_move_down(GTK_MULTIVPANED(tab->multivpaned));
633 /* change the position in the vbox */
634 GtkWidget
*focus_widget
;
636 focus_widget
= viewer_container_focus(tab
->viewer_container
);
637 position
= viewer_container_position(tab
->viewer_container
, focus_widget
);
641 g_list_length(gtk_container_get_children(
642 GTK_CONTAINER(tab
->viewer_container
)))-1
644 /* can move down one position */
645 gtk_box_reorder_child(GTK_BOX(tab
->viewer_container
),
653 /* delete_viewer deletes the selected viewer in the current tab
656 void delete_viewer(GtkWidget
* widget
, gpointer user_data
)
658 GtkWidget
* notebook
= lookup_widget(widget
, "MNotebook");
660 GtkWidget
*page
= gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook
),
661 gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook
)));
668 ptab
= g_object_get_data(G_OBJECT(page
), "Tab_Plugin");
672 //gtk_multivpaned_widget_delete(GTK_MULTIVPANED(tab->multivpaned));
674 GtkWidget
*focus_widget
= viewer_container_focus(tab
->viewer_container
);
676 if(focus_widget
!= NULL
)
677 gtk_widget_destroy(focus_widget
);
679 g_object_set_data(G_OBJECT(tab
->viewer_container
), "focused_viewer", NULL
);
682 #if UNFINISHED_FEATURE
683 /* TODO ybrosseau 2012-03-15: Function is half implemented. Should be removed */
684 /* open_traceset will open a traceset saved in a file
685 * Right now, it is not finished yet, (not working)
689 void open_traceset(GtkWidget
* widget
, gpointer user_data
)
693 LttvTraceset
* traceset
;
694 MainWindow
* mw_data
= get_window_data_struct(widget
);
695 GtkFileSelection
* file_selector
=
696 (GtkFileSelection
*)gtk_file_selection_new("Select a traceset");
698 gtk_file_selection_hide_fileop_buttons(file_selector
);
700 gtk_window_set_transient_for(GTK_WINDOW(file_selector
),
701 GTK_WINDOW(mw_data
->mwindow
));
703 id
= gtk_dialog_run(GTK_DIALOG(file_selector
));
705 case GTK_RESPONSE_ACCEPT
:
706 case GTK_RESPONSE_OK
:
707 dir
= gtk_file_selection_get_selections (file_selector
);
708 traceset
= lttv_traceset_load(dir
[0]);
709 g_info("Open a trace set %s\n", dir
[0]);
712 case GTK_RESPONSE_REJECT
:
713 case GTK_RESPONSE_CANCEL
:
715 gtk_widget_destroy((GtkWidget
*)file_selector
);
721 /* lttvwindow_process_pending_requests
723 * Process requests for parts of the trace from viewers.
725 * These requests are made by lttvwindow_events_request().
727 * This internal function gets called by g_idle, taking care of the pending
728 * requests. It is responsible for concatenation of time intervals and position
729 * requests. It does it with the following algorithm organizing process traceset
730 * calls. Here is the detailed description of the way it works :
732 * - Events Requests Servicing Algorithm
734 * Data structures necessary :
736 * List of requests added to context : list_in
737 * List of requests not added to context : list_out
742 * list_out : many events requests
744 * FIXME : insert rest of algorithm here
748 #define list_out tab->events_requests
750 gboolean
lttvwindow_process_pending_requests(Tab
*tab
)
755 GSList
*list_in
= NULL
;
759 LttvTracesetPosition
*end_position
;
761 if(lttvwindow_preempt_count
> 0) return TRUE
;
764 g_critical("Foreground processing : tab does not exist. Processing removed.");
768 /* There is no events requests pending : we should never have been called! */
769 g_assert(g_slist_length(list_out
) != 0);
771 ts
= tab
->traceset_info
->traceset
;
773 //set the cursor to be X shape, indicating that the computer is busy in doing its job
775 new = gdk_cursor_new(GDK_X_CURSOR
);
776 widget
= lookup_widget(tab
->mw
->mwindow
, "MToolbar1");
777 win
= gtk_widget_get_parent_window(widget
);
778 gdk_window_set_cursor(win
, new);
779 gdk_cursor_unref(new);
780 gdk_window_stick(win
);
781 gdk_window_unstick(win
);
784 g_debug("SIZE events req len : %d", g_slist_length(list_out
));
786 /* Preliminary check for no trace in traceset */
787 /* Unregister the routine if empty, empty list_out too */
788 if(lttv_traceset_number(ts
) == 0) {
790 /* - For each req in list_out */
791 GSList
*iter
= list_out
;
793 while(iter
!= NULL
) {
795 gboolean remove
= FALSE
;
796 gboolean free_data
= FALSE
;
797 EventsRequest
*events_request
= (EventsRequest
*)iter
->data
;
799 /* - Call end request for req */
800 if(events_request
->servicing
== TRUE
)
801 lttv_hooks_call(events_request
->after_request
, (gpointer
)ts
);
803 /* - remove req from list_out */
804 /* Destroy the request */
807 //TODO ybrosseau: This if is always true
811 GSList
*remove_iter
= iter
;
813 iter
= g_slist_next(iter
);
814 if(free_data
) events_request_free((EventsRequest
*)remove_iter
->data
);
815 list_out
= g_slist_remove_link(list_out
, remove_iter
);
816 } else { // not remove
817 iter
= g_slist_next(iter
);
822 /* 0.1 Lock Traces */
827 iter_trace
<lttv_traceset_number(ts
);
829 LttvTrace
*trace_v
= lttv_traceset_get(ts
, iter_trace
);
831 if(lttvwindowtraces_lock(trace_v
) != 0) {
832 g_critical("Foreground processing : Unable to get trace lock");
833 return TRUE
; /* Cannot get lock, try later */
838 /* 0.2 Seek tracefiles positions to context position */
840 //g_assert(lttv_process_traceset_seek_position(tsc, sync_position) == 0);
841 lttv_process_traceset_synchronize_tracefiles(tsc
);
844 /* Events processing algorithm implementation */
845 /* Warning : the gtk_events_pending takes a LOT of cpu time. So what we do
846 * instead is to leave the control to GTK and take it back.
848 /* A. Servicing loop */
849 //while( (g_slist_length(list_in) != 0 || g_slist_length(list_out) != 0)) {
850 if((g_slist_length(list_in
) != 0 || g_slist_length(list_out
) != 0)) {
852 /* 1. If list_in is empty (need a seek) */
853 if( g_slist_length(list_in
) == 0 ) {
855 /* list in is empty, need a seek */
857 /* 1.1 Add requests to list_in */
858 GSList
*ltime
= NULL
;
862 /* 1.1.1 Find all time requests with the lowest start time in list_out
865 if(g_slist_length(list_out
) > 0)
866 ltime
= g_slist_append(ltime
, g_slist_nth_data(list_out
, 0));
867 for(iter
=g_slist_nth(list_out
,1);iter
!=NULL
;iter
=g_slist_next(iter
)) {
868 /* Find all time requests with the lowest start time in list_out */
869 EventsRequest
*event_request_ltime
= (EventsRequest
*)g_slist_nth_data(ltime
, 0);
870 EventsRequest
*event_request_list_out
= (EventsRequest
*)iter
->data
;
873 comp
= ltt_time_compare(event_request_ltime
->start_time
,
874 event_request_list_out
->start_time
);
876 ltime
= g_slist_append(ltime
, event_request_list_out
);
878 /* Remove all elements from ltime, and add current */
880 ltime
= g_slist_delete_link(ltime
, g_slist_nth(ltime
, 0));
881 ltime
= g_slist_append(ltime
, event_request_list_out
);
885 /* 1.1.2 Find all position requests with the lowest position in list_out
888 if(g_slist_length(list_out
) > 0)
889 lpos
= g_slist_append(lpos
, g_slist_nth_data(list_out
, 0));
890 for(iter
=g_slist_nth(list_out
,1);iter
!=NULL
;iter
=g_slist_next(iter
)) {
891 /* Find all position requests with the lowest position in list_out */
892 EventsRequest
*event_request_lpos
= (EventsRequest
*)g_slist_nth_data(lpos
, 0);
893 EventsRequest
*event_request_list_out
= (EventsRequest
*)iter
->data
;
896 if(event_request_lpos
->start_position
!= NULL
897 && event_request_list_out
->start_position
!= NULL
)
899 //TODO ybrosseau: this compare is in fact an equal, so the behavior might not be right.
900 comp
= lttv_traceset_position_time_compare
901 (event_request_lpos
->start_position
,
902 event_request_list_out
->start_position
);
907 lpos
= g_slist_append(lpos
, event_request_list_out
);
909 /* Remove all elements from lpos, and add current */
911 lpos
= g_slist_delete_link(lpos
, g_slist_nth(lpos
, 0));
912 lpos
= g_slist_append(lpos
, event_request_list_out
);
917 EventsRequest
*event_request_lpos
= (EventsRequest
*)g_slist_nth_data(lpos
, 0);
918 EventsRequest
*event_request_ltime
= (EventsRequest
*)g_slist_nth_data(ltime
, 0);
919 LttTime lpos_start_time
;
921 if(event_request_lpos
!= NULL
922 && event_request_lpos
->start_position
!= NULL
) {
923 lpos_start_time
= lttv_traceset_position_get_time(
924 event_request_lpos
->start_position
);
927 /* 1.1.3 If lpos.start time < ltime */
928 if(event_request_lpos
!= NULL
929 && event_request_lpos
->start_position
!= NULL
930 && ltt_time_compare(lpos_start_time
,
931 event_request_ltime
->start_time
)<0) {
932 /* Add lpos to list_in, remove them from list_out */
933 for(iter
=lpos
;iter
!=NULL
;iter
=g_slist_next(iter
)) {
935 EventsRequest
*event_request_lpos
=
936 (EventsRequest
*)iter
->data
;
938 list_in
= g_slist_append(list_in
, event_request_lpos
);
939 /* Remove from list_out */
940 list_out
= g_slist_remove(list_out
, event_request_lpos
);
943 /* 1.1.4 (lpos.start time >= ltime) */
944 /* Add ltime to list_in, remove them from list_out */
946 for(iter
=ltime
;iter
!=NULL
;iter
=g_slist_next(iter
)) {
948 EventsRequest
*event_request_ltime
=
949 (EventsRequest
*)iter
->data
;
951 list_in
= g_slist_append(list_in
, event_request_ltime
);
952 /* Remove from list_out */
953 list_out
= g_slist_remove(list_out
, event_request_ltime
);
964 g_assert(g_slist_length(list_in
)>0);
965 EventsRequest
*events_request
= g_slist_nth_data(list_in
, 0);
970 /* 1.2.1 If first request in list_in is a time request */
971 if(events_request
->start_position
== NULL
) {
972 /* - If first req in list_in start time != current time */
973 //TODO ybrosseau: if commented out, since it was only affecting the g_debug
974 //if(tfc == NULL || ltt_time_compare(events_request->start_time,
975 // tfc->timestamp) != 0)
976 /* - Seek to that time */
977 g_debug("SEEK TIME : %lu, %lu", events_request
->start_time
.tv_sec
,
978 events_request
->start_time
.tv_nsec
);
979 lttv_state_traceset_seek_time_closest(ts
,
980 events_request
->start_time
);
982 /* Process the traceset with only state hooks */
986 lttv_process_traceset_middle(ts
,
987 events_request
->start_time
,
990 g_assert(seek_count
< LTTV_STATE_SAVE_INTERVAL
);
996 //LttvTracefileContext *tfc =
997 // lttv_traceset_context_get_current_tfc(tsc);
998 /* Else, the first request in list_in is a position request */
999 /* If first req in list_in pos != current pos */
1000 g_assert(events_request
->start_position
!= NULL
);
1001 g_debug("SEEK POS time : %lu, %lu",
1002 lttv_traceset_position_get_time(
1003 events_request
->start_position
).tv_sec
,
1004 lttv_traceset_position_get_time(
1005 events_request
->start_position
).tv_nsec
);
1007 /*if(tfc) {*/ if(0) {
1008 /* g_debug("SEEK POS context time : %lu, %lu",
1009 tfc->timestamp.tv_sec,
1010 tfc->timestamp.tv_nsec); */
1012 g_debug("SEEK POS context time : %lu, %lu",
1013 ltt_time_infinite
.tv_sec
,
1014 ltt_time_infinite
.tv_nsec
);
1016 g_assert(events_request
->start_position
!= NULL
);
1017 //TODO ybrosseau: for now, always seek
1018 if(/*lttv_traceset_context_ctx_pos_compare(tsc,
1019 events_request->start_position) != 0*/1) {
1020 /* 1.2.2.1 Seek to that position */
1021 g_debug("SEEK POSITION");
1022 //lttv_process_traceset_seek_position(tsc, events_request->start_position);
1023 pos_time
= lttv_traceset_position_get_time(
1024 events_request
->start_position
);
1026 lttv_state_traceset_seek_time_closest(ts
,
1028 //lttv_traceset_seek_to_position( events_request->start_position);
1030 /* Process the traceset with only state hooks */
1034 lttv_process_traceset_middle(ts
,
1037 events_request
->start_position
);
1039 //g_assert(lttv_traceset_context_ctx_pos_compare(tsc,
1040 // events_request->start_position) == 0);
1047 /* 1.3 Add hooks and call before request for all list_in members */
1049 GSList
*iter
= NULL
;
1051 for(iter
=list_in
;iter
!=NULL
;iter
=g_slist_next(iter
)) {
1052 EventsRequest
*events_request
= (EventsRequest
*)iter
->data
;
1053 /* 1.3.1 If !servicing */
1054 if(events_request
->servicing
== FALSE
) {
1055 /* - begin request hooks called
1056 * - servicing = TRUE
1058 lttv_hooks_call(events_request
->before_request
, (gpointer
)ts
);
1059 events_request
->servicing
= TRUE
;
1061 /* 1.3.2 call before chunk
1062 * 1.3.3 events hooks added
1064 //TODO ybrosseau 2012-07-10: || TRUE added since we only support
1065 // traceset wide requests
1066 if(events_request
->trace
== -1 || TRUE
)
1067 lttv_process_traceset_begin(ts
,
1068 events_request
->before_chunk_traceset
,
1069 events_request
->before_chunk_trace
,
1070 events_request
->event
1073 guint nb_trace
= lttv_traceset_number(ts
);
1074 g_assert((guint
)events_request
->trace
< nb_trace
&&
1075 events_request
->trace
> -1);
1076 LttvTrace
*trace
= lttv_traceset_get(ts
, events_request
->trace
);
1078 lttv_hooks_call(events_request
->before_chunk_traceset
, ts
);
1080 lttv_trace_add_hooks(trace
,
1081 events_request
->before_chunk_trace
,
1083 events_request
->event
1089 /* 2. Else, list_in is not empty, we continue a read */
1092 /* 2.0 For each req of list_in */
1093 GSList
*iter
= list_in
;
1095 while(iter
!= NULL
) {
1097 EventsRequest
*events_request
= (EventsRequest
*)iter
->data
;
1099 /* - Call before chunk
1100 * - events hooks added
1102 //TODO ybrosseau 2012-07-10: || TRUE added since we only support
1103 // traceset wide requests
1104 if(events_request
->trace
== -1 || TRUE
)
1105 lttv_process_traceset_begin(ts
,
1106 events_request
->before_chunk_traceset
,
1107 events_request
->before_chunk_trace
,
1108 events_request
->event
1111 guint nb_trace
= lttv_traceset_number(ts
);
1112 g_assert((guint
)events_request
->trace
< nb_trace
&&
1113 events_request
->trace
> -1);
1114 LttvTrace
*trace
= lttv_traceset_get(ts
, events_request
->trace
);
1116 lttv_hooks_call(events_request
->before_chunk_traceset
, ts
);
1118 lttv_trace_add_hooks(trace
,
1119 events_request
->before_chunk_trace
,
1121 events_request
->event
1125 iter
= g_slist_next(iter
);
1132 /* 2.1 For each req of list_out */
1133 GSList
*iter
= list_out
;
1135 while(iter
!= NULL
) {
1137 gboolean remove
= FALSE
;
1138 gboolean free_data
= FALSE
;
1139 EventsRequest
*events_request
= (EventsRequest
*)iter
->data
;
1141 /* if req.start time == current context time
1142 * or req.start position == current position*/
1143 /* if( ltt_time_compare(events_request->start_time,
1144 tfc->timestamp) == 0
1146 (events_request->start_position != NULL
1148 lttv_traceset_context_ctx_pos_compare(tsc,
1149 events_request->start_position) == 0)
1152 if(lttv_traceset_position_compare_current(ts
, events_request
->start_position
) == 0) {
1154 /* - Add to list_in, remove from list_out */
1155 list_in
= g_slist_append(list_in
, events_request
);
1159 /* - If !servicing */
1160 if(events_request
->servicing
== FALSE
) {
1161 /* - begin request hooks called
1162 * - servicing = TRUE
1164 lttv_hooks_call(events_request
->before_request
, (gpointer
)ts
);
1165 events_request
->servicing
= TRUE
;
1167 /* call before chunk
1168 * events hooks added
1170 //TODO ybrosseau 2012-07-10: || TRUE added since we only support
1171 // traceset wide requests
1172 if(events_request
->trace
== -1 || TRUE
)
1173 lttv_process_traceset_begin(ts
,
1174 events_request
->before_chunk_traceset
,
1175 events_request
->before_chunk_trace
,
1176 events_request
->event
1179 guint nb_trace
= lttv_traceset_number(ts
);
1180 g_assert((guint
)events_request
->trace
< nb_trace
&&
1181 events_request
->trace
> -1);
1182 LttvTrace
* trace
= lttv_traceset_get(ts
,events_request
->trace
);
1184 lttv_hooks_call(events_request
->before_chunk_traceset
, ts
);
1186 lttv_trace_add_hooks(trace
,
1187 events_request
->before_chunk_trace
,
1189 events_request
->event
);
1199 GSList
*remove_iter
= iter
;
1201 iter
= g_slist_next(iter
);
1202 if(free_data
) events_request_free((EventsRequest
*)remove_iter
->data
);
1203 list_out
= g_slist_remove_link(list_out
, remove_iter
);
1204 } else { // not remove
1205 iter
= g_slist_next(iter
);
1211 /* 3. Find end criterions */
1216 /* 3.1.1 Find lowest end time in list_in */
1217 g_assert(g_slist_length(list_in
)>0);
1218 end_time
= ((EventsRequest
*)g_slist_nth_data(list_in
,0))->end_time
;
1220 for(iter
=g_slist_nth(list_in
,1);iter
!=NULL
;iter
=g_slist_next(iter
)) {
1221 EventsRequest
*events_request
= (EventsRequest
*)iter
->data
;
1223 if(ltt_time_compare(events_request
->end_time
,
1225 end_time
= events_request
->end_time
;
1228 /* 3.1.2 Find lowest start time in list_out */
1229 for(iter
=list_out
;iter
!=NULL
;iter
=g_slist_next(iter
)) {
1230 EventsRequest
*events_request
= (EventsRequest
*)iter
->data
;
1232 if(ltt_time_compare(events_request
->start_time
,
1234 end_time
= events_request
->start_time
;
1239 /* 3.2 Number of events */
1241 /* 3.2.1 Find lowest number of events in list_in */
1244 end_nb_events
= ((EventsRequest
*)g_slist_nth_data(list_in
,0))->num_events
;
1246 for(iter
=g_slist_nth(list_in
,1);iter
!=NULL
;iter
=g_slist_next(iter
)) {
1247 EventsRequest
*events_request
= (EventsRequest
*)iter
->data
;
1249 if(events_request
->num_events
< end_nb_events
)
1250 end_nb_events
= events_request
->num_events
;
1253 /* 3.2.2 Use min(CHUNK_NUM_EVENTS, min num events in list_in) as
1256 end_nb_events
= MIN(CHUNK_NUM_EVENTS
, end_nb_events
);
1260 /* 3.3 End position */
1262 /* 3.3.1 Find lowest end position in list_in */
1265 end_position
=((EventsRequest
*)g_slist_nth_data(list_in
,0))->end_position
;
1267 for(iter
=g_slist_nth(list_in
,1);iter
!=NULL
;iter
=g_slist_next(iter
)) {
1268 EventsRequest
*events_request
= (EventsRequest
*)iter
->data
;
1270 if(events_request
->end_position
!= NULL
&& end_position
!= NULL
&&
1271 lttv_traceset_position_time_compare(events_request
->end_position
,
1273 end_position
= events_request
->end_position
;
1278 /* 3.3.2 Find lowest start position in list_out */
1281 for(iter
=list_out
;iter
!=NULL
;iter
=g_slist_next(iter
)) {
1282 EventsRequest
*events_request
= (EventsRequest
*)iter
->data
;
1284 if(events_request
->end_position
!= NULL
&& end_position
!= NULL
&&
1285 lttv_traceset_position_time_compare(events_request
->end_position
,
1287 end_position
= events_request
->end_position
;
1292 /* 4. Call process traceset middle */
1293 g_debug("Calling process traceset middle with %p, %lu sec %lu nsec, %u nb ev, %p end pos", ts
, end_time
.tv_sec
, end_time
.tv_nsec
, end_nb_events
, end_position
);
1294 count
= lttv_process_traceset_middle(ts
, end_time
, end_nb_events
, end_position
);
1296 #ifdef BABEL_CLEANUP
1297 tfc
= lttv_traceset_context_get_current_tfc(tsc
);
1299 g_debug("Context time after middle : %lu, %lu", tfc
->timestamp
.tv_sec
,
1300 tfc
->timestamp
.tv_nsec
);
1302 g_debug("End of trace reached after middle.");
1307 /* 5. After process traceset middle */
1309 LttTime curTime
= lttv_traceset_get_current_time(ts
);
1310 /* - if the iterator is not valid anymore (got to the end) */
1311 if(bt_ctf_iter_read_event(ts
->iter
) == NULL
) {
1312 /* - For each req in list_in */
1313 GSList
*iter
= list_in
;
1315 while(iter
!= NULL
) {
1317 gboolean remove
= FALSE
;
1318 gboolean free_data
= FALSE
;
1319 EventsRequest
*events_request
= (EventsRequest
*)iter
->data
;
1321 /* - Remove events hooks for req
1322 * - Call end chunk for req
1324 //TODO ybrosseau 2012-07-10: || TRUE added since we only support
1325 // traceset wide requests
1326 if(events_request
->trace
== -1 || TRUE
)
1327 lttv_process_traceset_end(ts
,
1328 events_request
->after_chunk_traceset
,
1329 events_request
->after_chunk_trace
,
1331 events_request
->event
);
1334 guint nb_trace
= lttv_traceset_number(ts
);
1335 g_assert(events_request
->trace
< nb_trace
&&
1336 events_request
->trace
> -1);
1337 LttvTrace
*trace
= lttv_traceset_get(ts
,events_request
->trace
);
1339 lttv_trace_remove_hooks(trace
,
1340 events_request
->after_chunk_trace
,
1342 events_request
->event
);
1344 lttv_hooks_call(events_request
->after_chunk_traceset
, ts
);
1349 /* - Call end request for req */
1350 lttv_hooks_call(events_request
->after_request
, (gpointer
)ts
);
1352 /* - remove req from list_in */
1353 /* Destroy the request */
1360 GSList
*remove_iter
= iter
;
1362 iter
= g_slist_next(iter
);
1363 if(free_data
) events_request_free((EventsRequest
*)remove_iter
->data
);
1364 list_in
= g_slist_remove_link(list_in
, remove_iter
);
1365 } else { // not remove
1366 iter
= g_slist_next(iter
);
1371 /* 5.1 For each req in list_in */
1372 GSList
*iter
= list_in
;
1374 while(iter
!= NULL
) {
1376 gboolean remove
= FALSE
;
1377 gboolean free_data
= FALSE
;
1378 EventsRequest
*events_request
= (EventsRequest
*)iter
->data
;
1380 /* - Remove events hooks for req
1381 * - Call end chunk for req
1383 //TODO ybrosseau 2012-07-10: || TRUE added since we only support
1384 // traceset wide requests
1385 if(events_request
->trace
== -1 || TRUE
)
1386 lttv_process_traceset_end(ts
,
1387 events_request
->after_chunk_traceset
,
1388 events_request
->after_chunk_trace
,
1390 events_request
->event
);
1394 guint nb_trace
= lttv_traceset_number(ts
);
1395 g_assert(events_request
->trace
< nb_trace
&&
1396 events_request
->trace
> -1);
1397 LttvTrace
*trace
= lttv_traceset_get(ts
, events_request
->trace
);
1399 lttv_trace_remove_hooks(trace
,
1400 events_request
->after_chunk_trace
,
1402 events_request
->event
);
1405 lttv_hooks_call(events_request
->after_chunk_traceset
, ts
);
1408 /* - req.num -= count */
1409 g_assert(events_request
->num_events
>= count
);
1410 events_request
->num_events
-= count
;
1412 //g_assert(tfc != NULL);
1413 /* - if req.num == 0
1415 * current context time >= req.end time
1417 * req.end pos == current pos
1419 * req.stop_flag == TRUE
1421 if( events_request
->num_events
== 0
1423 events_request
->stop_flag
== TRUE
1425 ltt_time_compare(lttv_traceset_get_current_time(ts
),
1426 events_request
->end_time
) >= 0
1428 (events_request
->end_position
!= NULL
1430 lttv_traceset_position_compare_current(ts
,
1431 events_request
->end_position
) == 0)
1434 g_assert(events_request
->servicing
== TRUE
);
1435 /* - Call end request for req
1436 * - remove req from list_in */
1437 lttv_hooks_call(events_request
->after_request
, (gpointer
)ts
);
1438 /* - remove req from list_in */
1439 /* Destroy the request */
1447 GSList
*remove_iter
= iter
;
1449 iter
= g_slist_next(iter
);
1450 if(free_data
) events_request_free((EventsRequest
*)remove_iter
->data
);
1451 list_in
= g_slist_remove_link(list_in
, remove_iter
);
1452 } else { // not remove
1453 iter
= g_slist_next(iter
);
1459 /* End of removed servicing loop : leave control to GTK instead. */
1460 // if(gtk_events_pending()) break;
1463 /* B. When interrupted between chunks */
1466 GSList
*iter
= list_in
;
1468 /* 1. for each request in list_in */
1469 while(iter
!= NULL
) {
1471 gboolean remove
= FALSE
;
1472 gboolean free_data
= FALSE
;
1473 EventsRequest
*events_request
= (EventsRequest
*)iter
->data
;
1475 /* 1.1. Use current postition as start position */
1476 if(events_request
->start_position
!= NULL
)
1477 lttv_traceset_destroy_position(events_request
->start_position
);
1478 events_request
->start_position
= lttv_traceset_create_current_position(ts
);
1481 /* 1.2. Remove start time */
1482 events_request
->start_time
= ltt_time_infinite
;
1484 /* 1.3. Move from list_in to list_out */
1487 list_out
= g_slist_append(list_out
, events_request
);
1492 GSList
*remove_iter
= iter
;
1494 iter
= g_slist_next(iter
);
1495 if(free_data
) events_request_free((EventsRequest
*)remove_iter
->data
);
1496 list_in
= g_slist_remove_link(list_in
, remove_iter
);
1497 } else { // not remove
1498 iter
= g_slist_next(iter
);
1504 /* C Unlock Traces */
1506 #ifdef BABEL_CLEANUP
1507 lttv_process_traceset_get_sync_data(tsc
);
1509 //lttv_traceset_context_position_save(tsc, sync_position);
1514 iter_trace
<lttv_traceset_number(ts
);
1516 LttvTrace
*trace_v
= lttv_traceset_get(ts
, iter_trace
);
1518 lttvwindowtraces_unlock(trace_v
);
1522 //set the cursor back to normal
1523 gdk_window_set_cursor(win
, NULL
);
1526 g_assert(g_slist_length(list_in
) == 0);
1528 if( g_slist_length(list_out
) == 0 ) {
1529 /* Put tab's request pending flag back to normal */
1530 tab
->events_request_pending
= FALSE
;
1531 g_debug("remove the idle fct");
1532 return FALSE
; /* Remove the idle function */
1534 g_debug("leave the idle fct");
1535 return TRUE
; /* Leave the idle function */
1537 /* We do not use simili-round-robin, it may require to read 1 meg buffers
1538 * again and again if many tracesets use the same tracefiles. */
1539 /* Hack for round-robin idle functions */
1540 /* It will put the idle function at the end of the pool */
1541 /*g_idle_add_full((G_PRIORITY_HIGH_IDLE + 21),
1542 (GSourceFunc)execute_events_requests,
1553 Manage the periodic update of a live trace
1556 live_trace_update_handler(Tab
*tab
)
1558 #ifdef BABEL_CLEANUP
1559 unsigned int updated_count
;
1560 LttvTracesetContext
*tsc
= LTTV_TRACESET_CONTEXT(tab
->traceset_info
->traceset_context
);
1561 TimeInterval initial_time_span
= tsc
->time_span
;
1562 TimeInterval updated_time_span
;
1564 updated_count
= lttv_process_traceset_update(tsc
);
1566 /* TODO ybrosseau 2011-01-12: Add trace resynchronization */
1568 /* Get the changed period bounds */
1569 updated_time_span
= tsc
->time_span
;
1571 if(ltt_time_compare(updated_time_span
.start_time
,
1572 initial_time_span
.start_time
) != 0) {
1573 /* The initial time should not change on a live update */
1577 /* Notify viewers (only on updates) */
1578 if(ltt_time_compare(updated_time_span
.end_time
,
1579 initial_time_span
.end_time
) != 0) {
1581 notify_time_span_changed(tab
);
1582 /* TODO ybrosseau 2011-01-12: Change the timebar to register
1583 to the time_span hook */
1584 timebar_set_minmax_time(TIMEBAR(tab
->MTimebar
),
1585 &updated_time_span
.start_time
,
1586 &updated_time_span
.end_time
);
1588 /* To update the min max */
1589 time_change_manager(tab
, tab
->time_window
);
1592 /* Timer will be recalled as long as there is files to update */
1593 return (updated_count
> 0);
1594 #endif /* BABEL_CLEANUP */
1597 static void lttvwindow_add_trace(Tab
*tab
, LttvTrace
*trace_v
)
1599 #ifdef BABEL_CLEANUP
1600 LttvTraceset
*traceset
= tab
->traceset_info
->traceset
;
1602 guint num_traces
= lttv_traceset_number(traceset
);
1604 //Verify if trace is already present.
1605 for(i
=0; i
<num_traces
; i
++)
1607 LttvTrace
* trace
= lttv_traceset_get(traceset
, i
);
1608 if(trace
== trace_v
)
1612 //Keep a reference to the traces so they are not freed.
1613 for(i
=0; i
<lttv_traceset_number(traceset
); i
++)
1615 LttvTrace
* trace
= lttv_traceset_get(traceset
, i
);
1616 lttv_trace_ref(trace
);
1619 //remove state update hooks
1620 lttv_state_remove_event_hooks(
1621 (LttvTracesetState
*)tab
->traceset_info
->traceset_context
);
1623 lttv_context_fini(LTTV_TRACESET_CONTEXT(
1624 tab
->traceset_info
->traceset_context
));
1625 g_object_unref(tab
->traceset_info
->traceset_context
);
1627 lttv_traceset_add(traceset
, trace_v
);
1628 lttv_trace_ref(trace_v
); /* local ref */
1630 /* Create new context */
1631 tab
->traceset_info
->traceset_context
=
1632 g_object_new(LTTV_TRACESET_STATS_TYPE
, NULL
);
1634 LTTV_TRACESET_CONTEXT(tab
->traceset_info
->
1639 //add state update hooks
1640 lttv_state_add_event_hooks(
1641 (LttvTracesetState
*)tab
->traceset_info
->traceset_context
);
1642 //Remove local reference to the traces.
1643 for(i
=0; i
<lttv_traceset_number(traceset
); i
++)
1645 LttvTrace
* trace
= lttv_traceset_get(traceset
, i
);
1646 lttv_trace_unref(trace
);
1650 //add_trace_into_traceset_selector(GTK_MULTIVPANED(tab->multivpaned), lttv_trace(trace_v));
1653 if (lttv_trace(trace_v
)->is_live
) {
1654 /* Add timer for live update */
1655 /* TODO ybrosseau 2011-01-12: Parametrize the hardcoded 1 seconds */
1656 g_timeout_add_seconds (1,
1657 (GSourceFunc
) live_trace_update_handler
,
1660 #endif /* BABEL_CLEANUP */
1663 /* add_trace adds a trace into the current traceset. It first displays a
1664 * directory selection dialogue to let user choose a trace, then recreates
1665 * tracset_context, and redraws all the viewer of the current tab
1668 void add_trace(GtkWidget
* widget
, gpointer user_data
)
1671 LttvTraceset
* traceset
= NULL
;
1673 char abs_path
[PATH_MAX
];
1675 MainWindow
* mw_data
= get_window_data_struct(widget
);
1676 GtkWidget
* notebook
= lookup_widget(widget
, "MNotebook");
1678 GtkWidget
*page
= gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook
),
1679 gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook
)));
1680 LttvPluginTab
*ptab
;
1684 ptab
= create_new_tab(widget
, NULL
);
1687 ptab
= (LttvPluginTab
*)g_object_get_data(G_OBJECT(page
), "Tab_Plugin");
1690 //TODO fdeslauriers 2012-07-06: Remove this popup when we support multiple traces
1691 traceset
= lttvwindow_get_traceset(tab
);
1692 if(traceset
!= NULL
&& lttv_traceset_number(traceset
) > 0){
1693 GtkWidget
*dialogue
=
1694 gtk_message_dialog_new(
1695 GTK_WINDOW(gtk_widget_get_toplevel(widget
)),
1696 GTK_DIALOG_MODAL
|GTK_DIALOG_DESTROY_WITH_PARENT
,
1699 "Loading multiple traces is not supported at the moment.");
1700 gtk_dialog_run(GTK_DIALOG(dialogue
));
1701 gtk_widget_destroy(dialogue
);
1705 /* Create a new traceset*/
1706 traceset
= lttv_traceset_new();
1707 /* File open dialog management */
1708 #ifdef BABEL_CLEANUP
1709 GtkWidget
*extra_live_button
;
1710 #endif //babel_cleanup
1711 GtkFileChooser
* file_chooser
=
1713 gtk_file_chooser_dialog_new ("Select a trace",
1714 GTK_WINDOW(mw_data
->mwindow
),
1715 GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER
,
1716 GTK_STOCK_CANCEL
, GTK_RESPONSE_CANCEL
,
1717 GTK_STOCK_OPEN
, GTK_RESPONSE_ACCEPT
,
1719 #ifdef BABEL_CLEANUP
1720 /* Button to indicate the opening of a live trace */
1721 extra_live_button
= gtk_check_button_new_with_mnemonic ("Trace is live (currently being writen)");
1722 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (extra_live_button
), FALSE
);
1723 gtk_file_chooser_set_extra_widget (GTK_FILE_CHOOSER (file_chooser
), extra_live_button
);
1724 #endif //babel_cleanup
1725 gtk_file_chooser_set_show_hidden (file_chooser
, TRUE
);
1726 if(remember_trace_dir
[0] != '\0')
1727 gtk_file_chooser_set_filename(file_chooser
, remember_trace_dir
);
1729 gboolean closeFileChooserDialog
= TRUE
;
1733 id
= gtk_dialog_run(GTK_DIALOG(file_chooser
));
1735 case GTK_RESPONSE_ACCEPT
:
1736 case GTK_RESPONSE_OK
:
1737 path
= gtk_file_chooser_get_filename (file_chooser
);
1739 strncpy(remember_trace_dir
, path
, PATH_MAX
);
1740 strncat(remember_trace_dir
, "/", PATH_MAX
);
1741 if(!path
|| strlen(path
) == 0){
1744 get_absolute_pathname(path
, abs_path
);
1746 if(lttv_traceset_add_path(traceset
,abs_path
) != 0 ){ /*failure*/
1748 g_warning("cannot open trace %s", abs_path
);
1749 strncpy(remember_trace_dir
, "\0", PATH_MAX
);
1750 GtkWidget
*dialogue
=
1751 gtk_message_dialog_new(
1752 GTK_WINDOW(gtk_widget_get_toplevel(widget
)),
1753 GTK_DIALOG_MODAL
|GTK_DIALOG_DESTROY_WITH_PARENT
,
1756 "Cannot open trace : maybe you should enter in the directory "
1758 gtk_dialog_run(GTK_DIALOG(dialogue
));
1759 gtk_widget_destroy(dialogue
);
1760 closeFileChooserDialog
= FALSE
;
1763 closeFileChooserDialog
= TRUE
;
1764 SetTraceset(tab
, traceset
);
1767 //update current tab
1768 //update_traceset(mw_data);
1770 // in expose now call_pending_read_hooks(mw_data);
1772 //lttvwindow_report_current_time(mw_data,&(tab->current_time));
1774 case GTK_RESPONSE_REJECT
:
1775 case GTK_RESPONSE_CANCEL
:
1777 closeFileChooserDialog
= TRUE
;
1780 }while(!closeFileChooserDialog
);
1782 gtk_widget_destroy((GtkWidget
*)file_chooser
);
1786 /* remove_trace removes a trace from the current traceset if all viewers in
1787 * the current tab are not interested in the trace. It first displays a
1788 * dialogue, which shows all traces in the current traceset, to let user choose
1789 * a trace, then it checks if all viewers unselect the trace, if it is true,
1790 * it will remove the trace, recreate the traceset_contex,
1791 * and redraws all the viewer of the current tab. If there is on trace in the
1792 * current traceset, it will delete all viewers of the current tab
1794 * It destroys the filter tree. FIXME... we should request for an update
1798 void remove_trace(GtkWidget
*widget
, gpointer user_data
)
1800 #ifdef BABEL_CLEANUP
1802 LttvTrace
* trace_v
;
1803 LttvTraceset
* traceset
;
1804 gint i
, j
, nb_trace
, index
=-1;
1805 char ** name
, *remove_trace_name
;
1806 MainWindow
* mw_data
= get_window_data_struct(widget
);
1807 GtkWidget
* notebook
= lookup_widget(widget
, "MNotebook");
1809 GtkWidget
*page
= gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook
),
1810 gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook
)));
1816 LttvPluginTab
*ptab
;
1817 ptab
= (LttvPluginTab
*)g_object_get_data(G_OBJECT(page
), "Tab_Plugin");
1821 nb_trace
=lttv_traceset_number(tab
->traceset_info
->traceset
);
1822 name
= g_new(char*,nb_trace
);
1823 for(i
= 0; i
< nb_trace
; i
++){
1824 trace_v
= lttv_traceset_get(tab
->traceset_info
->traceset
, i
);
1825 trace
= lttv_trace(trace_v
);
1826 name
[i
] = (char *) g_quark_to_string(ltt_trace_name(trace
));
1829 remove_trace_name
= get_remove_trace(mw_data
, name
, nb_trace
);
1832 if(remove_trace_name
){
1834 /* yuk, cut n paste from old code.. should be better (MD)*/
1835 for(i
= 0; i
<nb_trace
; i
++) {
1836 if(strcmp(remove_trace_name
,name
[i
]) == 0){
1841 traceset
= tab
->traceset_info
->traceset
;
1842 //Keep a reference to the traces so they are not freed.
1843 for(j
=0; j
<lttv_traceset_number(traceset
); j
++)
1845 LttvTrace
* trace
= lttv_traceset_get(traceset
, j
);
1846 lttv_trace_ref(trace
);
1849 //remove state update hooks
1850 lttv_state_remove_event_hooks(
1851 (LttvTracesetState
*)tab
->traceset_info
->traceset_context
);
1852 lttv_context_fini(LTTV_TRACESET_CONTEXT(tab
->traceset_info
->traceset_context
));
1853 g_object_unref(tab
->traceset_info
->traceset_context
);
1855 trace_v
= lttv_traceset_get(traceset
, index
);
1857 lttv_traceset_remove(traceset
, index
);
1858 lttv_trace_unref(trace_v
); // Remove local reference
1860 if(lttv_trace_get_ref_number(trace_v
) <= 1) {
1861 /* ref 1 : lttvwindowtraces only*/
1862 ltt_trace_close(lttv_trace(trace_v
));
1863 /* lttvwindowtraces_remove_trace takes care of destroying
1864 * the traceset linked with the trace_v and also of destroying
1865 * the trace_v at the same time.
1867 lttvwindowtraces_remove_trace(trace_v
);
1870 tab
->traceset_info
->traceset_context
=
1871 g_object_new(LTTV_TRACESET_STATS_TYPE
, NULL
);
1873 LTTV_TRACESET_CONTEXT(tab
->
1874 traceset_info
->traceset_context
),traceset
);
1875 //add state update hooks
1876 lttv_state_add_event_hooks(
1877 (LttvTracesetState
*)tab
->traceset_info
->traceset_context
);
1879 //Remove local reference to the traces.
1880 for(j
=0; j
<lttv_traceset_number(traceset
); j
++)
1882 LttvTrace
* trace
= lttv_traceset_get(traceset
, j
);
1883 lttv_trace_unref(trace
);
1886 SetTraceset(tab
, (gpointer
)traceset
);
1889 #endif /* BABEL_CLEANUP */
1893 void remove_trace(GtkWidget
* widget
, gpointer user_data
)
1896 LttvTrace
* trace_v
;
1897 LttvTraceset
* traceset
;
1898 gint i
, j
, nb_trace
;
1899 char ** name
, *remove_trace_name
;
1900 MainWindow
* mw_data
= get_window_data_struct(widget
);
1901 LttvTracesetSelector
* s
;
1902 LttvTraceSelector
* t
;
1905 GtkWidget
* notebook
= lookup_widget(widget
, "MNotebook");
1907 GtkWidget
*page
= gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook
),
1908 gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook
)));
1914 tab
= (Tab
*)g_object_get_data(G_OBJECT(page
), "Tab_Info");
1917 nb_trace
=lttv_traceset_number(tab
->traceset_info
->traceset
);
1918 name
= g_new(char*,nb_trace
);
1919 for(i
= 0; i
< nb_trace
; i
++){
1920 trace_v
= lttv_traceset_get(tab
->traceset_info
->traceset
, i
);
1921 trace
= lttv_trace(trace_v
);
1922 name
[i
] = ltt_trace_name(trace
);
1925 remove_trace_name
= get_remove_trace(name
, nb_trace
);
1927 if(remove_trace_name
){
1928 for(i
=0; i
<nb_trace
; i
++){
1929 if(strcmp(remove_trace_name
,name
[i
]) == 0){
1930 //unselect the trace from the current viewer
1932 w
= gtk_multivpaned_get_widget(GTK_MULTIVPANED(tab
->multivpaned
));
1934 s
= g_object_get_data(G_OBJECT(w
), "Traceset_Selector");
1936 t
= lttv_traceset_selector_trace_get(s
,i
);
1937 lttv_trace_selector_set_selected(t
, FALSE
);
1940 //check if other viewers select the trace
1941 w
= gtk_multivpaned_get_first_widget(GTK_MULTIVPANED(tab
->multivpaned
));
1943 s
= g_object_get_data(G_OBJECT(w
), "Traceset_Selector");
1945 t
= lttv_traceset_selector_trace_get(s
,i
);
1946 selected
= lttv_trace_selector_get_selected(t
);
1949 w
= gtk_multivpaned_get_next_widget(GTK_MULTIVPANED(tab
->multivpaned
));
1951 }else selected
= FALSE
;
1953 //if no viewer selects the trace, remove it
1955 remove_trace_from_traceset_selector(GTK_MULTIVPANED(tab
->multivpaned
), i
);
1957 traceset
= tab
->traceset_info
->traceset
;
1958 //Keep a reference to the traces so they are not freed.
1959 for(j
=0; j
<lttv_traceset_number(traceset
); j
++)
1961 LttvTrace
* trace
= lttv_traceset_get(traceset
, j
);
1962 lttv_trace_ref(trace
);
1965 //remove state update hooks
1966 lttv_state_remove_event_hooks(
1967 (LttvTracesetState
*)tab
->traceset_info
->traceset_context
);
1968 lttv_context_fini(LTTV_TRACESET_CONTEXT(tab
->traceset_info
->traceset_context
));
1969 g_object_unref(tab
->traceset_info
->traceset_context
);
1972 trace_v
= lttv_traceset_get(traceset
, i
);
1974 if(lttv_trace_get_ref_number(trace_v
) <= 2) {
1975 /* ref 2 : traceset, local */
1976 lttvwindowtraces_remove_trace(trace_v
);
1977 ltt_trace_close(lttv_trace(trace_v
));
1980 lttv_traceset_remove(traceset
, i
);
1981 lttv_trace_unref(trace_v
); // Remove local reference
1983 if(!lttv_trace_get_ref_number(trace_v
))
1984 lttv_trace_destroy(trace_v
);
1986 tab
->traceset_info
->traceset_context
=
1987 g_object_new(LTTV_TRACESET_STATS_TYPE
, NULL
);
1989 LTTV_TRACESET_CONTEXT(tab
->
1990 traceset_info
->traceset_context
),traceset
);
1991 //add state update hooks
1992 lttv_state_add_event_hooks(
1993 (LttvTracesetState
*)tab
->traceset_info
->traceset_context
);
1995 //Remove local reference to the traces.
1996 for(j
=0; j
<lttv_traceset_number(traceset
); j
++)
1998 LttvTrace
* trace
= lttv_traceset_get(traceset
, j
);
1999 lttv_trace_unref(trace
);
2003 //update current tab
2004 //update_traceset(mw_data);
2007 SetTraceset(tab
, (gpointer
)traceset
);
2008 // in expose now call_pending_read_hooks(mw_data);
2010 //lttvwindow_report_current_time(mw_data,&(tab->current_time));
2013 // while(tab->multi_vpaned->num_children){
2014 // gtk_multi_vpaned_widget_delete(tab->multi_vpaned);
2028 /* Redraw all the viewers in the current tab */
2029 void redraw(GtkWidget
*widget
, gpointer user_data
)
2031 GtkWidget
* notebook
= lookup_widget(widget
, "MNotebook");
2032 GtkWidget
*page
= gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook
),
2033 gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook
)));
2040 LttvPluginTab
*ptab
;
2041 ptab
= (LttvPluginTab
*)g_object_get_data(G_OBJECT(page
), "Tab_Plugin");
2046 LttvAttributeValue value
;
2048 retval
= lttv_iattribute_find_by_path(tab
->attributes
, "hooks/redraw", LTTV_POINTER
, &value
);
2051 tmp
= (LttvHooks
*)*(value
.v_pointer
);
2053 lttv_hooks_call(tmp
,NULL
);
2057 void continue_processing(GtkWidget
*widget
, gpointer user_data
)
2059 GtkWidget
* notebook
= lookup_widget(widget
, "MNotebook");
2060 GtkWidget
*page
= gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook
),
2061 gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook
)));
2068 LttvPluginTab
*ptab
;
2069 ptab
= (LttvPluginTab
*)g_object_get_data(G_OBJECT(page
), "Tab_Plugin");
2074 LttvAttributeValue value
;
2076 retval
= lttv_iattribute_find_by_path(tab
->attributes
, "hooks/continue",
2077 LTTV_POINTER
, &value
);
2080 tmp
= (LttvHooks
*)*(value
.v_pointer
);
2082 lttv_hooks_call(tmp
,NULL
);
2085 /* Stop the processing for the calling main window's current tab.
2086 * It removes every processing requests that are in its list. It does not call
2087 * the end request hooks, because the request is not finished.
2090 void stop_processing(GtkWidget
*widget
, gpointer user_data
)
2092 GtkWidget
* notebook
= lookup_widget(widget
, "MNotebook");
2093 GtkWidget
*page
= gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook
),
2094 gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook
)));
2099 LttvPluginTab
*ptab
;
2100 ptab
= (LttvPluginTab
*)g_object_get_data(G_OBJECT(page
), "Tab_Plugin");
2103 GSList
*iter
= tab
->events_requests
;
2105 while(iter
!= NULL
) {
2106 GSList
*remove_iter
= iter
;
2107 iter
= g_slist_next(iter
);
2109 g_free(remove_iter
->data
);
2110 tab
->events_requests
=
2111 g_slist_remove_link(tab
->events_requests
, remove_iter
);
2113 tab
->events_request_pending
= FALSE
;
2114 tab
->stop_foreground
= TRUE
;
2115 g_idle_remove_by_data(tab
);
2116 g_assert(g_slist_length(tab
->events_requests
) == 0);
2120 /* save will save the traceset to a file
2121 * Not implemented yet FIXME
2124 void save(GtkWidget
* widget
, gpointer user_data
)
2129 void save_as(GtkWidget
* widget
, gpointer user_data
)
2131 g_info("Save as\n");
2135 /* zoom will change the time_window of all the viewers of the
2136 * current tab, and redisplay them. The main functionality is to
2137 * determine the new time_window of the current tab
2140 void zoom(GtkWidget
* widget
, double size
)
2142 #ifdef BABEL_CLEANUP
2143 TimeInterval time_span
;
2144 TimeWindow new_time_window
;
2145 LttTime current_time
, time_delta
;
2146 LttvTracesetContext
*tsc
;
2147 GtkWidget
* notebook
= lookup_widget(widget
, "MNotebook");
2149 GtkWidget
*page
= gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook
),
2150 gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook
)));
2156 LttvPluginTab
*ptab
;
2157 ptab
= (LttvPluginTab
*)g_object_get_data(G_OBJECT(page
), "Tab_Plugin");
2161 if(size
== 1) return;
2163 tsc
= LTTV_TRACESET_CONTEXT(tab
->traceset_info
->traceset_context
);
2164 time_span
= tsc
->time_span
;
2165 new_time_window
= tab
->time_window
;
2166 current_time
= tab
->current_time
;
2168 time_delta
= ltt_time_sub(time_span
.end_time
,time_span
.start_time
);
2170 new_time_window
.start_time
= time_span
.start_time
;
2171 new_time_window
.time_width
= time_delta
;
2172 new_time_window
.time_width_double
= ltt_time_to_double(time_delta
);
2173 new_time_window
.end_time
= ltt_time_add(new_time_window
.start_time
,
2174 new_time_window
.time_width
) ;
2176 new_time_window
.time_width
= ltt_time_div(new_time_window
.time_width
, size
);
2177 new_time_window
.time_width_double
=
2178 ltt_time_to_double(new_time_window
.time_width
);
2179 if(ltt_time_compare(new_time_window
.time_width
,time_delta
) > 0)
2180 { /* Case where zoom out is bigger than trace length */
2181 new_time_window
.start_time
= time_span
.start_time
;
2182 new_time_window
.time_width
= time_delta
;
2183 new_time_window
.time_width_double
= ltt_time_to_double(time_delta
);
2184 new_time_window
.end_time
= ltt_time_add(new_time_window
.start_time
,
2185 new_time_window
.time_width
) ;
2189 /* Center the image on the current time */
2190 new_time_window
.start_time
=
2191 ltt_time_sub(current_time
,
2192 ltt_time_from_double(new_time_window
.time_width_double
/2.0));
2193 new_time_window
.end_time
= ltt_time_add(new_time_window
.start_time
,
2194 new_time_window
.time_width
) ;
2195 /* If on borders, don't fall off */
2196 if(ltt_time_compare(new_time_window
.start_time
, time_span
.start_time
) <0
2197 || ltt_time_compare(new_time_window
.start_time
, time_span
.end_time
) >0)
2199 new_time_window
.start_time
= time_span
.start_time
;
2200 new_time_window
.end_time
= ltt_time_add(new_time_window
.start_time
,
2201 new_time_window
.time_width
) ;
2205 if(ltt_time_compare(new_time_window
.end_time
,
2206 time_span
.end_time
) > 0
2207 || ltt_time_compare(new_time_window
.end_time
,
2208 time_span
.start_time
) < 0)
2210 new_time_window
.start_time
=
2211 ltt_time_sub(time_span
.end_time
, new_time_window
.time_width
);
2213 new_time_window
.end_time
= ltt_time_add(new_time_window
.start_time
,
2214 new_time_window
.time_width
) ;
2221 if(ltt_time_compare(new_time_window
.time_width
, ltt_time_zero
) == 0) {
2222 g_warning("Zoom more than 1 ns impossible");
2224 time_change_manager(tab
, new_time_window
);
2227 #endif /* BABEL_CLEANUP */
2230 void zoom_in(GtkWidget
* widget
, gpointer user_data
)
2235 void zoom_out(GtkWidget
* widget
, gpointer user_data
)
2240 void zoom_extended(GtkWidget
* widget
, gpointer user_data
)
2245 void go_to_time(GtkWidget
* widget
, gpointer user_data
)
2247 g_info("Go to time\n");
2250 void show_time_frame(GtkWidget
* widget
, gpointer user_data
)
2252 g_info("Show time frame\n");
2256 /* callback function */
2259 on_empty_traceset_activate (GtkMenuItem
*menuitem
,
2262 create_new_window((GtkWidget
*)menuitem
, user_data
, FALSE
);
2267 on_clone_traceset_activate (GtkMenuItem
*menuitem
,
2270 create_new_window((GtkWidget
*)menuitem
, user_data
, TRUE
);
2274 /* create_new_tab calls create_tab to construct a new tab in the main window
2277 LttvPluginTab
*create_new_tab(GtkWidget
* widget
, gpointer user_data
)
2279 gchar label
[PATH_MAX
];
2280 MainWindow
* mw_data
= get_window_data_struct(widget
);
2282 GtkNotebook
* notebook
= (GtkNotebook
*)lookup_widget(widget
, "MNotebook");
2283 if(notebook
== NULL
){
2284 g_info("Notebook does not exist\n");
2287 GtkWidget
*page
= gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook
),
2288 gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook
)));
2294 LttvPluginTab
*ptab
;
2295 ptab
= (LttvPluginTab
*)g_object_get_data(G_OBJECT(page
), "Tab_Plugin");
2296 copy_tab
= ptab
->tab
;
2299 strcpy(label
,"Page");
2300 if(get_label(mw_data
, label
,"Get the name of the tab","Please input tab's name")) {
2301 LttvPluginTab
*ptab
;
2303 ptab
= g_object_new(LTTV_TYPE_PLUGIN_TAB
, NULL
);
2304 init_tab (ptab
->tab
, mw_data
, copy_tab
, notebook
, label
);
2305 ptab
->parent
.top_widget
= ptab
->tab
->top_widget
;
2306 g_object_set_data_full(
2307 G_OBJECT(ptab
->tab
->vbox
),
2310 (GDestroyNotify
)tab_destructor
);
2317 on_tab_activate (GtkMenuItem
*menuitem
,
2320 create_new_tab((GtkWidget
*)menuitem
, user_data
);
2325 on_open_activate (GtkMenuItem
*menuitem
,
2328 #ifdef UNFINISHED_FEATURE
2329 open_traceset((GtkWidget
*)menuitem
, user_data
);
2335 on_close_activate (GtkMenuItem
*menuitem
,
2338 MainWindow
* mw_data
= get_window_data_struct((GtkWidget
*)menuitem
);
2339 main_window_destructor(mw_data
);
2343 /* remove the current tab from the main window
2347 on_close_tab_activate (GtkWidget
*widget
,
2351 GtkWidget
* notebook
;
2352 notebook
= lookup_widget(widget
, "MNotebook");
2353 if(notebook
== NULL
){
2354 g_info("Notebook does not exist\n");
2358 page_num
= gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook
));
2360 gtk_notebook_remove_page(GTK_NOTEBOOK(notebook
), page_num
);
2365 on_close_tab_X_clicked (GtkWidget
*widget
,
2369 GtkWidget
*notebook
= lookup_widget(widget
, "MNotebook");
2370 if(notebook
== NULL
){
2371 g_info("Notebook does not exist\n");
2375 if((page_num
= gtk_notebook_page_num(GTK_NOTEBOOK(notebook
), widget
)) != -1)
2376 gtk_notebook_remove_page(GTK_NOTEBOOK(notebook
), page_num
);
2382 on_add_trace_activate (GtkMenuItem
*menuitem
,
2385 add_trace((GtkWidget
*)menuitem
, user_data
);
2390 on_remove_trace_activate (GtkMenuItem
*menuitem
,
2393 remove_trace((GtkWidget
*)menuitem
, user_data
);
2398 on_save_activate (GtkMenuItem
*menuitem
,
2401 save((GtkWidget
*)menuitem
, user_data
);
2406 on_save_as_activate (GtkMenuItem
*menuitem
,
2409 save_as((GtkWidget
*)menuitem
, user_data
);
2414 on_quit_activate (GtkMenuItem
*menuitem
,
2417 while (g_slist_length(g_main_window_list
) != 0) {
2418 on_MWindow_destroy(((MainWindow
*)g_main_window_list
->data
)->mwindow
,
2425 on_cut_activate (GtkMenuItem
*menuitem
,
2433 on_copy_activate (GtkMenuItem
*menuitem
,
2441 on_paste_activate (GtkMenuItem
*menuitem
,
2449 on_delete_activate (GtkMenuItem
*menuitem
,
2457 on_zoom_in_activate (GtkMenuItem
*menuitem
,
2460 zoom_in((GtkWidget
*)menuitem
, user_data
);
2465 on_zoom_out_activate (GtkMenuItem
*menuitem
,
2468 zoom_out((GtkWidget
*)menuitem
, user_data
);
2473 on_zoom_extended_activate (GtkMenuItem
*menuitem
,
2476 zoom_extended((GtkWidget
*)menuitem
, user_data
);
2481 on_go_to_time_activate (GtkMenuItem
*menuitem
,
2484 go_to_time((GtkWidget
*)menuitem
, user_data
);
2489 on_show_time_frame_activate (GtkMenuItem
*menuitem
,
2492 show_time_frame((GtkWidget
*)menuitem
, user_data
);
2497 on_move_viewer_up_activate (GtkMenuItem
*menuitem
,
2500 move_up_viewer((GtkWidget
*)menuitem
, user_data
);
2505 on_move_viewer_down_activate (GtkMenuItem
*menuitem
,
2508 move_down_viewer((GtkWidget
*)menuitem
, user_data
);
2513 on_remove_viewer_activate (GtkMenuItem
*menuitem
,
2516 delete_viewer((GtkWidget
*)menuitem
, user_data
);
2520 on_trace_facility_activate (GtkMenuItem
*menuitem
,
2523 g_info("Trace facility selector: %s\n", "");
2527 /* Dispaly a file selection dialogue to let user select a library, then call
2528 * lttv_library_load().
2532 on_load_library_activate (GtkMenuItem
*menuitem
,
2535 GError
*error
= NULL
;
2536 MainWindow
* mw_data
= get_window_data_struct((GtkWidget
*)menuitem
);
2538 gchar load_module_path_alter
[PATH_MAX
];
2542 gchar
*load_module_path
;
2543 name
= g_ptr_array_new();
2544 nb
= lttv_library_path_number();
2545 /* ask for the library path */
2549 path
= lttv_library_path_get(i
);
2550 g_ptr_array_add(name
, path
);
2553 load_module_path
= get_selection(mw_data
,
2554 (char **)(name
->pdata
), name
->len
,
2555 "Select a library path", "Library paths");
2556 if(load_module_path
!= NULL
)
2557 strncpy(load_module_path_alter
, load_module_path
, PATH_MAX
-1); // -1 for /
2559 g_ptr_array_free(name
, TRUE
);
2561 if(load_module_path
== NULL
) return;
2565 /* Make sure the module path ends with a / */
2566 gchar
*ptr
= load_module_path_alter
;
2568 ptr
= strchr(ptr
, '\0');
2570 if(*(ptr
-1) != '/') {
2577 /* Ask for the library to load : list files in the previously selected
2579 gchar str
[PATH_MAX
];
2582 GtkFileSelection
* file_selector
=
2583 (GtkFileSelection
*)gtk_file_selection_new("Select a module");
2584 gtk_file_selection_set_filename(file_selector
, load_module_path_alter
);
2585 gtk_file_selection_hide_fileop_buttons(file_selector
);
2587 gtk_window_set_transient_for(GTK_WINDOW(file_selector
),
2588 GTK_WINDOW(mw_data
->mwindow
));
2591 id
= gtk_dialog_run(GTK_DIALOG(file_selector
));
2593 case GTK_RESPONSE_ACCEPT
:
2594 case GTK_RESPONSE_OK
:
2595 dir
= gtk_file_selection_get_selections (file_selector
);
2596 strncpy(str
,dir
[0],PATH_MAX
);
2597 strncpy(remember_plugins_dir
,dir
[0],PATH_MAX
);
2598 /* only keep file name */
2600 str1
= strrchr(str
,'/');
2603 str1
= strrchr(str
,'\\');
2608 if(*str1
== 'l' && *(str1
+1)== 'i' && *(str1
+2)=='b')
2610 remove info after
. */
2614 str2
= strrchr(str2
, '.');
2615 if(str2
!= NULL
) *str2
= '\0';
2617 lttv_module_require(str1
, &error
);
2619 lttv_library_load(str1
, &error
);
2620 if(error
!= NULL
) g_warning("%s", error
->message
);
2621 else g_info("Load library: %s\n", str
);
2623 case GTK_RESPONSE_REJECT
:
2624 case GTK_RESPONSE_CANCEL
:
2626 gtk_widget_destroy((GtkWidget
*)file_selector
);
2637 /* Display all loaded modules, let user to select a module to unload
2638 * by calling lttv_module_unload
2642 on_unload_library_activate (GtkMenuItem
*menuitem
,
2645 MainWindow
* mw_data
= get_window_data_struct((GtkWidget
*)menuitem
);
2647 LttvLibrary
*library
= NULL
;
2652 name
= g_ptr_array_new();
2653 nb
= lttv_library_number();
2654 LttvLibraryInfo
*lib_info
= g_new(LttvLibraryInfo
,nb
);
2655 /* ask for the library name */
2658 LttvLibrary
*iter_lib
= lttv_library_get(i
);
2659 lttv_library_info(iter_lib
, &lib_info
[i
]);
2661 gchar
*path
= lib_info
[i
].name
;
2662 g_ptr_array_add(name
, path
);
2664 lib_name
= get_selection(mw_data
, (char **)(name
->pdata
), name
->len
,
2665 "Select a library", "Libraries");
2666 if(lib_name
!= NULL
) {
2668 if(strcmp(lib_name
, lib_info
[i
].name
) == 0) {
2669 library
= lttv_library_get(i
);
2674 g_ptr_array_free(name
, TRUE
);
2677 if(lib_name
== NULL
) return;
2679 if(library
!= NULL
) lttv_library_unload(library
);
2683 /* Dispaly a file selection dialogue to let user select a module, then call
2684 * lttv_module_require().
2688 on_load_module_activate (GtkMenuItem
*menuitem
,
2691 GError
*error
= NULL
;
2692 MainWindow
* mw_data
= get_window_data_struct((GtkWidget
*)menuitem
);
2694 LttvLibrary
*library
= NULL
;
2699 name
= g_ptr_array_new();
2700 nb
= lttv_library_number();
2701 LttvLibraryInfo
*lib_info
= g_new(LttvLibraryInfo
,nb
);
2702 /* ask for the library name */
2705 LttvLibrary
*iter_lib
= lttv_library_get(i
);
2706 lttv_library_info(iter_lib
, &lib_info
[i
]);
2708 gchar
*path
= lib_info
[i
].name
;
2709 g_ptr_array_add(name
, path
);
2711 lib_name
= get_selection(mw_data
,(char **)(name
->pdata
), name
->len
,
2712 "Select a library", "Libraries");
2713 if(lib_name
!= NULL
) {
2715 if(strcmp(lib_name
, lib_info
[i
].name
) == 0) {
2716 library
= lttv_library_get(i
);
2721 g_ptr_array_free(name
, TRUE
);
2724 if(lib_name
== NULL
) return;
2727 //LttvModule *module;
2728 gchar module_name_out
[PATH_MAX
];
2730 /* Ask for the module to load : list modules in the selected lib */
2734 nb
= lttv_library_module_number(library
);
2735 LttvModuleInfo
*module_info
= g_new(LttvModuleInfo
,nb
);
2736 name
= g_ptr_array_new();
2737 /* ask for the module name */
2740 LttvModule
*iter_module
= lttv_library_module_get(library
, i
);
2741 lttv_module_info(iter_module
, &module_info
[i
]);
2743 gchar
*path
= module_info
[i
].name
;
2744 g_ptr_array_add(name
, path
);
2746 module_name
= get_selection(mw_data
, (char **)(name
->pdata
), name
->len
,
2747 "Select a module", "Modules");
2748 if(module_name
!= NULL
) {
2750 if(strcmp(module_name
, module_info
[i
].name
) == 0) {
2751 strncpy(module_name_out
, module_name
, PATH_MAX
);
2752 //module = lttv_library_module_get(i);
2758 g_ptr_array_free(name
, TRUE
);
2759 g_free(module_info
);
2761 if(module_name
== NULL
) return;
2764 lttv_module_require(module_name_out
, &error
);
2765 if(error
!= NULL
) g_warning("%s", error
->message
);
2766 else g_info("Load module: %s", module_name_out
);
2773 gchar str
[PATH_MAX
];
2776 GtkFileSelection
* file_selector
=
2777 (GtkFileSelection
*)gtk_file_selection_new("Select a module");
2778 gtk_file_selection_set_filename(file_selector
, load_module_path_alter
);
2779 gtk_file_selection_hide_fileop_buttons(file_selector
);
2782 id
= gtk_dialog_run(GTK_DIALOG(file_selector
));
2784 case GTK_RESPONSE_ACCEPT
:
2785 case GTK_RESPONSE_OK
:
2786 dir
= gtk_file_selection_get_selections (file_selector
);
2787 strncpy(str
,dir
[0],PATH_MAX
);
2788 strncpy(remember_plugins_dir
,dir
[0],PATH_MAX
);
2790 /* only keep file name */
2792 str1
= strrchr(str
,'/');
2795 str1
= strrchr(str
,'\\');
2800 if(*str1
== 'l' && *(str1
+1)== 'i' && *(str1
+2)=='b')
2802 remove info after
. */
2806 str2
= strrchr(str2
, '.');
2807 if(str2
!= NULL
) *str2
= '\0';
2809 lttv_module_require(str1
, &error
);
2811 lttv_library_load(str1
, &error
);
2812 if(error
!= NULL
) g_warning(error
->message
);
2813 else g_info("Load library: %s\n", str
);
2815 case GTK_RESPONSE_REJECT
:
2816 case GTK_RESPONSE_CANCEL
:
2818 gtk_widget_destroy((GtkWidget
*)file_selector
);
2830 /* Display all loaded modules, let user to select a module to unload
2831 * by calling lttv_module_unload
2835 on_unload_module_activate (GtkMenuItem
*menuitem
,
2838 MainWindow
* mw_data
= get_window_data_struct((GtkWidget
*)menuitem
);
2840 LttvLibrary
*library
= NULL
;
2845 name
= g_ptr_array_new();
2846 nb
= lttv_library_number();
2847 LttvLibraryInfo
*lib_info
= g_new(LttvLibraryInfo
,nb
);
2848 /* ask for the library name */
2851 LttvLibrary
*iter_lib
= lttv_library_get(i
);
2852 lttv_library_info(iter_lib
, &lib_info
[i
]);
2854 gchar
*path
= lib_info
[i
].name
;
2855 g_ptr_array_add(name
, path
);
2857 lib_name
= get_selection(mw_data
, (char **)(name
->pdata
), name
->len
,
2858 "Select a library", "Libraries");
2859 if(lib_name
!= NULL
) {
2861 if(strcmp(lib_name
, lib_info
[i
].name
) == 0) {
2862 library
= lttv_library_get(i
);
2867 g_ptr_array_free(name
, TRUE
);
2870 if(lib_name
== NULL
) return;
2873 LttvModule
*module
= NULL
;
2875 /* Ask for the module to load : list modules in the selected lib */
2879 nb
= lttv_library_module_number(library
);
2880 LttvModuleInfo
*module_info
= g_new(LttvModuleInfo
,nb
);
2881 name
= g_ptr_array_new();
2882 /* ask for the module name */
2885 LttvModule
*iter_module
= lttv_library_module_get(library
, i
);
2886 lttv_module_info(iter_module
, &module_info
[i
]);
2888 gchar
*path
= module_info
[i
].name
;
2889 if(module_info
[i
].use_count
> 0) g_ptr_array_add(name
, path
);
2891 module_name
= get_selection(mw_data
, (char **)(name
->pdata
), name
->len
,
2892 "Select a module", "Modules");
2893 if(module_name
!= NULL
) {
2895 if(strcmp(module_name
, module_info
[i
].name
) == 0) {
2896 module
= lttv_library_module_get(library
, i
);
2902 g_ptr_array_free(name
, TRUE
);
2903 g_free(module_info
);
2905 if(module_name
== NULL
) return;
2908 LttvModuleInfo module_info
;
2909 lttv_module_info(module
, &module_info
);
2910 g_info("Release module: %s\n", module_info
.name
);
2912 lttv_module_release(module
);
2916 /* Display a directory dialogue to let user select a path for library searching
2920 on_add_library_search_path_activate (GtkMenuItem
*menuitem
,
2923 MainWindow
* mw_data
= get_window_data_struct((GtkWidget
*)menuitem
);
2924 //GtkDirSelection * file_selector = (GtkDirSelection *)gtk_dir_selection_new("Select library path");
2925 GtkFileSelection
* file_selector
= (GtkFileSelection
*)gtk_file_selection_new("Select a trace");
2926 gtk_widget_hide( (file_selector
)->file_list
->parent
) ;
2928 gtk_window_set_transient_for(GTK_WINDOW(file_selector
),
2929 GTK_WINDOW(mw_data
->mwindow
));
2934 if(remember_plugins_dir
[0] != '\0')
2935 gtk_file_selection_set_filename(file_selector
, remember_plugins_dir
);
2937 id
= gtk_dialog_run(GTK_DIALOG(file_selector
));
2939 case GTK_RESPONSE_ACCEPT
:
2940 case GTK_RESPONSE_OK
:
2941 dir
= gtk_file_selection_get_filename (file_selector
);
2942 strncpy(remember_plugins_dir
,dir
,PATH_MAX
);
2943 strncat(remember_plugins_dir
,"/",PATH_MAX
);
2944 lttv_library_path_add(dir
);
2945 case GTK_RESPONSE_REJECT
:
2946 case GTK_RESPONSE_CANCEL
:
2948 gtk_widget_destroy((GtkWidget
*)file_selector
);
2954 /* Display a directory dialogue to let user select a path for library searching
2958 on_remove_library_search_path_activate (GtkMenuItem
*menuitem
,
2961 MainWindow
* mw_data
= get_window_data_struct((GtkWidget
*)menuitem
);
2963 const char *lib_path
;
2967 name
= g_ptr_array_new();
2968 nb
= lttv_library_path_number();
2969 /* ask for the library name */
2972 gchar
*path
= lttv_library_path_get(i
);
2973 g_ptr_array_add(name
, path
);
2975 lib_path
= get_selection(mw_data
, (char **)(name
->pdata
), name
->len
,
2976 "Select a library path", "Library paths");
2978 g_ptr_array_free(name
, TRUE
);
2980 if(lib_path
== NULL
) return;
2983 lttv_library_path_remove(lib_path
);
2987 on_color_activate (GtkMenuItem
*menuitem
,
2995 on_save_configuration_activate (GtkMenuItem
*menuitem
,
2998 g_info("Save configuration\n");
3003 on_content_activate (GtkMenuItem
*menuitem
,
3006 char* filename
= NULL
,
3009 const char* relativePath
= "doc/user/user_guide/html/index.html";
3010 filename
= g_build_filename (g_get_current_dir(), relativePath
, NULL
);
3011 path
= g_strdup_printf ("ghelp://%s", filename
);
3013 screen
= gdk_screen_get_default();
3014 gtk_show_uri (screen
, path
, gtk_get_current_event_time(), NULL
);
3018 g_info("Content\n");
3023 on_about_close_activate (GtkButton
*button
,
3026 GtkWidget
*about_widget
= GTK_WIDGET(user_data
);
3028 gtk_widget_destroy(about_widget
);
3032 on_about_activate (GtkMenuItem
*menuitem
,
3035 MainWindow
*main_window
= get_window_data_struct(GTK_WIDGET(menuitem
));
3036 GtkWidget
*window_widget
= main_window
->mwindow
;
3037 GtkWidget
*about_widget
= gtk_window_new(GTK_WINDOW_TOPLEVEL
);
3038 GtkWindow
*about_window
= GTK_WINDOW(about_widget
);
3040 gtk_window_set_title(about_window
, "About Linux Trace Toolkit");
3042 gtk_window_set_resizable(about_window
, FALSE
);
3043 gtk_window_set_transient_for(about_window
, GTK_WINDOW(window_widget
));
3044 gtk_window_set_destroy_with_parent(about_window
, TRUE
);
3045 gtk_window_set_modal(about_window
, FALSE
);
3047 /* Put the about window at the center of the screen */
3048 gtk_window_set_position(about_window
, GTK_WIN_POS_CENTER_ALWAYS
);
3050 GtkWidget
*vbox
= gtk_vbox_new(FALSE
, 1);
3052 gtk_container_add(GTK_CONTAINER(about_widget
), vbox
);
3055 GtkWidget
*label1
= gtk_label_new("");
3056 gtk_misc_set_padding(GTK_MISC(label1
), 10, 20);
3057 gtk_label_set_markup(GTK_LABEL(label1
), "\
3058 <big>Linux Trace Toolkit " VERSION
"</big>");
3059 gtk_label_set_justify(GTK_LABEL(label1
), GTK_JUSTIFY_CENTER
);
3061 GtkWidget
*label2
= gtk_label_new("");
3062 gtk_misc_set_padding(GTK_MISC(label2
), 10, 20);
3063 gtk_label_set_markup(GTK_LABEL(label2
), "\
3066 Michel Dagenais (New trace format, lttv main)\n\
3067 Mathieu Desnoyers (Kernel Tracer, Directory structure, build with automake/conf,\n\
3068 lttv gui, control flow view, gui cooperative trace reading\n\
3069 scheduler with interruptible foreground and background\n\
3070 computation, detailed event list (rewrite), trace reading\n\
3071 library (rewrite))\n\
3072 Benoit Des Ligneris, Eric Clement (Cluster adaptation, work in progress)\n\
3073 Xang-Xiu Yang (new trace reading library and converter, lttv gui, \n\
3074 detailed event list and statistics view)\n\
3075 Tom Zanussi (RelayFS)\n\
3077 Inspired from the original Linux Trace Toolkit Visualizer made by\n\
3080 GtkWidget
*label3
= gtk_label_new("");
3081 gtk_label_set_markup(GTK_LABEL(label3
), "\
3082 Linux Trace Toolkit Viewer, Copyright (C) 2004, 2005, 2006\n\
3084 Mathieu Desnoyers\n\
3086 Linux Trace Toolkit comes with ABSOLUTELY NO WARRANTY.\n\
3087 This is free software, and you are welcome to redistribute it\n\
3088 under certain conditions. See COPYING for details.");
3089 gtk_misc_set_padding(GTK_MISC(label3
), 10, 20);
3091 gtk_box_pack_start_defaults(GTK_BOX(vbox
), label1
);
3092 gtk_box_pack_start_defaults(GTK_BOX(vbox
), label2
);
3093 gtk_box_pack_start_defaults(GTK_BOX(vbox
), label3
);
3095 GtkWidget
*hbox
= gtk_hbox_new(TRUE
, 0);
3096 gtk_box_pack_end(GTK_BOX(vbox
), hbox
, FALSE
, FALSE
, 0);
3097 GtkWidget
*close_button
= gtk_button_new_with_mnemonic("_Close");
3098 gtk_box_pack_end(GTK_BOX(hbox
), close_button
, FALSE
, FALSE
, 0);
3099 gtk_container_set_border_width(GTK_CONTAINER(close_button
), 20);
3101 g_signal_connect(G_OBJECT(close_button
), "clicked",
3102 G_CALLBACK(on_about_close_activate
),
3103 (gpointer
)about_widget
);
3105 gtk_widget_show_all(about_widget
);
3110 on_button_new_clicked (GtkButton
*button
,
3113 create_new_window((GtkWidget
*)button
, user_data
, TRUE
);
3117 on_button_new_tab_clicked (GtkButton
*button
,
3120 create_new_tab((GtkWidget
*)button
, user_data
);
3124 on_button_open_clicked (GtkButton
*button
,
3127 #ifdef UNFINISHED_FEATURE
3128 open_traceset((GtkWidget
*)button
, user_data
);
3134 on_button_add_trace_clicked (GtkButton
*button
,
3137 add_trace((GtkWidget
*)button
, user_data
);
3142 on_button_remove_trace_clicked (GtkButton
*button
,
3145 remove_trace((GtkWidget
*)button
, user_data
);
3149 on_button_redraw_clicked (GtkButton
*button
,
3152 redraw((GtkWidget
*)button
, user_data
);
3156 on_button_continue_processing_clicked (GtkButton
*button
,
3159 continue_processing((GtkWidget
*)button
, user_data
);
3163 on_button_stop_processing_clicked (GtkButton
*button
,
3166 stop_processing((GtkWidget
*)button
, user_data
);
3172 on_button_save_clicked (GtkButton
*button
,
3175 save((GtkWidget
*)button
, user_data
);
3180 on_button_save_as_clicked (GtkButton
*button
,
3183 save_as((GtkWidget
*)button
, user_data
);
3188 on_button_zoom_in_clicked (GtkButton
*button
,
3191 zoom_in((GtkWidget
*)button
, user_data
);
3196 on_button_zoom_out_clicked (GtkButton
*button
,
3199 zoom_out((GtkWidget
*)button
, user_data
);
3204 on_button_zoom_extended_clicked (GtkButton
*button
,
3207 zoom_extended((GtkWidget
*)button
, user_data
);
3212 on_button_go_to_time_clicked (GtkButton
*button
,
3215 go_to_time((GtkWidget
*)button
, user_data
);
3220 on_button_show_time_frame_clicked (GtkButton
*button
,
3223 show_time_frame((GtkWidget
*)button
, user_data
);
3228 on_button_move_up_clicked (GtkButton
*button
,
3231 move_up_viewer((GtkWidget
*)button
, user_data
);
3236 on_button_move_down_clicked (GtkButton
*button
,
3239 move_down_viewer((GtkWidget
*)button
, user_data
);
3244 on_button_delete_viewer_clicked (GtkButton
*button
,
3247 delete_viewer((GtkWidget
*)button
, user_data
);
3251 on_MWindow_destroy (GtkWidget
*widget
,
3254 MainWindow
*main_window
= get_window_data_struct(widget
);
3255 LttvIAttribute
*attributes
= main_window
->attributes
;
3256 LttvAttributeValue value
;
3259 //This is unnecessary, since widgets will be destroyed
3260 //by the main window widget anyway.
3261 //remove_all_menu_toolbar_constructors(main_window, NULL);
3263 retval
= lttv_iattribute_find_by_path(attributes
, "viewers/menu",
3264 LTTV_POINTER
, &value
);
3266 lttv_menus_destroy((LttvMenus
*)*(value
.v_pointer
));
3268 retval
= lttv_iattribute_find_by_path(attributes
, "viewers/toolbar",
3269 LTTV_POINTER
, &value
);
3271 lttv_toolbars_destroy((LttvToolbars
*)*(value
.v_pointer
));
3273 g_object_unref(main_window
->attributes
);
3274 g_main_window_list
= g_slist_remove(g_main_window_list
, main_window
);
3276 g_info("There are now : %d windows\n",g_slist_length(g_main_window_list
));
3277 if(g_slist_length(g_main_window_list
) == 0)
3282 on_MWindow_configure (GtkWidget
*widget
,
3283 GdkEventConfigure
*event
,
3286 // MD : removed time width modification upon resizing of the main window.
3287 // The viewers will redraw themselves completely, without time interval
3290 if(mw_data->window_width){
3291 time_span = LTTV_TRACESET_CONTEXT(tab->traceset_info->traceset_context)->Time_Span ;
3292 time_win = tab->time_window;
3293 ratio = width / mw_data->window_width;
3294 tab->time_window.time_width = ltt_time_mul(time_win.time_width,ratio);
3295 time = ltt_time_sub(time_span->endTime, time_win.start_time);
3296 if(ltt_time_compare(time, tab->time_window.time_width) < 0){
3297 tab->time_window.time_width = time;
3303 mw_data->window_width = (int)width;
3312 on_MNotebook_switch_page (GtkNotebook
*notebook
,
3313 GtkNotebookPage
*page
,
3321 void time_change_manager (Tab
*tab
,
3322 TimeWindow new_time_window
)
3325 /* Only one source of time change */
3326 if(tab
->time_manager_lock
== TRUE
) return;
3328 tab
->time_manager_lock
= TRUE
;
3329 TimeInterval time_span
;
3331 LttvTraceset
*ts
= tab
->traceset_info
->traceset
;
3332 time_span
.start_time
=ltt_time_from_uint64( lttv_traceset_get_timestamp_begin(ts
));
3333 time_span
.end_time
= ltt_time_from_uint64(lttv_traceset_get_timestamp_end(ts
));
3336 LttTime start_time
= new_time_window
.start_time
;
3337 LttTime end_time
= new_time_window
.end_time
;
3339 g_assert(ltt_time_compare(start_time
, end_time
) < 0);
3342 GtkAdjustment
*adjustment
= gtk_range_get_adjustment(GTK_RANGE(tab
->scrollbar
));
3343 LttTime upper
= ltt_time_sub(time_span
.end_time
, time_span
.start_time
);
3346 gtk_range_set_increments(GTK_RANGE(tab
->scrollbar
),
3347 ltt_time_to_double(new_time_window
.time_width
)
3348 / SCROLL_STEP_PER_PAGE
3349 * NANOSECONDS_PER_SECOND
, /* step increment */
3350 ltt_time_to_double(new_time_window
.time_width
)
3351 * NANOSECONDS_PER_SECOND
); /* page increment */
3352 gtk_range_set_range(GTK_RANGE(tab
->scrollbar
),
3354 ltt_time_to_double(upper
)
3355 * NANOSECONDS_PER_SECOND
); /* upper */
3357 g_object_set(G_OBJECT(adjustment
),
3361 ltt_time_to_double(upper
), /* upper */
3363 new_time_window
.time_width_double
3364 / SCROLL_STEP_PER_PAGE
, /* step increment */
3366 new_time_window
.time_width_double
,
3367 /* page increment */
3369 new_time_window
.time_width_double
, /* page size */
3371 gtk_adjustment_changed(adjustment
);
3373 // g_object_set(G_OBJECT(adjustment),
3375 // ltt_time_to_double(
3376 // ltt_time_sub(start_time, time_span.start_time))
3379 //gtk_adjustment_value_changed(adjustment);
3380 gtk_range_set_value(GTK_RANGE(tab
->scrollbar
),
3382 ltt_time_sub(start_time
, time_span
.start_time
)) /* value */);
3384 /* set the time bar. */
3387 timebar_set_minmax_time(TIMEBAR(tab
->MTimebar
),
3388 &time_span
.start_time
,
3389 &time_span
.end_time
);
3390 timebar_set_start_time(TIMEBAR(tab
->MTimebar
),&start_time
);
3391 timebar_set_end_time(TIMEBAR(tab
->MTimebar
),&end_time
);
3395 /* call viewer hooks for new time window */
3396 set_time_window(tab
, &new_time_window
);
3398 tab
->time_manager_lock
= FALSE
;
3407 void current_time_change_manager (Tab
*tab
,
3408 LttTime new_current_time
)
3410 /* Only one source of time change */
3411 if(tab
->current_time_manager_lock
== TRUE
) return;
3413 tab
->current_time_manager_lock
= TRUE
;
3415 timebar_set_current_time(TIMEBAR(tab
->MTimebar
), &new_current_time
);
3417 set_current_time(tab
, &new_current_time
);
3419 tab
->current_time_manager_lock
= FALSE
;
3422 void current_position_change_manager(Tab
*tab
, LttvTracesetPosition
*pos
)
3424 lttv_traceset_seek_to_position( pos
);
3426 LttTime new_time
= lttv_traceset_position_get_time(pos
);
3427 /* Put the context in a state coherent position */
3429 lttv_state_traceset_seek_time_closest(tab
->traceset_info
->traceset
, ltt_time_zero
);
3431 current_time_change_manager(tab
, new_time
);
3433 set_current_position(tab
, pos
);
3436 static void on_timebar_starttime_changed(Timebar
*timebar
,
3439 Tab
*tab
= (Tab
*)user_data
;
3440 LttvTraceset
* ts
=tab
->traceset_info
->traceset
;
3441 TimeInterval time_span
= lttv_traceset_get_time_span(ts
);
3443 TimeWindow new_time_window
= tab
->time_window
;
3444 new_time_window
.start_time
= timebar_get_start_time(timebar
);
3446 LttTime end_time
= new_time_window
.end_time
;
3448 /* TODO ybrosseau 2010-12-02: This if should have been checked
3449 by the timebar already */
3450 if(ltt_time_compare(new_time_window
.start_time
, end_time
) >= 0) {
3451 /* Then, we must push back end time : keep the same time width
3452 * if possible, else end traceset time */
3453 end_time
= LTT_TIME_MIN(ltt_time_add(new_time_window
.start_time
,
3454 new_time_window
.time_width
),
3455 time_span
.end_time
);
3458 /* Fix the time width to fit start time and end time */
3459 new_time_window
.time_width
= ltt_time_sub(end_time
,
3460 new_time_window
.start_time
);
3462 new_time_window
.time_width_double
=
3463 ltt_time_to_double(new_time_window
.time_width
);
3465 new_time_window
.end_time
= end_time
;
3467 /* Notify the time_manager */
3468 time_change_manager(tab
, new_time_window
);
3472 static void on_timebar_endtime_changed(Timebar
*timebar
,
3475 Tab
*tab
= (Tab
*)user_data
;
3476 LttvTraceset
* ts
=tab
->traceset_info
->traceset
;
3477 TimeInterval time_span
= lttv_traceset_get_time_span(ts
);
3479 TimeWindow new_time_window
= tab
->time_window
;
3481 LttTime end_time
= timebar_get_end_time(timebar
);
3483 /* TODO ybrosseau 2010-12-02: This if should have been
3484 checked by the timebar already */
3485 if(ltt_time_compare(new_time_window
.start_time
, end_time
) >= 0) {
3486 /* Then, we must push front start time : keep the same time
3487 width if possible, else end traceset time */
3488 new_time_window
.start_time
= LTT_TIME_MAX(
3489 ltt_time_sub(end_time
,
3490 new_time_window
.time_width
),
3491 time_span
.start_time
);
3494 /* Fix the time width to fit start time and end time */
3495 new_time_window
.time_width
= ltt_time_sub(end_time
,
3496 new_time_window
.start_time
);
3498 new_time_window
.time_width_double
=
3499 ltt_time_to_double(new_time_window
.time_width
);
3501 new_time_window
.end_time
= end_time
;
3503 /* Notify the time_manager */
3504 time_change_manager(tab
, new_time_window
);
3506 static void on_timebar_currenttime_changed(Timebar
*timebar
,
3509 Tab
*tab
= (Tab
*)user_data
;
3511 LttTime new_current_time
= timebar_get_current_time(timebar
);
3513 current_time_change_manager(tab
, new_current_time
);
3516 void scroll_value_changed_cb(GtkWidget
*scrollbar
,
3519 Tab
*tab
= (Tab
*)user_data
;
3520 TimeWindow new_time_window
;
3522 GtkAdjustment
*adjust
= gtk_range_get_adjustment(GTK_RANGE(scrollbar
));
3523 gdouble value
= gtk_adjustment_get_value(adjust
);
3524 // gdouble upper, lower, ratio, page_size;
3527 LttvTraceset
* ts
= tab
->traceset_info
->traceset
;
3528 TimeInterval time_span
= lttv_traceset_get_time_span(ts
);
3530 time
= ltt_time_add(ltt_time_from_double(value
),
3531 time_span
.start_time
);
3533 new_time_window
.start_time
= time
;
3535 page_size
= adjust
->page_size
;
3537 new_time_window
.time_width
=
3538 ltt_time_from_double(page_size
);
3540 new_time_window
.time_width_double
=
3543 new_time_window
.end_time
= ltt_time_add(new_time_window
.start_time
,
3544 new_time_window
.time_width
);
3547 time_change_manager(tab
, new_time_window
);
3550 //time_window = tab->time_window;
3552 lower
= adjust
->lower
;
3553 upper
= adjust
->upper
;
3554 ratio
= (value
- lower
) / (upper
- lower
);
3555 g_info("lower %lu, upper %lu, value %lu, ratio %lu", lower
, upper
, value
, ratio
);
3557 //time = ltt_time_sub(time_span->end_time, time_span->start_time);
3558 //time = ltt_time_mul(time, (float)ratio);
3559 //time = ltt_time_add(time_span->start_time, time);
3560 time
= ltt_time_add(ltt_time_from_double(value
),
3561 time_span
.start_time
);
3563 time_window
.start_time
= time
;
3565 page_size
= adjust
->page_size
;
3567 time_window
.time_width
=
3568 ltt_time_from_double(page_size
);
3569 //time = ltt_time_sub(time_span.end_time, time);
3570 //if(ltt_time_compare(time,time_window.time_width) < 0){
3571 // time_window.time_width = time;
3574 /* call viewer hooks for new time window */
3575 set_time_window(tab
, &time_window
);
3581 /* Display a dialogue showing all eventtypes and traces, let user to select the interested
3582 * eventtypes, tracefiles and traces (filter)
3585 /* Select a trace which will be removed from traceset
3588 char * get_remove_trace(MainWindow
*mw_data
,
3589 char ** all_trace_name
, int nb_trace
)
3591 return get_selection(mw_data
, all_trace_name
, nb_trace
,
3592 "Select a trace", "Trace pathname");
3596 /* Select a module which will be loaded
3599 char * get_load_module(MainWindow
*mw_data
,
3600 char ** load_module_name
, int nb_module
)
3602 return get_selection(mw_data
, load_module_name
, nb_module
,
3603 "Select a module to load", "Module name");
3609 /* Select a module which will be unloaded
3612 char * get_unload_module(MainWindow
*mw_data
,
3613 char ** loaded_module_name
, int nb_module
)
3615 return get_selection(mw_data
, loaded_module_name
, nb_module
,
3616 "Select a module to unload", "Module name");
3620 /* Display a dialogue which shows all selectable items, let user to
3621 * select one of them
3624 char * get_selection(MainWindow
*mw_data
,
3625 char ** loaded_module_name
, int nb_module
,
3626 char *title
, char * column_title
)
3628 GtkWidget
* dialogue
;
3629 GtkWidget
* scroll_win
;
3631 GtkListStore
* store
;
3632 GtkTreeViewColumn
* column
;
3633 GtkCellRenderer
* renderer
;
3634 GtkTreeSelection
* select
;
3637 char * unload_module_name
= NULL
;
3639 dialogue
= gtk_dialog_new_with_buttons(title
,
3642 GTK_STOCK_OK
,GTK_RESPONSE_ACCEPT
,
3643 GTK_STOCK_CANCEL
,GTK_RESPONSE_REJECT
,
3645 gtk_window_set_default_size((GtkWindow
*)dialogue
, 500, 200);
3646 gtk_window_set_transient_for(GTK_WINDOW(dialogue
),
3647 GTK_WINDOW(mw_data
->mwindow
));
3649 scroll_win
= gtk_scrolled_window_new (NULL
, NULL
);
3650 gtk_widget_show ( scroll_win
);
3651 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll_win
),
3652 GTK_POLICY_AUTOMATIC
, GTK_POLICY_AUTOMATIC
);
3654 store
= gtk_list_store_new (N_COLUMNS
,G_TYPE_STRING
);
3655 tree
= gtk_tree_view_new_with_model(GTK_TREE_MODEL (store
));
3656 gtk_widget_show ( tree
);
3657 g_object_unref (G_OBJECT (store
));
3659 renderer
= gtk_cell_renderer_text_new ();
3660 column
= gtk_tree_view_column_new_with_attributes (column_title
,
3662 "text", MODULE_COLUMN
,
3664 gtk_tree_view_column_set_alignment (column
, 0.5);
3665 gtk_tree_view_column_set_fixed_width (column
, 150);
3666 gtk_tree_view_append_column (GTK_TREE_VIEW (tree
), column
);
3668 select
= gtk_tree_view_get_selection (GTK_TREE_VIEW (tree
));
3669 gtk_tree_selection_set_mode (select
, GTK_SELECTION_SINGLE
);
3671 gtk_container_add (GTK_CONTAINER (scroll_win
), tree
);
3673 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialogue
)->vbox
), scroll_win
,TRUE
, TRUE
,0);
3675 for(i
=0;i
<nb_module
;i
++){
3676 gtk_list_store_append (store
, &iter
);
3677 gtk_list_store_set (store
, &iter
, MODULE_COLUMN
,loaded_module_name
[i
],-1);
3680 id
= gtk_dialog_run(GTK_DIALOG(dialogue
));
3681 GtkTreeModel
**store_model
= (GtkTreeModel
**)&store
;
3683 case GTK_RESPONSE_ACCEPT
:
3684 case GTK_RESPONSE_OK
:
3685 if (gtk_tree_selection_get_selected (select
, store_model
, &iter
)){
3686 gtk_tree_model_get ((GtkTreeModel
*)store
, &iter
, MODULE_COLUMN
, &unload_module_name
, -1);
3688 case GTK_RESPONSE_REJECT
:
3689 case GTK_RESPONSE_CANCEL
:
3691 gtk_widget_destroy(dialogue
);
3695 return unload_module_name
;
3699 /* Insert all menu entry and tool buttons into this main window
3704 void add_all_menu_toolbar_constructors(MainWindow
* mw
, gpointer user_data
)
3708 lttvwindow_viewer_constructor constructor
;
3709 LttvMenus
* global_menu
, * instance_menu
;
3710 LttvToolbars
* global_toolbar
, * instance_toolbar
;
3711 LttvMenuClosure
*menu_item
;
3712 LttvToolbarClosure
*toolbar_item
;
3713 LttvAttributeValue value
;
3714 LttvIAttribute
*global_attributes
= LTTV_IATTRIBUTE(lttv_global_attributes());
3715 LttvIAttribute
*attributes
= mw
->attributes
;
3716 GtkWidget
* tool_menu_title_menu
, *new_widget
, *pixmap
;
3719 retval
= lttv_iattribute_find_by_path(global_attributes
, "viewers/menu",
3720 LTTV_POINTER
, &value
);
3722 if(*(value
.v_pointer
) == NULL
)
3723 *(value
.v_pointer
) = lttv_menus_new();
3724 global_menu
= (LttvMenus
*)*(value
.v_pointer
);
3726 retval
= lttv_iattribute_find_by_path(attributes
, "viewers/menu",
3727 LTTV_POINTER
, &value
);
3729 if(*(value
.v_pointer
) == NULL
)
3730 *(value
.v_pointer
) = lttv_menus_new();
3731 instance_menu
= (LttvMenus
*)*(value
.v_pointer
);
3733 retval
= lttv_iattribute_find_by_path(global_attributes
, "viewers/toolbar",
3734 LTTV_POINTER
, &value
);
3736 if(*(value
.v_pointer
) == NULL
)
3737 *(value
.v_pointer
) = lttv_toolbars_new();
3738 global_toolbar
= (LttvToolbars
*)*(value
.v_pointer
);
3740 retval
= lttv_iattribute_find_by_path(attributes
, "viewers/toolbar",
3741 LTTV_POINTER
, &value
);
3743 if(*(value
.v_pointer
) == NULL
)
3744 *(value
.v_pointer
) = lttv_toolbars_new();
3745 instance_toolbar
= (LttvToolbars
*)*(value
.v_pointer
);
3747 /* Add missing menu entries to window instance */
3748 for(i
=0;i
<global_menu
->len
;i
++) {
3749 menu_item
= &g_array_index(global_menu
, LttvMenuClosure
, i
);
3751 //add menu_item to window instance;
3752 constructor
= menu_item
->con
;
3753 tool_menu_title_menu
= lookup_widget(mw
->mwindow
,"ToolMenuTitle_menu");
3755 gtk_menu_item_new_with_mnemonic (menu_item
->menu_text
);
3756 gtk_container_add (GTK_CONTAINER (tool_menu_title_menu
),
3758 g_signal_connect ((gpointer
) new_widget
, "activate",
3759 G_CALLBACK (insert_viewer_wrap
),
3761 gtk_widget_show (new_widget
);
3762 lttv_menus_add(instance_menu
, menu_item
->con
,
3763 menu_item
->menu_path
,
3764 menu_item
->menu_text
,
3769 /* Add missing toolbar entries to window instance */
3770 for(i
=0;i
<global_toolbar
->len
;i
++) {
3771 toolbar_item
= &g_array_index(global_toolbar
, LttvToolbarClosure
, i
);
3773 //add toolbar_item to window instance;
3774 constructor
= toolbar_item
->con
;
3775 tool_menu_title_menu
= lookup_widget(mw
->mwindow
,"MToolbar1");
3776 pixbuf
= gdk_pixbuf_new_from_xpm_data((const char**)toolbar_item
->pixmap
);
3777 pixmap
= gtk_image_new_from_pixbuf(pixbuf
);
3779 gtk_toolbar_append_element (GTK_TOOLBAR (tool_menu_title_menu
),
3780 GTK_TOOLBAR_CHILD_BUTTON
,
3783 toolbar_item
->tooltip
, NULL
,
3784 pixmap
, NULL
, NULL
);
3785 gtk_label_set_use_underline(
3786 GTK_LABEL (((GtkToolbarChild
*) (
3787 g_list_last (GTK_TOOLBAR
3788 (tool_menu_title_menu
)->children
)->data
))->label
),
3790 gtk_container_set_border_width (GTK_CONTAINER (new_widget
), 1);
3791 g_signal_connect ((gpointer
) new_widget
,
3793 G_CALLBACK (insert_viewer_wrap
),
3795 gtk_widget_show (new_widget
);
3797 lttv_toolbars_add(instance_toolbar
, toolbar_item
->con
,
3798 toolbar_item
->tooltip
,
3799 toolbar_item
->pixmap
,
3807 /* Create a main window
3810 MainWindow
*construct_main_window(MainWindow
* parent
)
3814 g_debug("construct_main_window()");
3815 GtkWidget
* new_window
; /* New generated main window */
3816 MainWindow
* new_m_window
;/* New main window structure */
3817 GtkNotebook
* notebook
;
3818 LttvIAttribute
*attributes
=
3819 LTTV_IATTRIBUTE(g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
));
3820 LttvAttributeValue value
;
3822 new_m_window
= g_new(MainWindow
, 1);
3824 // Add the object's information to the module's array
3825 g_main_window_list
= g_slist_append(g_main_window_list
, new_m_window
);
3827 new_window
= create_MWindow();
3828 gtk_widget_show (new_window
);
3830 new_m_window
->mwindow
= new_window
;
3831 new_m_window
->attributes
= attributes
;
3833 retval
= lttv_iattribute_find_by_path(attributes
, "viewers/menu",
3834 LTTV_POINTER
, &value
);
3836 *(value
.v_pointer
) = lttv_menus_new();
3838 retval
= lttv_iattribute_find_by_path(attributes
, "viewers/toolbar",
3839 LTTV_POINTER
, &value
);
3841 *(value
.v_pointer
) = lttv_toolbars_new();
3843 add_all_menu_toolbar_constructors(new_m_window
, NULL
);
3845 g_object_set_data_full(G_OBJECT(new_window
),
3847 (gpointer
)new_m_window
,
3848 (GDestroyNotify
)g_free
);
3849 //create a default tab
3850 notebook
= (GtkNotebook
*)lookup_widget(new_m_window
->mwindow
, "MNotebook");
3851 if(notebook
== NULL
){
3852 g_info("Notebook does not exist\n");
3853 /* FIXME : destroy partially created widgets */
3854 g_free(new_m_window
);
3857 //gtk_notebook_popup_enable (GTK_NOTEBOOK(notebook));
3858 //for now there is no name field in LttvTraceset structure
3859 //Use "Traceset" as the label for the default tab
3861 GtkWidget
* parent_notebook
= lookup_widget(parent
->mwindow
, "MNotebook");
3862 GtkWidget
*page
= gtk_notebook_get_nth_page(GTK_NOTEBOOK(parent_notebook
),
3863 gtk_notebook_get_current_page(GTK_NOTEBOOK(parent_notebook
)));
3869 LttvPluginTab
*ptab
;
3870 ptab
= (LttvPluginTab
*)g_object_get_data(G_OBJECT(page
), "Tab_Plugin");
3871 parent_tab
= ptab
->tab
;
3873 LttvPluginTab
*ptab
= g_object_new(LTTV_TYPE_PLUGIN_TAB
, NULL
);
3875 new_m_window
, parent_tab
, notebook
, "Traceset");
3876 ptab
->parent
.top_widget
= ptab
->tab
->top_widget
;
3877 g_object_set_data_full(
3878 G_OBJECT(ptab
->tab
->vbox
),
3881 (GDestroyNotify
)tab_destructor
);
3883 LttvPluginTab
*ptab
= g_object_new(LTTV_TYPE_PLUGIN_TAB
, NULL
);
3884 init_tab(ptab
->tab
, new_m_window
, NULL
, notebook
, "Traceset");
3885 ptab
->parent
.top_widget
= ptab
->tab
->top_widget
;
3886 g_object_set_data_full(
3887 G_OBJECT(ptab
->tab
->vbox
),
3890 (GDestroyNotify
)tab_destructor
);
3893 /* Insert default viewers */
3895 LttvAttributeType type
;
3896 LttvAttributeName name
;
3897 LttvAttributeValue value
;
3898 LttvAttribute
*attribute
;
3900 LttvIAttribute
*attributes_global
=
3901 LTTV_IATTRIBUTE(lttv_global_attributes());
3903 attribute
= LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(
3904 LTTV_IATTRIBUTE(attributes_global
),
3905 LTTV_VIEWER_CONSTRUCTORS
));
3906 g_assert(attribute
);
3908 name
= g_quark_from_string("guievents");
3909 type
= lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(attribute
),
3911 if(type
== LTTV_POINTER
) {
3912 lttvwindow_viewer_constructor viewer_constructor
=
3913 (lttvwindow_viewer_constructor
)*value
.v_pointer
;
3914 insert_viewer(new_window
, viewer_constructor
);
3917 name
= g_quark_from_string("guicontrolflow");
3918 type
= lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(attribute
),
3920 if(type
== LTTV_POINTER
) {
3921 lttvwindow_viewer_constructor viewer_constructor
=
3922 (lttvwindow_viewer_constructor
)*value
.v_pointer
;
3923 insert_viewer(new_window
, viewer_constructor
);
3926 name
= g_quark_from_string("guistatistics");
3927 type
= lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(attribute
),
3929 if(type
== LTTV_POINTER
) {
3930 lttvwindow_viewer_constructor viewer_constructor
=
3931 (lttvwindow_viewer_constructor
)*value
.v_pointer
;
3932 insert_viewer(new_window
, viewer_constructor
);
3936 g_info("There are now : %d windows\n",g_slist_length(g_main_window_list
));
3938 return new_m_window
;
3942 /* Free the memory occupied by a tab structure
3946 void tab_destructor(LttvPluginTab
* ptab
)
3948 #ifdef BABEL_CLEANUP
3949 int i
, nb
, ref_count
;
3951 Tab
*tab
= ptab
->tab
;
3954 g_object_unref(tab
->attributes
);
3956 if(tab
->interrupted_state
)
3957 g_object_unref(tab
->interrupted_state
);
3960 if(tab
->traceset_info
->traceset_context
!= NULL
){
3961 //remove state update hooks
3962 lttv_state_remove_event_hooks(
3963 (LttvTracesetState
*)tab
->traceset_info
->
3965 lttv_context_fini(LTTV_TRACESET_CONTEXT(tab
->traceset_info
->
3967 g_object_unref(tab
->traceset_info
->traceset_context
);
3969 if(tab
->traceset_info
->traceset
!= NULL
) {
3970 nb
= lttv_traceset_number(tab
->traceset_info
->traceset
);
3971 for(i
= 0 ; i
< nb
; i
++) {
3972 trace
= lttv_traceset_get(tab
->traceset_info
->traceset
, i
);
3973 ref_count
= lttv_trace_get_ref_number(trace
);
3975 ltt_trace_close(lttv_trace(trace
));
3979 lttv_traceset_destroy(tab
->traceset_info
->traceset
);
3980 /* Remove the idle events requests processing function of the tab */
3981 g_idle_remove_by_data(tab
);
3983 g_slist_free(tab
->events_requests
);
3984 g_free(tab
->traceset_info
);
3986 g_object_unref(ptab
);
3987 #endif /* BABEL_CLEANUP */
3991 /* Create a tab and insert it into the current main window
3994 void init_tab(Tab
*tab
, MainWindow
* mw
, Tab
*copy_tab
,
3995 GtkNotebook
* notebook
, char * label
)
4000 //LttvFilter *filter = NULL;
4002 //create a new tab data structure
4003 //tab = g_new(Tab,1);
4005 //construct and initialize the traceset_info
4006 tab
->traceset_info
= g_new(TracesetInfo
,1);
4009 tab
->traceset_info
->traceset
=
4010 lttv_traceset_copy(copy_tab
->traceset_info
->traceset
);
4012 /* Copy the previous tab's filter */
4013 /* We can clone the filter, as we copy the trace set also */
4014 /* The filter must always be in sync with the trace set */
4016 #ifdef BABEL_CLEANUP
4017 tab
->filter
= lttv_filter_clone(copy_tab
->filter
);
4018 #endif /* BABEL_CLEANUP */
4020 tab
->traceset_info
->traceset
= lttv_traceset_new();
4025 lttv_attribute_write_xml(
4026 lttv_traceset_attribute(tab
->traceset_info
->traceset
),
4032 tab
->time_manager_lock
= FALSE
;
4033 tab
->current_time_manager_lock
= FALSE
;
4034 #ifdef BABEL_CLEANUP
4035 //FIXME copy not implemented in lower level
4036 tab
->traceset_info
->traceset_context
=
4037 g_object_new(LTTV_TRACESET_STATS_TYPE
, NULL
);
4038 //add state update hooks
4039 #endif //BABEL_CLEANUP
4040 lttv_state_add_event_hooks(
4041 tab
->traceset_info
->traceset
);
4043 //determine the current_time and time_window of the tab
4045 if(copy_tab
!= NULL
){
4046 tab
->time_window
= copy_tab
->time_window
;
4047 tab
->current_time
= copy_tab
->current_time
;
4049 tab
->time_window
.start_time
=
4050 LTTV_TRACESET_CONTEXT(tab
->traceset_info
->traceset_context
)->
4051 time_span
.start_time
;
4052 if(DEFAULT_TIME_WIDTH_S
<
4053 LTTV_TRACESET_CONTEXT(tab
->traceset_info
->traceset_context
)->
4054 time_span
.end_time
.tv_sec
)
4055 tmp_time
.tv_sec
= DEFAULT_TIME_WIDTH_S
;
4058 LTTV_TRACESET_CONTEXT(tab
->traceset_info
->traceset_context
)->
4059 time_span
.end_time
.tv_sec
;
4060 tmp_time
.tv_nsec
= 0;
4061 tab
->time_window
.time_width
= tmp_time
;
4062 tab
->current_time
.tv_sec
=
4063 LTTV_TRACESET_CONTEXT(tab
->traceset_info
->traceset_context
)->
4064 time_span
.start_time
.tv_sec
;
4065 tab
->current_time
.tv_nsec
=
4066 LTTV_TRACESET_CONTEXT(tab
->traceset_info
->traceset_context
)->
4067 time_span
.start_time
.tv_nsec
;
4070 tab
->attributes
= LTTV_IATTRIBUTE(g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
));
4071 tab
->interrupted_state
= g_object_new(LTTV_ATTRIBUTE_TYPE
, NULL
);
4073 tab
->vbox
= gtk_vbox_new(FALSE
, 2);
4074 tab
->top_widget
= tab
->vbox
;
4075 //g_object_set_data_full(G_OBJECT(tab->top_widget), "filter",
4076 // filter, (GDestroyNotify)lttv_filter_destroy);
4078 // g_signal_connect (G_OBJECT(tab->top_widget),
4080 // G_CALLBACK (on_top_notify),
4083 tab
->viewer_container
= gtk_vbox_new(TRUE
, 2);
4084 tab
->scrollbar
= gtk_hscrollbar_new(NULL
);
4085 //tab->multivpaned = gtk_multi_vpaned_new();
4087 gtk_box_pack_start(GTK_BOX(tab
->vbox
),
4088 tab
->viewer_container
,
4090 TRUE
, /* Give the extra space to the child */
4091 0); /* No padding */
4094 // tab->time_window = copy_tab->time_window;
4095 // tab->current_time = copy_tab->current_time;
4098 /* Create the timebar */
4100 tab
->MTimebar
= timebar_new();
4102 gtk_box_pack_end(GTK_BOX(tab
->vbox
),
4104 FALSE
, /* Do not expand */
4105 FALSE
, /* Fill has no effect here (expand false) */
4106 0); /* No padding */
4108 gtk_box_pack_end(GTK_BOX(tab
->vbox
),
4110 FALSE
, /* Do not expand */
4111 FALSE
, /* Fill has no effect here (expand false) */
4112 0); /* No padding */
4114 g_object_set_data(G_OBJECT(tab
->viewer_container
), "focused_viewer", NULL
);
4120 // Display a label with a X
4121 GtkWidget *w_hbox = gtk_hbox_new(FALSE, 4);
4122 GtkWidget *w_label = gtk_label_new (label);
4123 GtkWidget *pixmap = create_pixmap(GTK_WIDGET(notebook), "close.png");
4124 GtkWidget *w_button = gtk_button_new ();
4125 gtk_container_add(GTK_CONTAINER(w_button), pixmap);
4126 //GtkWidget *w_button = gtk_button_new_with_label("x");
4128 gtk_button_set_relief(GTK_BUTTON(w_button), GTK_RELIEF_NONE);
4130 gtk_box_pack_start(GTK_BOX(w_hbox), w_label, TRUE, TRUE, 0);
4131 gtk_box_pack_end(GTK_BOX(w_hbox), w_button, FALSE,
4134 g_signal_connect_swapped (w_button, "clicked",
4135 G_CALLBACK (on_close_tab_X_clicked),
4138 gtk_widget_set_state(w_button, GTK_STATE_ACTIVE);
4140 gtk_widget_show (w_label);
4141 gtk_widget_show (pixmap);
4142 gtk_widget_show (w_button);
4143 gtk_widget_show (w_hbox);
4145 tab->label = w_hbox;
4149 tab
->label
= gtk_label_new (label
);
4151 gtk_widget_show(tab
->label
);
4152 gtk_widget_show(tab
->scrollbar
);
4153 gtk_widget_show(tab
->MTimebar
);
4154 gtk_widget_show(tab
->viewer_container
);
4155 gtk_widget_show(tab
->vbox
);
4157 //gtk_widget_show(tab->multivpaned);
4160 /* Start with empty events requests list */
4161 tab
->events_requests
= NULL
;
4162 tab
->events_request_pending
= FALSE
;
4163 tab
->stop_foreground
= FALSE
;
4167 g_signal_connect(G_OBJECT(tab
->scrollbar
), "value-changed",
4168 G_CALLBACK(scroll_value_changed_cb
), tab
);
4171 /* Timebar signal handler */
4172 g_signal_connect(G_OBJECT(tab
->MTimebar
), "start-time-changed",
4173 G_CALLBACK(on_timebar_starttime_changed
), tab
);
4174 g_signal_connect(G_OBJECT(tab
->MTimebar
), "end-time-changed",
4175 G_CALLBACK(on_timebar_endtime_changed
), tab
);
4176 g_signal_connect(G_OBJECT(tab
->MTimebar
), "current-time-changed",
4177 G_CALLBACK(on_timebar_currenttime_changed
), tab
);
4179 //g_signal_connect(G_OBJECT(tab->scrollbar), "changed",
4180 // G_CALLBACK(scroll_value_changed_cb), tab);
4183 //insert tab into notebook
4184 gtk_notebook_append_page(notebook
,
4187 list
= gtk_container_get_children(GTK_CONTAINER(notebook
));
4188 gtk_notebook_set_current_page(notebook
,g_list_length(list
)-1);
4189 // always show : not if(g_list_length(list)>1)
4190 gtk_notebook_set_show_tabs(notebook
, TRUE
);
4193 lttvwindow_report_time_window(tab
, copy_tab
->time_window
);
4194 lttvwindow_report_current_time(tab
, copy_tab
->current_time
);
4196 TimeWindow time_window
;
4198 time_window
.start_time
= ltt_time_zero
;
4199 time_window
.end_time
= ltt_time_add(time_window
.start_time
,
4200 lttvwindow_default_time_width
);
4201 time_window
.time_width
= lttvwindow_default_time_width
;
4202 time_window
.time_width_double
= ltt_time_to_double(time_window
.time_width
);
4204 lttvwindow_report_time_window(tab
, time_window
);
4205 lttvwindow_report_current_time(tab
, ltt_time_zero
);
4208 LttvTraceset
*traceset
= tab
->traceset_info
->traceset
;
4209 SetTraceset(tab
, traceset
);
4213 * execute_events_requests
4215 * Idle function that executes the pending requests for a tab.
4217 * @return return value : TRUE : keep the idle function, FALSE : remove it.
4219 gboolean
execute_events_requests(Tab
*tab
)
4221 return ( lttvwindow_process_pending_requests(tab
) );
4225 __EXPORT
void create_main_window_with_trace_list(GSList
*traces
)
4228 GSList
*iter
= NULL
;
4231 MainWindow
*mw
= construct_main_window(NULL
);
4232 GtkWidget
*widget
= mw
->mwindow
;
4234 GtkWidget
* notebook
= lookup_widget(widget
, "MNotebook");
4235 GtkWidget
*page
= gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook
),
4236 gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook
)));
4237 LttvPluginTab
*ptab
;
4241 ptab
= create_new_tab(widget
, NULL
);
4244 ptab
= (LttvPluginTab
*)g_object_get_data(G_OBJECT(page
), "Tab_Plugin");
4248 LttvTraceset
* traceset
= lttv_traceset_new();
4249 for(iter
=traces
; iter
!=NULL
; iter
=g_slist_next(iter
)) {
4250 gchar
*path
= (gchar
*)iter
->data
;
4252 gchar abs_path
[PATH_MAX
];
4255 get_absolute_pathname(path
, abs_path
);
4257 if(lttv_traceset_add_path(traceset
,abs_path
) != 0 ){ /*failure*/
4259 g_warning("cannot open trace %s", abs_path
);
4261 GtkWidget
*dialogue
=
4262 gtk_message_dialog_new(
4263 GTK_WINDOW(gtk_widget_get_toplevel(widget
)),
4264 GTK_DIALOG_MODAL
|GTK_DIALOG_DESTROY_WITH_PARENT
,
4267 "Cannot open trace : maybe you should enter in the directory "
4269 gtk_dialog_run(GTK_DIALOG(dialogue
));
4270 gtk_widget_destroy(dialogue
);
4273 SetTraceset(tab
, traceset
);