trace control finished
[lttv.git] / ltt / branches / poly / lttv / modules / gui / lttvwindow / lttvwindow / callbacks.c
1 /* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2003-2004 XangXiu Yang, Mathieu Desnoyers
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License Version 2 as
6 * published by the Free Software Foundation;
7 *
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.
12 *
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,
16 * MA 02111-1307, USA.
17 */
18
19 #ifdef HAVE_CONFIG_H
20 # include <config.h>
21 #endif
22
23 #include <limits.h> // for PATH_MAX
24 #include <stdlib.h>
25 #include <ctype.h>
26 #include <string.h>
27 #include <stdlib.h>
28
29 #include <gtk/gtk.h>
30
31 #include "callbacks.h"
32 #include "interface.h"
33 #include "support.h"
34 #include <ltt/trace.h>
35 #include <ltt/facility.h>
36 #include <ltt/time.h>
37 #include <ltt/event.h>
38 #include <lttv/lttv.h>
39 #include <lttv/module.h>
40 #include <lttv/iattribute.h>
41 #include <lttv/stats.h>
42 #include <lttv/filter.h>
43 #include <lttvwindow/mainwindow.h>
44 #include <lttvwindow/mainwindow-private.h>
45 #include <lttvwindow/menu.h>
46 #include <lttvwindow/toolbar.h>
47 #include <lttvwindow/lttvwindow.h>
48 #include <lttvwindow/lttvwindowtraces.h>
49
50
51 static LttTime lttvwindow_default_time_width = { 1, 0 };
52 #define CLIP_BUF 256 // size of clipboard buffer
53
54 extern LttvTrace *g_init_trace ;
55
56
57 /** Array containing instanced objects. */
58 extern GSList * g_main_window_list;
59
60 /** MD : keep old directory. */
61 static char remember_plugins_dir[PATH_MAX] = "";
62 static char remember_trace_dir[PATH_MAX] = "";
63
64
65 MainWindow * get_window_data_struct(GtkWidget * widget);
66 char * get_load_module(MainWindow *mw,
67 char ** load_module_name, int nb_module);
68 char * get_unload_module(MainWindow *mw,
69 char ** loaded_module_name, int nb_module);
70 char * get_remove_trace(MainWindow *mw, char ** all_trace_name, int nb_trace);
71 char * get_selection(MainWindow *mw,
72 char ** all_name, int nb, char *title, char * column_title);
73 Tab* create_tab(MainWindow * mw, Tab *copy_tab,
74 GtkNotebook * notebook, char * label);
75
76 static void insert_viewer(GtkWidget* widget, lttvwindow_viewer_constructor constructor);
77
78 Tab *create_new_tab(GtkWidget* widget, gpointer user_data);
79
80 static gboolean lttvwindow_process_pending_requests(Tab *tab);
81
82 enum {
83 CHECKBOX_COLUMN,
84 NAME_COLUMN,
85 TOTAL_COLUMNS
86 };
87
88 enum
89 {
90 MODULE_COLUMN,
91 N_COLUMNS
92 };
93
94 /* Pasting routines */
95
96 static void MEventBox1a_receive(GtkClipboard *clipboard,
97 const gchar *text,
98 gpointer data)
99 {
100 if(text == NULL) return;
101 Tab *tab = (Tab *)data;
102 gchar buffer[CLIP_BUF];
103 gchar *ptr = buffer, *ptr_ssec, *ptr_snsec, *ptr_esec, *ptr_ensec;
104
105 strncpy(buffer, text, CLIP_BUF);
106
107 /* start */
108 while(!isdigit(*ptr) && ptr < buffer+CLIP_BUF-1) ptr++;
109 /* remove leading junk */
110 ptr_ssec = ptr;
111 while(isdigit(*ptr) && ptr < buffer+CLIP_BUF-1) ptr++;
112 /* read all the first number */
113 *ptr = '\0';
114 ptr++;
115
116 while(!isdigit(*ptr) && ptr < buffer+CLIP_BUF-1) ptr++;
117 /* remove leading junk */
118 ptr_snsec = ptr;
119 while(isdigit(*ptr) && ptr < buffer+CLIP_BUF-1) ptr++;
120 /* read all the first number */
121 *ptr = '\0';
122
123 /* end */
124 while(!isdigit(*ptr) && ptr < buffer+CLIP_BUF-1) ptr++;
125 /* remove leading junk */
126 ptr_esec = ptr;
127 while(isdigit(*ptr) && ptr < buffer+CLIP_BUF-1) ptr++;
128 /* read all the first number */
129 *ptr = '\0';
130 ptr++;
131
132 while(!isdigit(*ptr) && ptr < buffer+CLIP_BUF-1) ptr++;
133 /* remove leading junk */
134 ptr_ensec = ptr;
135 while(isdigit(*ptr) && ptr < buffer+CLIP_BUF-1) ptr++;
136 /* read all the first number */
137 *ptr = '\0';
138
139 gtk_spin_button_set_value(GTK_SPIN_BUTTON(tab->MEntry1),
140 (double)strtoul(ptr_ssec, NULL, 10));
141 gtk_spin_button_set_value(GTK_SPIN_BUTTON(tab->MEntry2),
142 (double)strtoul(ptr_snsec, NULL, 10));
143 gtk_spin_button_set_value(GTK_SPIN_BUTTON(tab->MEntry3),
144 (double)strtoul(ptr_esec, NULL, 10));
145 gtk_spin_button_set_value(GTK_SPIN_BUTTON(tab->MEntry4),
146 (double)strtoul(ptr_ensec, NULL, 10));
147 }
148
149 static gboolean on_MEventBox1a_paste(GtkWidget *widget, GdkEventButton *event,
150 gpointer data)
151 {
152 Tab *tab = (Tab*)data;
153
154 GtkClipboard *clip = gtk_clipboard_get_for_display(gdk_display_get_default(),
155 GDK_SELECTION_PRIMARY);
156 gtk_clipboard_request_text(clip,
157 (GtkClipboardTextReceivedFunc)MEventBox1a_receive,
158 (gpointer)tab);
159 return 0;
160 }
161
162
163 /* Start */
164 static void MEventBox1b_receive(GtkClipboard *clipboard,
165 const gchar *text,
166 gpointer data)
167 {
168 if(text == NULL) return;
169 Tab *tab = (Tab *)data;
170 gchar buffer[CLIP_BUF];
171 gchar *ptr = buffer, *ptr_sec, *ptr_nsec;
172
173 strncpy(buffer, text, CLIP_BUF);
174
175 while(!isdigit(*ptr) && ptr < buffer+CLIP_BUF-1) ptr++;
176 /* remove leading junk */
177 ptr_sec = ptr;
178 while(isdigit(*ptr) && ptr < buffer+CLIP_BUF-1) ptr++;
179 /* read all the first number */
180 *ptr = '\0';
181 ptr++;
182
183 while(!isdigit(*ptr) && ptr < buffer+CLIP_BUF-1) ptr++;
184 /* remove leading junk */
185 ptr_nsec = ptr;
186 while(isdigit(*ptr) && ptr < buffer+CLIP_BUF-1) ptr++;
187 /* read all the first number */
188 *ptr = '\0';
189
190 gtk_spin_button_set_value(GTK_SPIN_BUTTON(tab->MEntry1),
191 (double)strtoul(ptr_sec, NULL, 10));
192 gtk_spin_button_set_value(GTK_SPIN_BUTTON(tab->MEntry2),
193 (double)strtoul(ptr_nsec, NULL, 10));
194 }
195
196 /* Start */
197 static gboolean on_MEventBox1b_paste(GtkWidget *widget, GdkEventButton *event,
198 gpointer data)
199 {
200 Tab *tab = (Tab*)data;
201
202 GtkClipboard *clip = gtk_clipboard_get_for_display(gdk_display_get_default(),
203 GDK_SELECTION_PRIMARY);
204 gtk_clipboard_request_text(clip,
205 (GtkClipboardTextReceivedFunc)MEventBox1b_receive,
206 (gpointer)tab);
207 return 0;
208 }
209
210 /* End */
211 static void MEventBox3b_receive(GtkClipboard *clipboard,
212 const gchar *text,
213 gpointer data)
214 {
215 if(text == NULL) return;
216 Tab *tab = (Tab *)data;
217 gchar buffer[CLIP_BUF];
218 gchar *ptr = buffer, *ptr_sec, *ptr_nsec;
219
220 strncpy(buffer, text, CLIP_BUF);
221
222 while(!isdigit(*ptr) && ptr < buffer+CLIP_BUF-1) ptr++;
223 /* remove leading junk */
224 ptr_sec = ptr;
225 while(isdigit(*ptr) && ptr < buffer+CLIP_BUF-1) ptr++;
226 /* read all the first number */
227 *ptr = '\0';
228 ptr++;
229
230 while(!isdigit(*ptr) && ptr < buffer+CLIP_BUF-1) ptr++;
231 /* remove leading junk */
232 ptr_nsec = ptr;
233 while(isdigit(*ptr) && ptr < buffer+CLIP_BUF-1) ptr++;
234 /* read all the first number */
235 *ptr = '\0';
236
237 gtk_spin_button_set_value(GTK_SPIN_BUTTON(tab->MEntry3),
238 (double)strtoul(ptr_sec, NULL, 10));
239 gtk_spin_button_set_value(GTK_SPIN_BUTTON(tab->MEntry4),
240 (double)strtoul(ptr_nsec, NULL, 10));
241 }
242
243 /* End */
244 static gboolean on_MEventBox3b_paste(GtkWidget *widget, GdkEventButton *event,
245 gpointer data)
246 {
247 Tab *tab = (Tab*)data;
248
249 GtkClipboard *clip = gtk_clipboard_get_for_display(gdk_display_get_default(),
250 GDK_SELECTION_PRIMARY);
251 gtk_clipboard_request_text(clip,
252 (GtkClipboardTextReceivedFunc)MEventBox3b_receive,
253 (gpointer)tab);
254 return 0;
255 }
256
257 /* Current */
258 static void MEventBox5b_receive(GtkClipboard *clipboard,
259 const gchar *text,
260 gpointer data)
261 {
262 if(text == NULL) return;
263 Tab *tab = (Tab *)data;
264 gchar buffer[CLIP_BUF];
265 gchar *ptr = buffer, *ptr_sec, *ptr_nsec;
266
267 strncpy(buffer, text, CLIP_BUF);
268
269 while(!isdigit(*ptr) && ptr < buffer+CLIP_BUF-1) ptr++;
270 /* remove leading junk */
271 ptr_sec = ptr;
272 while(isdigit(*ptr) && ptr < buffer+CLIP_BUF-1) ptr++;
273 /* read all the first number */
274 *ptr = '\0';
275 ptr++;
276
277 while(!isdigit(*ptr) && ptr < buffer+CLIP_BUF-1) ptr++;
278 /* remove leading junk */
279 ptr_nsec = ptr;
280 while(isdigit(*ptr) && ptr < buffer+CLIP_BUF-1) ptr++;
281 /* read all the first number */
282 *ptr = '\0';
283
284 gtk_spin_button_set_value(GTK_SPIN_BUTTON(tab->MEntry5),
285 (double)strtoul(ptr_sec, NULL, 10));
286 gtk_spin_button_set_value(GTK_SPIN_BUTTON(tab->MEntry6),
287 (double)strtoul(ptr_nsec, NULL, 10));
288 }
289
290 /* Current */
291 static gboolean on_MEventBox5b_paste(GtkWidget *widget, GdkEventButton *event,
292 gpointer data)
293 {
294 Tab *tab = (Tab*)data;
295
296 GtkClipboard *clip = gtk_clipboard_get_for_display(gdk_display_get_default(),
297 GDK_SELECTION_PRIMARY);
298 gtk_clipboard_request_text(clip,
299 (GtkClipboardTextReceivedFunc)MEventBox5b_receive,
300 (gpointer)tab);
301 return 0;
302 }
303
304
305 static gboolean viewer_grab_focus(GtkWidget *widget, GdkEventButton *event,
306 gpointer data)
307 {
308 GtkWidget *viewer = GTK_WIDGET(data);
309 GtkWidget *viewer_container = gtk_widget_get_parent(viewer);
310
311 g_debug("FOCUS GRABBED");
312 g_object_set_data(G_OBJECT(viewer_container), "focused_viewer", viewer);
313 return 0;
314 }
315
316
317 static void connect_focus_recursive(GtkWidget *widget,
318 GtkWidget *viewer)
319 {
320 if(GTK_IS_CONTAINER(widget)) {
321 gtk_container_forall(GTK_CONTAINER(widget),
322 (GtkCallback)connect_focus_recursive,
323 viewer);
324
325 }
326 if(GTK_IS_TREE_VIEW(widget)) {
327 gtk_tree_view_set_headers_clickable(GTK_TREE_VIEW(widget), TRUE);
328 }
329 gtk_widget_add_events(widget, GDK_BUTTON_PRESS_MASK);
330 g_signal_connect (G_OBJECT(widget),
331 "button-press-event",
332 G_CALLBACK (viewer_grab_focus),
333 (gpointer)viewer);
334 }
335
336 /* Stop all the processings and call gtk_main_quit() */
337 static void mainwindow_quit()
338 {
339 lttvwindowtraces_unregister_requests(g_quark_from_string("stats"));
340 lttvwindowtraces_unregister_requests(g_quark_from_string("state"));
341 lttvwindowtraces_unregister_computation_hooks(g_quark_from_string("stats"));
342 lttvwindowtraces_unregister_computation_hooks(g_quark_from_string("state"));
343
344 gtk_main_quit();
345 }
346
347
348 /* insert_viewer function constructs an instance of a viewer first,
349 * then inserts the widget of the instance into the container of the
350 * main window
351 */
352
353 void
354 insert_viewer_wrap(GtkWidget *menuitem, gpointer user_data)
355 {
356 insert_viewer((GtkWidget*)menuitem, (lttvwindow_viewer_constructor)user_data);
357 }
358
359
360 /* internal functions */
361 void insert_viewer(GtkWidget* widget, lttvwindow_viewer_constructor constructor)
362 {
363 GtkWidget * viewer_container;
364 MainWindow * mw_data = get_window_data_struct(widget);
365 GtkWidget * notebook = lookup_widget(widget, "MNotebook");
366 GtkWidget * viewer;
367 TimeInterval * time_interval;
368 GtkWidget *page = gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook),
369 gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook)));
370 Tab *tab;
371
372 if(!page) {
373 tab = create_new_tab(widget, NULL);
374 } else {
375 tab = (Tab *)g_object_get_data(G_OBJECT(page), "Tab_Info");
376 }
377
378 viewer_container = tab->viewer_container;
379
380 viewer = (GtkWidget*)constructor(tab);
381 if(viewer)
382 {
383 //gtk_multivpaned_widget_add(GTK_MULTIVPANED(multivpaned), viewer);
384
385 gtk_box_pack_end(GTK_BOX(viewer_container),
386 viewer,
387 TRUE,
388 TRUE,
389 0);
390
391 /* We want to connect the viewer_grab_focus to EVERY
392 * child of this widget. The little trick is to get each child
393 * of each GTK_CONTAINER, even subchildren.
394 */
395 connect_focus_recursive(viewer, viewer);
396 }
397 }
398
399 /**
400 * Function to set/update traceset for the viewers
401 * @param tab viewer's tab
402 * @param traceset traceset of the main window.
403 * return value :
404 * 0 : traceset updated
405 * 1 : no traceset hooks to update; not an error.
406 */
407
408 int SetTraceset(Tab * tab, LttvTraceset *traceset)
409 {
410 LttvTracesetContext *tsc =
411 LTTV_TRACESET_CONTEXT(tab->traceset_info->traceset_context);
412 TimeInterval time_span = tsc->time_span;
413 TimeWindow new_time_window = tab->time_window;
414 LttTime new_current_time = tab->current_time;
415
416 /* Set the tab's time window and current time if
417 * out of bounds */
418 if(ltt_time_compare(tab->time_window.start_time, time_span.start_time) < 0
419 || ltt_time_compare(tab->time_window.end_time,
420 time_span.end_time) > 0) {
421 new_time_window.start_time = time_span.start_time;
422
423 new_current_time = time_span.start_time;
424
425 LttTime tmp_time;
426
427 if(ltt_time_compare(lttvwindow_default_time_width,
428 ltt_time_sub(time_span.end_time, time_span.start_time)) < 0
429 ||
430 ltt_time_compare(time_span.end_time, time_span.start_time) == 0)
431 tmp_time = lttvwindow_default_time_width;
432 else
433 tmp_time = time_span.end_time;
434
435 new_time_window.time_width = tmp_time ;
436 new_time_window.time_width_double = ltt_time_to_double(tmp_time);
437 new_time_window.end_time = ltt_time_add(new_time_window.start_time,
438 new_time_window.time_width) ;
439 }
440
441
442
443 #if 0
444 /* Set scrollbar */
445 GtkAdjustment *adjustment = gtk_range_get_adjustment(GTK_RANGE(tab->scrollbar));
446 LttTime upper = ltt_time_sub(time_span.end_time, time_span.start_time);
447
448 g_object_set(G_OBJECT(adjustment),
449 "lower",
450 0.0, /* lower */
451 "upper",
452 ltt_time_to_double(upper)
453 * NANOSECONDS_PER_SECOND, /* upper */
454 "step_increment",
455 ltt_time_to_double(tab->time_window.time_width)
456 / SCROLL_STEP_PER_PAGE
457 * NANOSECONDS_PER_SECOND, /* step increment */
458 "page_increment",
459 ltt_time_to_double(tab->time_window.time_width)
460 * NANOSECONDS_PER_SECOND, /* page increment */
461 "page_size",
462 ltt_time_to_double(tab->time_window.time_width)
463 * NANOSECONDS_PER_SECOND, /* page size */
464 NULL);
465 gtk_adjustment_changed(adjustment);
466
467 g_object_set(G_OBJECT(adjustment),
468 "value",
469 ltt_time_to_double(
470 ltt_time_sub(tab->time_window.start_time, time_span.start_time))
471 * NANOSECONDS_PER_SECOND, /* value */
472 NULL);
473 gtk_adjustment_value_changed(adjustment);
474
475 /* set the time bar. The value callbacks will change their nsec themself */
476 /* start seconds */
477 gtk_spin_button_set_range(GTK_SPIN_BUTTON(tab->MEntry1),
478 (double)time_span.start_time.tv_sec,
479 (double)time_span.end_time.tv_sec);
480
481 /* end seconds */
482 gtk_spin_button_set_range(GTK_SPIN_BUTTON(tab->MEntry3),
483 (double)time_span.start_time.tv_sec,
484 (double)time_span.end_time.tv_sec);
485
486 /* current seconds */
487 gtk_spin_button_set_range(GTK_SPIN_BUTTON(tab->MEntry5),
488 (double)time_span.start_time.tv_sec,
489 (double)time_span.end_time.tv_sec);
490 #endif //0
491
492 /* Finally, call the update hooks of the viewers */
493 LttvHooks * tmp;
494 LttvAttributeValue value;
495 gint retval = 0;
496
497
498 g_assert( lttv_iattribute_find_by_path(tab->attributes,
499 "hooks/updatetraceset", LTTV_POINTER, &value));
500
501 tmp = (LttvHooks*)*(value.v_pointer);
502 if(tmp == NULL) retval = 1;
503 else lttv_hooks_call(tmp,traceset);
504
505 time_change_manager(tab, new_time_window);
506 current_time_change_manager(tab, new_current_time);
507
508 return retval;
509 }
510
511 /**
512 * Function to set/update filter for the viewers
513 * @param tab viewer's tab
514 * @param filter filter of the main window.
515 * return value :
516 * -1 : error
517 * 0 : filters updated
518 * 1 : no filter hooks to update; not an error.
519 */
520 #if 0
521 int SetFilter(Tab * tab, gpointer filter)
522 {
523 LttvHooks * tmp;
524 LttvAttributeValue value;
525
526 g_assert(lttv_iattribute_find_by_path(tab->attributes,
527 "hooks/updatefilter", LTTV_POINTER, &value));
528
529 tmp = (LttvHooks*)*(value.v_pointer);
530
531 if(tmp == NULL) return 1;
532 lttv_hooks_call(tmp,filter);
533
534 return 0;
535 }
536 #endif //0
537
538
539 /**
540 * Function to redraw each viewer belonging to the current tab
541 * @param tab viewer's tab
542 */
543
544 void update_traceset(Tab *tab)
545 {
546 LttvAttributeValue value;
547 LttvHooks * tmp;
548 g_assert(lttv_iattribute_find_by_path(tab->attributes,
549 "hooks/updatetraceset", LTTV_POINTER, &value));
550 tmp = (LttvHooks*)*(value.v_pointer);
551 if(tmp == NULL) return;
552 lttv_hooks_call(tmp, NULL);
553 }
554
555
556 /* get_label function is used to get user input, it displays an input
557 * box, which allows user to input a string
558 */
559
560 void get_label_string (GtkWidget * text, gchar * label)
561 {
562 GtkEntry * entry = (GtkEntry*)text;
563 if(strlen(gtk_entry_get_text(entry))!=0)
564 strcpy(label,gtk_entry_get_text(entry));
565 }
566
567 gboolean get_label(MainWindow * mw, gchar * str, gchar* dialogue_title, gchar * label_str)
568 {
569 GtkWidget * dialogue;
570 GtkWidget * text;
571 GtkWidget * label;
572 gint id;
573
574 dialogue = gtk_dialog_new_with_buttons(dialogue_title,NULL,
575 GTK_DIALOG_MODAL,
576 GTK_STOCK_OK,GTK_RESPONSE_ACCEPT,
577 GTK_STOCK_CANCEL,GTK_RESPONSE_REJECT,
578 NULL);
579
580 label = gtk_label_new(label_str);
581 gtk_widget_show(label);
582
583 text = gtk_entry_new();
584 gtk_widget_show(text);
585
586 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialogue)->vbox), label,TRUE, TRUE,0);
587 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialogue)->vbox), text,FALSE, FALSE,0);
588
589 id = gtk_dialog_run(GTK_DIALOG(dialogue));
590 switch(id){
591 case GTK_RESPONSE_ACCEPT:
592 get_label_string(text,str);
593 gtk_widget_destroy(dialogue);
594 break;
595 case GTK_RESPONSE_REJECT:
596 default:
597 gtk_widget_destroy(dialogue);
598 return FALSE;
599 }
600 return TRUE;
601 }
602
603
604 /* get_window_data_struct function is actually a lookup function,
605 * given a widget which is in the tree of the main window, it will
606 * return the MainWindow data structure associated with main window
607 */
608
609 MainWindow * get_window_data_struct(GtkWidget * widget)
610 {
611 GtkWidget * mw;
612 MainWindow * mw_data;
613
614 mw = lookup_widget(widget, "MWindow");
615 if(mw == NULL){
616 g_info("Main window does not exist\n");
617 return NULL;
618 }
619
620 mw_data = (MainWindow *) g_object_get_data(G_OBJECT(mw),"main_window_data");
621 if(mw_data == NULL){
622 g_warning("Main window data does not exist\n");
623 return NULL;
624 }
625 return mw_data;
626 }
627
628
629 /* create_new_window function, just constructs a new main window
630 */
631
632 void create_new_window(GtkWidget* widget, gpointer user_data, gboolean clone)
633 {
634 MainWindow * parent = get_window_data_struct(widget);
635
636 if(clone){
637 g_info("Clone : use the same traceset\n");
638 construct_main_window(parent);
639 }else{
640 g_info("Empty : traceset is set to NULL\n");
641 construct_main_window(NULL);
642 }
643 }
644
645 /* Get the currently focused viewer.
646 * If no viewer is focused, use the first one.
647 *
648 * If no viewer available, return NULL.
649 */
650 GtkWidget *viewer_container_focus(GtkWidget *container)
651 {
652 GtkWidget *widget;
653
654 widget = (GtkWidget*)g_object_get_data(G_OBJECT(container),
655 "focused_viewer");
656
657 if(widget == NULL) {
658 g_debug("no widget focused");
659 GList *children = gtk_container_get_children(GTK_CONTAINER(container));
660
661 if(children != NULL)
662 widget = GTK_WIDGET(children->data);
663 g_object_set_data(G_OBJECT(container),
664 "focused_viewer",
665 widget);
666 }
667
668 return widget;
669
670
671 }
672
673 gint viewer_container_position(GtkWidget *container, GtkWidget *child)
674 {
675
676 if(child == NULL) return -1;
677
678 gint pos;
679 GValue value;
680 memset(&value, 0, sizeof(GValue));
681 g_value_init(&value, G_TYPE_INT);
682 gtk_container_child_get_property(GTK_CONTAINER(container),
683 child,
684 "position",
685 &value);
686 pos = g_value_get_int(&value);
687
688 return pos;
689 }
690
691
692 /* move_*_viewer functions move the selected view up/down in
693 * the current tab
694 */
695
696 void move_down_viewer(GtkWidget * widget, gpointer user_data)
697 {
698 MainWindow * mw = get_window_data_struct(widget);
699 GtkWidget * notebook = lookup_widget(widget, "MNotebook");
700
701 GtkWidget *page = gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook),
702 gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook)));
703
704 Tab *tab;
705 if(!page) {
706 return;
707 } else {
708 tab = (Tab *)g_object_get_data(G_OBJECT(page), "Tab_Info");
709 }
710
711 //gtk_multivpaned_widget_move_up(GTK_MULTIVPANED(tab->multivpaned));
712
713 /* change the position in the vbox */
714 GtkWidget *focus_widget;
715 gint position;
716 focus_widget = viewer_container_focus(tab->viewer_container);
717 position = viewer_container_position(tab->viewer_container, focus_widget);
718
719 if(position > 0) {
720 /* can move up one position */
721 gtk_box_reorder_child(GTK_BOX(tab->viewer_container),
722 focus_widget,
723 position-1);
724 }
725
726 }
727
728 void move_up_viewer(GtkWidget * widget, gpointer user_data)
729 {
730 MainWindow * mw = get_window_data_struct(widget);
731 GtkWidget * notebook = lookup_widget(widget, "MNotebook");
732
733 GtkWidget *page = gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook),
734 gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook)));
735 Tab *tab;
736
737 if(!page) {
738 return;
739 } else {
740 tab = (Tab *)g_object_get_data(G_OBJECT(page), "Tab_Info");
741 }
742
743 //gtk_multivpaned_widget_move_down(GTK_MULTIVPANED(tab->multivpaned));
744 /* change the position in the vbox */
745 GtkWidget *focus_widget;
746 gint position;
747 focus_widget = viewer_container_focus(tab->viewer_container);
748 position = viewer_container_position(tab->viewer_container, focus_widget);
749
750 if(position != -1 &&
751 position <
752 g_list_length(gtk_container_get_children(
753 GTK_CONTAINER(tab->viewer_container)))-1
754 ) {
755 /* can move down one position */
756 gtk_box_reorder_child(GTK_BOX(tab->viewer_container),
757 focus_widget,
758 position+1);
759 }
760
761 }
762
763
764 /* delete_viewer deletes the selected viewer in the current tab
765 */
766
767 void delete_viewer(GtkWidget * widget, gpointer user_data)
768 {
769 MainWindow * mw = get_window_data_struct(widget);
770 GtkWidget * notebook = lookup_widget(widget, "MNotebook");
771
772 GtkWidget *page = gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook),
773 gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook)));
774 Tab *tab;
775
776 if(!page) {
777 return;
778 } else {
779 tab = (Tab *)g_object_get_data(G_OBJECT(page), "Tab_Info");
780 }
781
782 //gtk_multivpaned_widget_delete(GTK_MULTIVPANED(tab->multivpaned));
783
784 GtkWidget *focus_widget = viewer_container_focus(tab->viewer_container);
785
786 if(focus_widget != NULL)
787 gtk_widget_destroy(focus_widget);
788
789 g_object_set_data(G_OBJECT(tab->viewer_container), "focused_viewer", NULL);
790 }
791
792
793 /* open_traceset will open a traceset saved in a file
794 * Right now, it is not finished yet, (not working)
795 * FIXME
796 */
797
798 void open_traceset(GtkWidget * widget, gpointer user_data)
799 {
800 char ** dir;
801 gint id;
802 LttvTraceset * traceset;
803 MainWindow * mw_data = get_window_data_struct(widget);
804 GtkFileSelection * file_selector =
805 (GtkFileSelection *)gtk_file_selection_new("Select a traceset");
806
807 gtk_file_selection_hide_fileop_buttons(file_selector);
808
809 gtk_window_set_transient_for(GTK_WINDOW(file_selector),
810 GTK_WINDOW(mw_data->mwindow));
811
812 id = gtk_dialog_run(GTK_DIALOG(file_selector));
813 switch(id){
814 case GTK_RESPONSE_ACCEPT:
815 case GTK_RESPONSE_OK:
816 dir = gtk_file_selection_get_selections (file_selector);
817 traceset = lttv_traceset_load(dir[0]);
818 g_info("Open a trace set %s\n", dir[0]);
819 //Not finished yet
820 g_strfreev(dir);
821 case GTK_RESPONSE_REJECT:
822 case GTK_RESPONSE_CANCEL:
823 default:
824 gtk_widget_destroy((GtkWidget*)file_selector);
825 break;
826 }
827
828 }
829
830 /* lttvwindow_process_pending_requests
831 *
832 * This internal function gets called by g_idle, taking care of the pending
833 * requests. It is responsible for concatenation of time intervals and position
834 * requests. It does it with the following algorithm organizing process traceset
835 * calls. Here is the detailed description of the way it works :
836 *
837 * - Events Requests Servicing Algorithm
838 *
839 * Data structures necessary :
840 *
841 * List of requests added to context : list_in
842 * List of requests not added to context : list_out
843 *
844 * Initial state :
845 *
846 * list_in : empty
847 * list_out : many events requests
848 *
849 * FIXME : insert rest of algorithm here
850 *
851 */
852
853 #define list_out tab->events_requests
854
855 gboolean lttvwindow_process_pending_requests(Tab *tab)
856 {
857 GtkWidget* widget;
858 LttvTracesetContext *tsc;
859 LttvTracefileContext *tfc;
860 GSList *list_in = NULL;
861 LttTime end_time;
862 guint end_nb_events;
863 guint count;
864 LttvTracesetContextPosition *end_position;
865
866 if(tab == NULL) {
867 g_critical("Foreground processing : tab does not exist. Processing removed.");
868 return FALSE;
869 }
870
871 /* There is no events requests pending : we should never have been called! */
872 g_assert(g_slist_length(list_out) != 0);
873
874 tsc = LTTV_TRACESET_CONTEXT(tab->traceset_info->traceset_context);
875
876 //set the cursor to be X shape, indicating that the computer is busy in doing its job
877 #if 0
878 new = gdk_cursor_new(GDK_X_CURSOR);
879 widget = lookup_widget(tab->mw->mwindow, "MToolbar1");
880 win = gtk_widget_get_parent_window(widget);
881 gdk_window_set_cursor(win, new);
882 gdk_cursor_unref(new);
883 gdk_window_stick(win);
884 gdk_window_unstick(win);
885 #endif //0
886
887 g_debug("SIZE events req len : %d", g_slist_length(list_out));
888
889 /* Preliminary check for no trace in traceset */
890 /* Unregister the routine if empty, empty list_out too */
891 if(lttv_traceset_number(tsc->ts) == 0) {
892
893 /* - For each req in list_out */
894 GSList *iter = list_out;
895
896 while(iter != NULL) {
897
898 gboolean remove = FALSE;
899 gboolean free_data = FALSE;
900 EventsRequest *events_request = (EventsRequest *)iter->data;
901
902 /* - Call end request for req */
903 if(events_request->servicing == TRUE)
904 lttv_hooks_call(events_request->after_request, (gpointer)tsc);
905
906 /* - remove req from list_out */
907 /* Destroy the request */
908 remove = TRUE;
909 free_data = TRUE;
910
911 /* Go to next */
912 if(remove)
913 {
914 GSList *remove_iter = iter;
915
916 iter = g_slist_next(iter);
917 if(free_data) events_request_free((EventsRequest*)remove_iter->data);
918 list_out = g_slist_remove_link(list_out, remove_iter);
919 } else { // not remove
920 iter = g_slist_next(iter);
921 }
922 }
923 }
924
925 /* 0.1 Lock Traces */
926 {
927 guint iter_trace=0;
928
929 for(iter_trace=0;
930 iter_trace<lttv_traceset_number(tsc->ts);
931 iter_trace++) {
932 LttvTrace *trace_v = lttv_traceset_get(tsc->ts, iter_trace);
933
934 if(lttvwindowtraces_lock(trace_v) != 0) {
935 g_critical("Foreground processing : Unable to get trace lock");
936 return TRUE; /* Cannot get lock, try later */
937 }
938 }
939 }
940
941 /* 0.2 Seek tracefiles positions to context position */
942 //g_assert(lttv_process_traceset_seek_position(tsc, sync_position) == 0);
943 lttv_process_traceset_synchronize_tracefiles(tsc);
944
945
946 /* Events processing algorithm implementation */
947 /* Warning : the gtk_events_pending takes a LOT of cpu time. So what we do
948 * instead is to leave the control to GTK and take it back.
949 */
950 /* A. Servicing loop */
951 //while( (g_slist_length(list_in) != 0 || g_slist_length(list_out) != 0)) {
952 if((g_slist_length(list_in) != 0 || g_slist_length(list_out) != 0)) {
953 /* Servicing */
954 /* 1. If list_in is empty (need a seek) */
955 if( g_slist_length(list_in) == 0 ) {
956
957 /* list in is empty, need a seek */
958 {
959 /* 1.1 Add requests to list_in */
960 GSList *ltime = NULL;
961 GSList *lpos = NULL;
962 GSList *iter = NULL;
963
964 /* 1.1.1 Find all time requests with the lowest start time in list_out
965 * (ltime)
966 */
967 if(g_slist_length(list_out) > 0)
968 ltime = g_slist_append(ltime, g_slist_nth_data(list_out, 0));
969 for(iter=g_slist_nth(list_out,1);iter!=NULL;iter=g_slist_next(iter)) {
970 /* Find all time requests with the lowest start time in list_out */
971 EventsRequest *event_request_ltime = (EventsRequest*)g_slist_nth_data(ltime, 0);
972 EventsRequest *event_request_list_out = (EventsRequest*)iter->data;
973
974 int comp;
975 comp = ltt_time_compare(event_request_ltime->start_time,
976 event_request_list_out->start_time);
977 if(comp == 0)
978 ltime = g_slist_append(ltime, event_request_list_out);
979 else if(comp > 0) {
980 /* Remove all elements from ltime, and add current */
981 while(ltime != NULL)
982 ltime = g_slist_delete_link(ltime, g_slist_nth(ltime, 0));
983 ltime = g_slist_append(ltime, event_request_list_out);
984 }
985 }
986
987 /* 1.1.2 Find all position requests with the lowest position in list_out
988 * (lpos)
989 */
990 if(g_slist_length(list_out) > 0)
991 lpos = g_slist_append(lpos, g_slist_nth_data(list_out, 0));
992 for(iter=g_slist_nth(list_out,1);iter!=NULL;iter=g_slist_next(iter)) {
993 /* Find all position requests with the lowest position in list_out */
994 EventsRequest *event_request_lpos = (EventsRequest*)g_slist_nth_data(lpos, 0);
995 EventsRequest *event_request_list_out = (EventsRequest*)iter->data;
996
997 int comp;
998 if(event_request_lpos->start_position != NULL
999 && event_request_list_out->start_position != NULL)
1000 {
1001 comp = lttv_traceset_context_pos_pos_compare
1002 (event_request_lpos->start_position,
1003 event_request_list_out->start_position);
1004 } else {
1005 comp = -1;
1006 }
1007 if(comp == 0)
1008 lpos = g_slist_append(lpos, event_request_list_out);
1009 else if(comp > 0) {
1010 /* Remove all elements from lpos, and add current */
1011 while(lpos != NULL)
1012 lpos = g_slist_delete_link(lpos, g_slist_nth(lpos, 0));
1013 lpos = g_slist_append(lpos, event_request_list_out);
1014 }
1015 }
1016
1017 {
1018 EventsRequest *event_request_lpos = (EventsRequest*)g_slist_nth_data(lpos, 0);
1019 EventsRequest *event_request_ltime = (EventsRequest*)g_slist_nth_data(ltime, 0);
1020 LttTime lpos_start_time;
1021
1022 if(event_request_lpos != NULL
1023 && event_request_lpos->start_position != NULL) {
1024 lpos_start_time = lttv_traceset_context_position_get_time(
1025 event_request_lpos->start_position);
1026 }
1027
1028 /* 1.1.3 If lpos.start time < ltime */
1029 if(event_request_lpos != NULL
1030 && event_request_lpos->start_position != NULL
1031 && ltt_time_compare(lpos_start_time,
1032 event_request_ltime->start_time)<0) {
1033 /* Add lpos to list_in, remove them from list_out */
1034 for(iter=lpos;iter!=NULL;iter=g_slist_next(iter)) {
1035 /* Add to list_in */
1036 EventsRequest *event_request_lpos =
1037 (EventsRequest*)iter->data;
1038
1039 list_in = g_slist_append(list_in, event_request_lpos);
1040 /* Remove from list_out */
1041 list_out = g_slist_remove(list_out, event_request_lpos);
1042 }
1043 } else {
1044 /* 1.1.4 (lpos.start time >= ltime) */
1045 /* Add ltime to list_in, remove them from list_out */
1046
1047 for(iter=ltime;iter!=NULL;iter=g_slist_next(iter)) {
1048 /* Add to list_in */
1049 EventsRequest *event_request_ltime =
1050 (EventsRequest*)iter->data;
1051
1052 list_in = g_slist_append(list_in, event_request_ltime);
1053 /* Remove from list_out */
1054 list_out = g_slist_remove(list_out, event_request_ltime);
1055 }
1056 }
1057 }
1058 g_slist_free(lpos);
1059 g_slist_free(ltime);
1060 }
1061
1062 /* 1.2 Seek */
1063 {
1064 tfc = lttv_traceset_context_get_current_tfc(tsc);
1065 g_assert(g_slist_length(list_in)>0);
1066 EventsRequest *events_request = g_slist_nth_data(list_in, 0);
1067 guint seek_count;
1068
1069 /* 1.2.1 If first request in list_in is a time request */
1070 if(events_request->start_position == NULL) {
1071 /* - If first req in list_in start time != current time */
1072 if(tfc == NULL || ltt_time_compare(events_request->start_time,
1073 tfc->timestamp) != 0)
1074 /* - Seek to that time */
1075 g_debug("SEEK TIME : %lu, %lu", events_request->start_time.tv_sec,
1076 events_request->start_time.tv_nsec);
1077 //lttv_process_traceset_seek_time(tsc, events_request->start_time);
1078 lttv_state_traceset_seek_time_closest(LTTV_TRACESET_STATE(tsc),
1079 events_request->start_time);
1080
1081 /* Process the traceset with only state hooks */
1082 seek_count =
1083 lttv_process_traceset_middle(tsc,
1084 events_request->start_time,
1085 G_MAXUINT, NULL);
1086 #ifdef DEBUG
1087 g_assert(seek_count < LTTV_STATE_SAVE_INTERVAL);
1088 #endif //DEBUG
1089
1090
1091 } else {
1092 LttTime pos_time;
1093 /* Else, the first request in list_in is a position request */
1094 /* If first req in list_in pos != current pos */
1095 g_assert(events_request->start_position != NULL);
1096 g_debug("SEEK POS time : %lu, %lu",
1097 lttv_traceset_context_position_get_time(
1098 events_request->start_position).tv_sec,
1099 lttv_traceset_context_position_get_time(
1100 events_request->start_position).tv_nsec);
1101
1102 g_debug("SEEK POS context time : %lu, %lu",
1103 lttv_traceset_context_get_current_tfc(tsc)->timestamp.tv_sec,
1104 lttv_traceset_context_get_current_tfc(tsc)->timestamp.tv_nsec);
1105 g_assert(events_request->start_position != NULL);
1106 if(lttv_traceset_context_ctx_pos_compare(tsc,
1107 events_request->start_position) != 0) {
1108 /* 1.2.2.1 Seek to that position */
1109 g_debug("SEEK POSITION");
1110 //lttv_process_traceset_seek_position(tsc, events_request->start_position);
1111 pos_time = lttv_traceset_context_position_get_time(
1112 events_request->start_position);
1113
1114 lttv_state_traceset_seek_time_closest(LTTV_TRACESET_STATE(tsc),
1115 pos_time);
1116
1117 /* Process the traceset with only state hooks */
1118 seek_count =
1119 lttv_process_traceset_middle(tsc,
1120 ltt_time_infinite,
1121 G_MAXUINT,
1122 events_request->start_position);
1123 g_assert(lttv_traceset_context_ctx_pos_compare(tsc,
1124 events_request->start_position) == 0);
1125
1126
1127 }
1128 }
1129 }
1130
1131 /* 1.3 Add hooks and call before request for all list_in members */
1132 {
1133 GSList *iter = NULL;
1134
1135 for(iter=list_in;iter!=NULL;iter=g_slist_next(iter)) {
1136 EventsRequest *events_request = (EventsRequest*)iter->data;
1137 /* 1.3.1 If !servicing */
1138 if(events_request->servicing == FALSE) {
1139 /* - begin request hooks called
1140 * - servicing = TRUE
1141 */
1142 lttv_hooks_call(events_request->before_request, (gpointer)tsc);
1143 events_request->servicing = TRUE;
1144 }
1145 /* 1.3.2 call before chunk
1146 * 1.3.3 events hooks added
1147 */
1148 if(events_request->trace == -1)
1149 lttv_process_traceset_begin(tsc,
1150 events_request->before_chunk_traceset,
1151 events_request->before_chunk_trace,
1152 events_request->before_chunk_tracefile,
1153 events_request->event,
1154 events_request->event_by_id);
1155 else {
1156 guint nb_trace = lttv_traceset_number(tsc->ts);
1157 g_assert((guint)events_request->trace < nb_trace &&
1158 events_request->trace > -1);
1159 LttvTraceContext *tc = tsc->traces[events_request->trace];
1160
1161 lttv_hooks_call(events_request->before_chunk_traceset, tsc);
1162
1163 lttv_trace_context_add_hooks(tc,
1164 events_request->before_chunk_trace,
1165 events_request->before_chunk_tracefile,
1166 events_request->event,
1167 events_request->event_by_id);
1168 }
1169 }
1170 }
1171 } else {
1172 /* 2. Else, list_in is not empty, we continue a read */
1173
1174 {
1175 /* 2.0 For each req of list_in */
1176 GSList *iter = list_in;
1177
1178 while(iter != NULL) {
1179
1180 EventsRequest *events_request = (EventsRequest *)iter->data;
1181
1182 /* - Call before chunk
1183 * - events hooks added
1184 */
1185 if(events_request->trace == -1)
1186 lttv_process_traceset_begin(tsc,
1187 events_request->before_chunk_traceset,
1188 events_request->before_chunk_trace,
1189 events_request->before_chunk_tracefile,
1190 events_request->event,
1191 events_request->event_by_id);
1192 else {
1193 guint nb_trace = lttv_traceset_number(tsc->ts);
1194 g_assert((guint)events_request->trace < nb_trace &&
1195 events_request->trace > -1);
1196 LttvTraceContext *tc = tsc->traces[events_request->trace];
1197
1198 lttv_hooks_call(events_request->before_chunk_traceset, tsc);
1199
1200 lttv_trace_context_add_hooks(tc,
1201 events_request->before_chunk_trace,
1202 events_request->before_chunk_tracefile,
1203 events_request->event,
1204 events_request->event_by_id);
1205 }
1206
1207 iter = g_slist_next(iter);
1208 }
1209 }
1210
1211 {
1212 tfc = lttv_traceset_context_get_current_tfc(tsc);
1213
1214 /* 2.1 For each req of list_out */
1215 GSList *iter = list_out;
1216
1217 while(iter != NULL) {
1218
1219 gboolean remove = FALSE;
1220 gboolean free_data = FALSE;
1221 EventsRequest *events_request = (EventsRequest *)iter->data;
1222
1223 /* if req.start time == current context time
1224 * or req.start position == current position*/
1225 if( ltt_time_compare(events_request->start_time,
1226 tfc->timestamp) == 0
1227 ||
1228 (events_request->start_position != NULL
1229 &&
1230 lttv_traceset_context_ctx_pos_compare(tsc,
1231 events_request->start_position) == 0)
1232 ) {
1233 /* - Add to list_in, remove from list_out */
1234 list_in = g_slist_append(list_in, events_request);
1235 remove = TRUE;
1236 free_data = FALSE;
1237
1238 /* - If !servicing */
1239 if(events_request->servicing == FALSE) {
1240 /* - begin request hooks called
1241 * - servicing = TRUE
1242 */
1243 lttv_hooks_call(events_request->before_request, (gpointer)tsc);
1244 events_request->servicing = TRUE;
1245 }
1246 /* call before chunk
1247 * events hooks added
1248 */
1249 if(events_request->trace == -1)
1250 lttv_process_traceset_begin(tsc,
1251 events_request->before_chunk_traceset,
1252 events_request->before_chunk_trace,
1253 events_request->before_chunk_tracefile,
1254 events_request->event,
1255 events_request->event_by_id);
1256 else {
1257 guint nb_trace = lttv_traceset_number(tsc->ts);
1258 g_assert((guint)events_request->trace < nb_trace &&
1259 events_request->trace > -1);
1260 LttvTraceContext *tc = tsc->traces[events_request->trace];
1261
1262 lttv_hooks_call(events_request->before_chunk_traceset, tsc);
1263
1264 lttv_trace_context_add_hooks(tc,
1265 events_request->before_chunk_trace,
1266 events_request->before_chunk_tracefile,
1267 events_request->event,
1268 events_request->event_by_id);
1269 }
1270
1271
1272 }
1273
1274 /* Go to next */
1275 if(remove)
1276 {
1277 GSList *remove_iter = iter;
1278
1279 iter = g_slist_next(iter);
1280 if(free_data) events_request_free((EventsRequest*)remove_iter->data);
1281 list_out = g_slist_remove_link(list_out, remove_iter);
1282 } else { // not remove
1283 iter = g_slist_next(iter);
1284 }
1285 }
1286 }
1287 }
1288
1289 /* 3. Find end criterions */
1290 {
1291 /* 3.1 End time */
1292 GSList *iter;
1293
1294 /* 3.1.1 Find lowest end time in list_in */
1295 g_assert(g_slist_length(list_in)>0);
1296 end_time = ((EventsRequest*)g_slist_nth_data(list_in,0))->end_time;
1297
1298 for(iter=g_slist_nth(list_in,1);iter!=NULL;iter=g_slist_next(iter)) {
1299 EventsRequest *events_request = (EventsRequest*)iter->data;
1300
1301 if(ltt_time_compare(events_request->end_time,
1302 end_time) < 0)
1303 end_time = events_request->end_time;
1304 }
1305
1306 /* 3.1.2 Find lowest start time in list_out */
1307 for(iter=list_out;iter!=NULL;iter=g_slist_next(iter)) {
1308 EventsRequest *events_request = (EventsRequest*)iter->data;
1309
1310 if(ltt_time_compare(events_request->start_time,
1311 end_time) < 0)
1312 end_time = events_request->start_time;
1313 }
1314 }
1315
1316 {
1317 /* 3.2 Number of events */
1318
1319 /* 3.2.1 Find lowest number of events in list_in */
1320 GSList *iter;
1321
1322 end_nb_events = ((EventsRequest*)g_slist_nth_data(list_in,0))->num_events;
1323
1324 for(iter=g_slist_nth(list_in,1);iter!=NULL;iter=g_slist_next(iter)) {
1325 EventsRequest *events_request = (EventsRequest*)iter->data;
1326
1327 if(events_request->num_events < end_nb_events)
1328 end_nb_events = events_request->num_events;
1329 }
1330
1331 /* 3.2.2 Use min(CHUNK_NUM_EVENTS, min num events in list_in) as
1332 * num_events */
1333
1334 end_nb_events = MIN(CHUNK_NUM_EVENTS, end_nb_events);
1335 }
1336
1337 {
1338 /* 3.3 End position */
1339
1340 /* 3.3.1 Find lowest end position in list_in */
1341 GSList *iter;
1342
1343 end_position =((EventsRequest*)g_slist_nth_data(list_in,0))->end_position;
1344
1345 for(iter=g_slist_nth(list_in,1);iter!=NULL;iter=g_slist_next(iter)) {
1346 EventsRequest *events_request = (EventsRequest*)iter->data;
1347
1348 if(events_request->end_position != NULL && end_position != NULL &&
1349 lttv_traceset_context_pos_pos_compare(events_request->end_position,
1350 end_position) <0)
1351 end_position = events_request->end_position;
1352 }
1353 }
1354
1355 {
1356 /* 3.3.2 Find lowest start position in list_out */
1357 GSList *iter;
1358
1359 for(iter=list_out;iter!=NULL;iter=g_slist_next(iter)) {
1360 EventsRequest *events_request = (EventsRequest*)iter->data;
1361
1362 if(events_request->end_position != NULL && end_position != NULL &&
1363 lttv_traceset_context_pos_pos_compare(events_request->end_position,
1364 end_position) <0)
1365 end_position = events_request->end_position;
1366 }
1367 }
1368
1369 {
1370 /* 4. Call process traceset middle */
1371 g_debug("Calling process traceset middle with %p, %lu sec %lu nsec, %u nb ev, %p end pos", tsc, end_time.tv_sec, end_time.tv_nsec, end_nb_events, end_position);
1372 count = lttv_process_traceset_middle(tsc, end_time, end_nb_events, end_position);
1373
1374 tfc = lttv_traceset_context_get_current_tfc(tsc);
1375 if(tfc != NULL)
1376 g_debug("Context time after middle : %lu, %lu", tfc->timestamp.tv_sec,
1377 tfc->timestamp.tv_nsec);
1378 else
1379 g_debug("End of trace reached after middle.");
1380
1381 }
1382 {
1383 /* 5. After process traceset middle */
1384 tfc = lttv_traceset_context_get_current_tfc(tsc);
1385
1386 /* - if current context time > traceset.end time */
1387 if(tfc == NULL || ltt_time_compare(tfc->timestamp,
1388 tsc->time_span.end_time) > 0) {
1389 /* - For each req in list_in */
1390 GSList *iter = list_in;
1391
1392 while(iter != NULL) {
1393
1394 gboolean remove = FALSE;
1395 gboolean free_data = FALSE;
1396 EventsRequest *events_request = (EventsRequest *)iter->data;
1397
1398 /* - Remove events hooks for req
1399 * - Call end chunk for req
1400 */
1401
1402 if(events_request->trace == -1)
1403 lttv_process_traceset_end(tsc,
1404 events_request->after_chunk_traceset,
1405 events_request->after_chunk_trace,
1406 events_request->after_chunk_tracefile,
1407 events_request->event,
1408 events_request->event_by_id);
1409
1410 else {
1411 guint nb_trace = lttv_traceset_number(tsc->ts);
1412 g_assert(events_request->trace < nb_trace &&
1413 events_request->trace > -1);
1414 LttvTraceContext *tc = tsc->traces[events_request->trace];
1415
1416 lttv_trace_context_remove_hooks(tc,
1417 events_request->after_chunk_trace,
1418 events_request->after_chunk_tracefile,
1419 events_request->event,
1420 events_request->event_by_id);
1421 lttv_hooks_call(events_request->after_chunk_traceset, tsc);
1422
1423
1424 }
1425
1426 /* - Call end request for req */
1427 lttv_hooks_call(events_request->after_request, (gpointer)tsc);
1428
1429 /* - remove req from list_in */
1430 /* Destroy the request */
1431 remove = TRUE;
1432 free_data = TRUE;
1433
1434 /* Go to next */
1435 if(remove)
1436 {
1437 GSList *remove_iter = iter;
1438
1439 iter = g_slist_next(iter);
1440 if(free_data) events_request_free((EventsRequest*)remove_iter->data);
1441 list_in = g_slist_remove_link(list_in, remove_iter);
1442 } else { // not remove
1443 iter = g_slist_next(iter);
1444 }
1445 }
1446 }
1447 {
1448 /* 5.1 For each req in list_in */
1449 GSList *iter = list_in;
1450
1451 while(iter != NULL) {
1452
1453 gboolean remove = FALSE;
1454 gboolean free_data = FALSE;
1455 EventsRequest *events_request = (EventsRequest *)iter->data;
1456
1457 /* - Remove events hooks for req
1458 * - Call end chunk for req
1459 */
1460 if(events_request->trace == -1)
1461 lttv_process_traceset_end(tsc,
1462 events_request->after_chunk_traceset,
1463 events_request->after_chunk_trace,
1464 events_request->after_chunk_tracefile,
1465 events_request->event,
1466 events_request->event_by_id);
1467
1468 else {
1469 guint nb_trace = lttv_traceset_number(tsc->ts);
1470 g_assert(events_request->trace < nb_trace &&
1471 events_request->trace > -1);
1472 LttvTraceContext *tc = tsc->traces[events_request->trace];
1473
1474 lttv_trace_context_remove_hooks(tc,
1475 events_request->after_chunk_trace,
1476 events_request->after_chunk_tracefile,
1477 events_request->event,
1478 events_request->event_by_id);
1479
1480 lttv_hooks_call(events_request->after_chunk_traceset, tsc);
1481 }
1482
1483 /* - req.num -= count */
1484 g_assert(events_request->num_events >= count);
1485 events_request->num_events -= count;
1486
1487 g_assert(tfc != NULL);
1488 /* - if req.num == 0
1489 * or
1490 * current context time >= req.end time
1491 * or
1492 * req.end pos == current pos
1493 * or
1494 * req.stop_flag == TRUE
1495 */
1496 if( events_request->num_events == 0
1497 ||
1498 events_request->stop_flag == TRUE
1499 ||
1500 ltt_time_compare(tfc->timestamp,
1501 events_request->end_time) >= 0
1502 ||
1503 (events_request->end_position != NULL
1504 &&
1505 lttv_traceset_context_ctx_pos_compare(tsc,
1506 events_request->end_position) == 0)
1507
1508 ) {
1509 g_assert(events_request->servicing == TRUE);
1510 /* - Call end request for req
1511 * - remove req from list_in */
1512 lttv_hooks_call(events_request->after_request, (gpointer)tsc);
1513 /* - remove req from list_in */
1514 /* Destroy the request */
1515 remove = TRUE;
1516 free_data = TRUE;
1517 }
1518
1519 /* Go to next */
1520 if(remove)
1521 {
1522 GSList *remove_iter = iter;
1523
1524 iter = g_slist_next(iter);
1525 if(free_data) events_request_free((EventsRequest*)remove_iter->data);
1526 list_in = g_slist_remove_link(list_in, remove_iter);
1527 } else { // not remove
1528 iter = g_slist_next(iter);
1529 }
1530 }
1531 }
1532 }
1533 }
1534 /* End of removed servicing loop : leave control to GTK instead. */
1535 // if(gtk_events_pending()) break;
1536 //}
1537
1538 /* B. When interrupted between chunks */
1539
1540 {
1541 GSList *iter = list_in;
1542
1543 /* 1. for each request in list_in */
1544 while(iter != NULL) {
1545
1546 gboolean remove = FALSE;
1547 gboolean free_data = FALSE;
1548 EventsRequest *events_request = (EventsRequest *)iter->data;
1549
1550 /* 1.1. Use current postition as start position */
1551 if(events_request->start_position != NULL)
1552 lttv_traceset_context_position_destroy(events_request->start_position);
1553 events_request->start_position = lttv_traceset_context_position_new(tsc);
1554 lttv_traceset_context_position_save(tsc, events_request->start_position);
1555
1556 /* 1.2. Remove start time */
1557 events_request->start_time = ltt_time_infinite;
1558
1559 /* 1.3. Move from list_in to list_out */
1560 remove = TRUE;
1561 free_data = FALSE;
1562 list_out = g_slist_append(list_out, events_request);
1563
1564 /* Go to next */
1565 if(remove)
1566 {
1567 GSList *remove_iter = iter;
1568
1569 iter = g_slist_next(iter);
1570 if(free_data) events_request_free((EventsRequest*)remove_iter->data);
1571 list_in = g_slist_remove_link(list_in, remove_iter);
1572 } else { // not remove
1573 iter = g_slist_next(iter);
1574 }
1575 }
1576
1577
1578 }
1579 /* C Unlock Traces */
1580 {
1581 lttv_process_traceset_get_sync_data(tsc);
1582 //lttv_traceset_context_position_save(tsc, sync_position);
1583
1584 guint iter_trace;
1585
1586 for(iter_trace=0;
1587 iter_trace<lttv_traceset_number(tsc->ts);
1588 iter_trace++) {
1589 LttvTrace *trace_v = lttv_traceset_get(tsc->ts, iter_trace);
1590
1591 lttvwindowtraces_unlock(trace_v);
1592 }
1593 }
1594 #if 0
1595 //set the cursor back to normal
1596 gdk_window_set_cursor(win, NULL);
1597 #endif //0
1598
1599 g_assert(g_slist_length(list_in) == 0);
1600
1601 if( g_slist_length(list_out) == 0 ) {
1602 /* Put tab's request pending flag back to normal */
1603 tab->events_request_pending = FALSE;
1604 g_debug("remove the idle fct");
1605 return FALSE; /* Remove the idle function */
1606 }
1607 g_debug("leave the idle fct");
1608 return TRUE; /* Leave the idle function */
1609
1610 /* We do not use simili-round-robin, it may require to read 1 meg buffers
1611 * again and again if many tracesets use the same tracefiles. */
1612 /* Hack for round-robin idle functions */
1613 /* It will put the idle function at the end of the pool */
1614 /*g_idle_add_full((G_PRIORITY_HIGH_IDLE + 21),
1615 (GSourceFunc)execute_events_requests,
1616 tab,
1617 NULL);
1618 return FALSE;
1619 */
1620 }
1621
1622 #undef list_out
1623
1624
1625 static void lttvwindow_add_trace(Tab *tab, LttvTrace *trace_v)
1626 {
1627 LttvTraceset *traceset = tab->traceset_info->traceset;
1628 guint i;
1629 guint num_traces = lttv_traceset_number(traceset);
1630
1631 //Verify if trace is already present.
1632 for(i=0; i<num_traces; i++)
1633 {
1634 LttvTrace * trace = lttv_traceset_get(traceset, i);
1635 if(trace == trace_v)
1636 return;
1637 }
1638
1639 //Keep a reference to the traces so they are not freed.
1640 for(i=0; i<lttv_traceset_number(traceset); i++)
1641 {
1642 LttvTrace * trace = lttv_traceset_get(traceset, i);
1643 lttv_trace_ref(trace);
1644 }
1645
1646 //remove state update hooks
1647 lttv_state_remove_event_hooks(
1648 (LttvTracesetState*)tab->traceset_info->traceset_context);
1649
1650 lttv_context_fini(LTTV_TRACESET_CONTEXT(
1651 tab->traceset_info->traceset_context));
1652 g_object_unref(tab->traceset_info->traceset_context);
1653
1654 lttv_traceset_add(traceset, trace_v);
1655 lttv_trace_ref(trace_v); /* local ref */
1656
1657 /* Create new context */
1658 tab->traceset_info->traceset_context =
1659 g_object_new(LTTV_TRACESET_STATS_TYPE, NULL);
1660 lttv_context_init(
1661 LTTV_TRACESET_CONTEXT(tab->traceset_info->
1662 traceset_context),
1663 traceset);
1664
1665
1666 //add state update hooks
1667 lttv_state_add_event_hooks(
1668 (LttvTracesetState*)tab->traceset_info->traceset_context);
1669 //Remove local reference to the traces.
1670 for(i=0; i<lttv_traceset_number(traceset); i++)
1671 {
1672 LttvTrace * trace = lttv_traceset_get(traceset, i);
1673 lttv_trace_unref(trace);
1674 }
1675
1676 //FIXME
1677 //add_trace_into_traceset_selector(GTK_MULTIVPANED(tab->multivpaned), lttv_trace(trace_v));
1678 }
1679
1680 /* add_trace adds a trace into the current traceset. It first displays a
1681 * directory selection dialogue to let user choose a trace, then recreates
1682 * tracset_context, and redraws all the viewer of the current tab
1683 */
1684
1685 void add_trace(GtkWidget * widget, gpointer user_data)
1686 {
1687 LttTrace *trace;
1688 LttvTrace * trace_v;
1689 LttvTraceset * traceset;
1690 const char * dir;
1691 char abs_path[PATH_MAX];
1692 gint id;
1693 MainWindow * mw_data = get_window_data_struct(widget);
1694 GtkWidget * notebook = lookup_widget(widget, "MNotebook");
1695
1696 GtkWidget *page = gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook),
1697 gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook)));
1698 Tab *tab;
1699
1700 if(!page) {
1701 tab = create_new_tab(widget, NULL);
1702 } else {
1703 tab = (Tab *)g_object_get_data(G_OBJECT(page), "Tab_Info");
1704 }
1705
1706 //GtkDirSelection * file_selector = (GtkDirSelection *)gtk_dir_selection_new("Select a trace");
1707 GtkFileSelection * file_selector = (GtkFileSelection *)gtk_file_selection_new("Select a trace");
1708 gtk_widget_hide( (file_selector)->file_list->parent) ;
1709 gtk_file_selection_hide_fileop_buttons(file_selector);
1710 gtk_window_set_transient_for(GTK_WINDOW(file_selector),
1711 GTK_WINDOW(mw_data->mwindow));
1712
1713 if(remember_trace_dir[0] != '\0')
1714 gtk_file_selection_set_filename(file_selector, remember_trace_dir);
1715
1716 id = gtk_dialog_run(GTK_DIALOG(file_selector));
1717 switch(id){
1718 case GTK_RESPONSE_ACCEPT:
1719 case GTK_RESPONSE_OK:
1720 dir = gtk_file_selection_get_filename (file_selector);
1721 strncpy(remember_trace_dir, dir, PATH_MAX);
1722 strncat(remember_trace_dir, "/", PATH_MAX);
1723 if(!dir || strlen(dir) == 0){
1724 gtk_widget_destroy((GtkWidget*)file_selector);
1725 break;
1726 }
1727 get_absolute_pathname(dir, abs_path);
1728 trace_v = lttvwindowtraces_get_trace_by_name(abs_path);
1729 if(trace_v == NULL) {
1730 trace = ltt_trace_open(abs_path);
1731 if(trace == NULL) {
1732 g_warning("cannot open trace %s", abs_path);
1733 } else {
1734 trace_v = lttv_trace_new(trace);
1735 lttvwindowtraces_add_trace(trace_v);
1736 lttvwindow_add_trace(tab, trace_v);
1737 }
1738 } else {
1739 lttvwindow_add_trace(tab, trace_v);
1740 }
1741
1742 gtk_widget_destroy((GtkWidget*)file_selector);
1743
1744 //update current tab
1745 //update_traceset(mw_data);
1746
1747 /* Call the updatetraceset hooks */
1748
1749 traceset = tab->traceset_info->traceset;
1750 SetTraceset(tab, traceset);
1751 // in expose now call_pending_read_hooks(mw_data);
1752
1753 //lttvwindow_report_current_time(mw_data,&(tab->current_time));
1754 break;
1755 case GTK_RESPONSE_REJECT:
1756 case GTK_RESPONSE_CANCEL:
1757 default:
1758 gtk_widget_destroy((GtkWidget*)file_selector);
1759 break;
1760 }
1761 }
1762
1763 /* remove_trace removes a trace from the current traceset if all viewers in
1764 * the current tab are not interested in the trace. It first displays a
1765 * dialogue, which shows all traces in the current traceset, to let user choose
1766 * a trace, then it checks if all viewers unselect the trace, if it is true,
1767 * it will remove the trace, recreate the traceset_contex,
1768 * and redraws all the viewer of the current tab. If there is on trace in the
1769 * current traceset, it will delete all viewers of the current tab
1770 *
1771 * It destroys the filter tree. FIXME... we should request for an update
1772 * instead.
1773 */
1774
1775 void remove_trace(GtkWidget *widget, gpointer user_data)
1776 {
1777 LttTrace *trace;
1778 LttvTrace * trace_v;
1779 LttvTraceset * traceset;
1780 gint i, j, nb_trace, index=-1;
1781 char ** name, *remove_trace_name;
1782 MainWindow * mw_data = get_window_data_struct(widget);
1783 GtkWidget * notebook = lookup_widget(widget, "MNotebook");
1784
1785 GtkWidget *page = gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook),
1786 gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook)));
1787 Tab *tab;
1788
1789 if(!page) {
1790 return;
1791 } else {
1792 tab = (Tab *)g_object_get_data(G_OBJECT(page), "Tab_Info");
1793 }
1794
1795 nb_trace =lttv_traceset_number(tab->traceset_info->traceset);
1796 name = g_new(char*,nb_trace);
1797 for(i = 0; i < nb_trace; i++){
1798 trace_v = lttv_traceset_get(tab->traceset_info->traceset, i);
1799 trace = lttv_trace(trace_v);
1800 name[i] = g_quark_to_string(ltt_trace_name(trace));
1801 }
1802
1803 remove_trace_name = get_remove_trace(mw_data, name, nb_trace);
1804
1805
1806 if(remove_trace_name){
1807
1808 /* yuk, cut n paste from old code.. should be better (MD)*/
1809 for(i = 0; i<nb_trace; i++) {
1810 if(strcmp(remove_trace_name,name[i]) == 0){
1811 index = i;
1812 }
1813 }
1814
1815 traceset = tab->traceset_info->traceset;
1816 //Keep a reference to the traces so they are not freed.
1817 for(j=0; j<lttv_traceset_number(traceset); j++)
1818 {
1819 LttvTrace * trace = lttv_traceset_get(traceset, j);
1820 lttv_trace_ref(trace);
1821 }
1822
1823 //remove state update hooks
1824 lttv_state_remove_event_hooks(
1825 (LttvTracesetState*)tab->traceset_info->traceset_context);
1826 lttv_context_fini(LTTV_TRACESET_CONTEXT(tab->traceset_info->traceset_context));
1827 g_object_unref(tab->traceset_info->traceset_context);
1828
1829 trace_v = lttv_traceset_get(traceset, index);
1830
1831 lttv_traceset_remove(traceset, index);
1832 lttv_trace_unref(trace_v); // Remove local reference
1833
1834 if(lttv_trace_get_ref_number(trace_v) <= 1) {
1835 /* ref 1 : lttvwindowtraces only*/
1836 ltt_trace_close(lttv_trace(trace_v));
1837 /* lttvwindowtraces_remove_trace takes care of destroying
1838 * the traceset linked with the trace_v and also of destroying
1839 * the trace_v at the same time.
1840 */
1841 lttvwindowtraces_remove_trace(trace_v);
1842 }
1843
1844 tab->traceset_info->traceset_context =
1845 g_object_new(LTTV_TRACESET_STATS_TYPE, NULL);
1846 lttv_context_init(
1847 LTTV_TRACESET_CONTEXT(tab->
1848 traceset_info->traceset_context),traceset);
1849 //add state update hooks
1850 lttv_state_add_event_hooks(
1851 (LttvTracesetState*)tab->traceset_info->traceset_context);
1852
1853 //Remove local reference to the traces.
1854 for(j=0; j<lttv_traceset_number(traceset); j++)
1855 {
1856 LttvTrace * trace = lttv_traceset_get(traceset, j);
1857 lttv_trace_unref(trace);
1858 }
1859
1860 SetTraceset(tab, (gpointer)traceset);
1861 }
1862 g_free(name);
1863 }
1864
1865 #if 0
1866 void remove_trace(GtkWidget * widget, gpointer user_data)
1867 {
1868 LttTrace *trace;
1869 LttvTrace * trace_v;
1870 LttvTraceset * traceset;
1871 gint i, j, nb_trace;
1872 char ** name, *remove_trace_name;
1873 MainWindow * mw_data = get_window_data_struct(widget);
1874 LttvTracesetSelector * s;
1875 LttvTraceSelector * t;
1876 GtkWidget * w;
1877 gboolean selected;
1878 GtkWidget * notebook = lookup_widget(widget, "MNotebook");
1879
1880 GtkWidget *page = gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook),
1881 gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook)));
1882 Tab *tab;
1883
1884 if(!page) {
1885 return;
1886 } else {
1887 tab = (Tab *)g_object_get_data(G_OBJECT(page), "Tab_Info");
1888 }
1889
1890 nb_trace =lttv_traceset_number(tab->traceset_info->traceset);
1891 name = g_new(char*,nb_trace);
1892 for(i = 0; i < nb_trace; i++){
1893 trace_v = lttv_traceset_get(tab->traceset_info->traceset, i);
1894 trace = lttv_trace(trace_v);
1895 name[i] = ltt_trace_name(trace);
1896 }
1897
1898 remove_trace_name = get_remove_trace(name, nb_trace);
1899
1900 if(remove_trace_name){
1901 for(i=0; i<nb_trace; i++){
1902 if(strcmp(remove_trace_name,name[i]) == 0){
1903 //unselect the trace from the current viewer
1904 //FIXME
1905 w = gtk_multivpaned_get_widget(GTK_MULTIVPANED(tab->multivpaned));
1906 if(w){
1907 s = g_object_get_data(G_OBJECT(w), "Traceset_Selector");
1908 if(s){
1909 t = lttv_traceset_selector_trace_get(s,i);
1910 lttv_trace_selector_set_selected(t, FALSE);
1911 }
1912
1913 //check if other viewers select the trace
1914 w = gtk_multivpaned_get_first_widget(GTK_MULTIVPANED(tab->multivpaned));
1915 while(w){
1916 s = g_object_get_data(G_OBJECT(w), "Traceset_Selector");
1917 if(s){
1918 t = lttv_traceset_selector_trace_get(s,i);
1919 selected = lttv_trace_selector_get_selected(t);
1920 if(selected)break;
1921 }
1922 w = gtk_multivpaned_get_next_widget(GTK_MULTIVPANED(tab->multivpaned));
1923 }
1924 }else selected = FALSE;
1925
1926 //if no viewer selects the trace, remove it
1927 if(!selected){
1928 remove_trace_from_traceset_selector(GTK_MULTIVPANED(tab->multivpaned), i);
1929
1930 traceset = tab->traceset_info->traceset;
1931 //Keep a reference to the traces so they are not freed.
1932 for(j=0; j<lttv_traceset_number(traceset); j++)
1933 {
1934 LttvTrace * trace = lttv_traceset_get(traceset, j);
1935 lttv_trace_ref(trace);
1936 }
1937
1938 //remove state update hooks
1939 lttv_state_remove_event_hooks(
1940 (LttvTracesetState*)tab->traceset_info->traceset_context);
1941 lttv_context_fini(LTTV_TRACESET_CONTEXT(tab->traceset_info->traceset_context));
1942 g_object_unref(tab->traceset_info->traceset_context);
1943
1944
1945 trace_v = lttv_traceset_get(traceset, i);
1946
1947 if(lttv_trace_get_ref_number(trace_v) <= 2) {
1948 /* ref 2 : traceset, local */
1949 lttvwindowtraces_remove_trace(trace_v);
1950 ltt_trace_close(lttv_trace(trace_v));
1951 }
1952
1953 lttv_traceset_remove(traceset, i);
1954 lttv_trace_unref(trace_v); // Remove local reference
1955
1956 if(!lttv_trace_get_ref_number(trace_v))
1957 lttv_trace_destroy(trace_v);
1958
1959 tab->traceset_info->traceset_context =
1960 g_object_new(LTTV_TRACESET_STATS_TYPE, NULL);
1961 lttv_context_init(
1962 LTTV_TRACESET_CONTEXT(tab->
1963 traceset_info->traceset_context),traceset);
1964 //add state update hooks
1965 lttv_state_add_event_hooks(
1966 (LttvTracesetState*)tab->traceset_info->traceset_context);
1967
1968 //Remove local reference to the traces.
1969 for(j=0; j<lttv_traceset_number(traceset); j++)
1970 {
1971 LttvTrace * trace = lttv_traceset_get(traceset, j);
1972 lttv_trace_unref(trace);
1973 }
1974
1975
1976 //update current tab
1977 //update_traceset(mw_data);
1978 //if(nb_trace > 1){
1979
1980 SetTraceset(tab, (gpointer)traceset);
1981 // in expose now call_pending_read_hooks(mw_data);
1982
1983 //lttvwindow_report_current_time(mw_data,&(tab->current_time));
1984 //}else{
1985 // if(tab){
1986 // while(tab->multi_vpaned->num_children){
1987 // gtk_multi_vpaned_widget_delete(tab->multi_vpaned);
1988 // }
1989 // }
1990 //}
1991 }
1992 break;
1993 }
1994 }
1995 }
1996
1997 g_free(name);
1998 }
1999 #endif //0
2000
2001 /* Redraw all the viewers in the current tab */
2002 void redraw(GtkWidget *widget, gpointer user_data)
2003 {
2004 GtkWidget * notebook = lookup_widget(widget, "MNotebook");
2005 GtkWidget *page = gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook),
2006 gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook)));
2007 Tab *tab;
2008 if(!page) {
2009 return;
2010 } else {
2011 tab = (Tab *)g_object_get_data(G_OBJECT(page), "Tab_Info");
2012 }
2013
2014 LttvHooks * tmp;
2015 LttvAttributeValue value;
2016
2017 g_assert(lttv_iattribute_find_by_path(tab->attributes, "hooks/redraw", LTTV_POINTER, &value));
2018
2019 tmp = (LttvHooks*)*(value.v_pointer);
2020 if(tmp != NULL)
2021 lttv_hooks_call(tmp,NULL);
2022 }
2023
2024
2025 void continue_processing(GtkWidget *widget, gpointer user_data)
2026 {
2027 GtkWidget * notebook = lookup_widget(widget, "MNotebook");
2028 GtkWidget *page = gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook),
2029 gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook)));
2030 Tab *tab;
2031 if(!page) {
2032 return;
2033 } else {
2034 tab = (Tab *)g_object_get_data(G_OBJECT(page), "Tab_Info");
2035 }
2036
2037 LttvHooks * tmp;
2038 LttvAttributeValue value;
2039
2040 g_assert(lttv_iattribute_find_by_path(tab->attributes,
2041 "hooks/continue", LTTV_POINTER, &value));
2042
2043 tmp = (LttvHooks*)*(value.v_pointer);
2044 if(tmp != NULL)
2045 lttv_hooks_call(tmp,NULL);
2046 }
2047
2048 /* Stop the processing for the calling main window's current tab.
2049 * It removes every processing requests that are in its list. It does not call
2050 * the end request hooks, because the request is not finished.
2051 */
2052
2053 void stop_processing(GtkWidget *widget, gpointer user_data)
2054 {
2055 GtkWidget * notebook = lookup_widget(widget, "MNotebook");
2056 GtkWidget *page = gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook),
2057 gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook)));
2058 Tab *tab;
2059 if(!page) {
2060 return;
2061 } else {
2062 tab = (Tab *)g_object_get_data(G_OBJECT(page), "Tab_Info");
2063 }
2064 GSList *iter = tab->events_requests;
2065
2066 while(iter != NULL) {
2067 GSList *remove_iter = iter;
2068 iter = g_slist_next(iter);
2069
2070 g_free(remove_iter->data);
2071 tab->events_requests =
2072 g_slist_remove_link(tab->events_requests, remove_iter);
2073 }
2074 tab->events_request_pending = FALSE;
2075 g_idle_remove_by_data(tab);
2076 g_assert(g_slist_length(tab->events_requests) == 0);
2077 }
2078
2079
2080 /* save will save the traceset to a file
2081 * Not implemented yet FIXME
2082 */
2083
2084 void save(GtkWidget * widget, gpointer user_data)
2085 {
2086 g_info("Save\n");
2087 }
2088
2089 void save_as(GtkWidget * widget, gpointer user_data)
2090 {
2091 g_info("Save as\n");
2092 }
2093
2094
2095 /* zoom will change the time_window of all the viewers of the
2096 * current tab, and redisplay them. The main functionality is to
2097 * determine the new time_window of the current tab
2098 */
2099
2100 void zoom(GtkWidget * widget, double size)
2101 {
2102 TimeInterval time_span;
2103 TimeWindow new_time_window;
2104 LttTime current_time, time_delta;
2105 MainWindow * mw_data = get_window_data_struct(widget);
2106 LttvTracesetContext *tsc;
2107 GtkWidget * notebook = lookup_widget(widget, "MNotebook");
2108
2109 GtkWidget *page = gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook),
2110 gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook)));
2111 Tab *tab;
2112
2113 if(!page) {
2114 return;
2115 } else {
2116 tab = (Tab *)g_object_get_data(G_OBJECT(page), "Tab_Info");
2117 }
2118
2119 if(size == 1) return;
2120
2121 tsc = LTTV_TRACESET_CONTEXT(tab->traceset_info->traceset_context);
2122 time_span = tsc->time_span;
2123 new_time_window = tab->time_window;
2124 current_time = tab->current_time;
2125
2126 time_delta = ltt_time_sub(time_span.end_time,time_span.start_time);
2127 if(size == 0){
2128 new_time_window.start_time = time_span.start_time;
2129 new_time_window.time_width = time_delta;
2130 new_time_window.time_width_double = ltt_time_to_double(time_delta);
2131 new_time_window.end_time = ltt_time_add(new_time_window.start_time,
2132 new_time_window.time_width) ;
2133 }else{
2134 new_time_window.time_width = ltt_time_div(new_time_window.time_width, size);
2135 new_time_window.time_width_double =
2136 ltt_time_to_double(new_time_window.time_width);
2137 if(ltt_time_compare(new_time_window.time_width,time_delta) > 0)
2138 { /* Case where zoom out is bigger than trace length */
2139 new_time_window.start_time = time_span.start_time;
2140 new_time_window.time_width = time_delta;
2141 new_time_window.time_width_double = ltt_time_to_double(time_delta);
2142 new_time_window.end_time = ltt_time_add(new_time_window.start_time,
2143 new_time_window.time_width) ;
2144 }
2145 else
2146 {
2147 /* Center the image on the current time */
2148 new_time_window.start_time =
2149 ltt_time_sub(current_time,
2150 ltt_time_from_double(new_time_window.time_width_double/2.0));
2151 new_time_window.end_time = ltt_time_add(new_time_window.start_time,
2152 new_time_window.time_width) ;
2153 /* If on borders, don't fall off */
2154 if(ltt_time_compare(new_time_window.start_time, time_span.start_time) <0)
2155 {
2156 new_time_window.start_time = time_span.start_time;
2157 new_time_window.end_time = ltt_time_add(new_time_window.start_time,
2158 new_time_window.time_width) ;
2159 }
2160 else
2161 {
2162 if(ltt_time_compare(new_time_window.end_time,
2163 time_span.end_time) > 0)
2164 {
2165 new_time_window.start_time =
2166 ltt_time_sub(time_span.end_time, new_time_window.time_width);
2167
2168 new_time_window.end_time = ltt_time_add(new_time_window.start_time,
2169 new_time_window.time_width) ;
2170 }
2171 }
2172
2173 }
2174 }
2175
2176 if(ltt_time_compare(new_time_window.time_width, ltt_time_zero) == 0) {
2177 g_warning("Zoom more than 1 ns impossible");
2178 } else {
2179 time_change_manager(tab, new_time_window);
2180 }
2181 }
2182
2183 void zoom_in(GtkWidget * widget, gpointer user_data)
2184 {
2185 zoom(widget, 2);
2186 }
2187
2188 void zoom_out(GtkWidget * widget, gpointer user_data)
2189 {
2190 zoom(widget, 0.5);
2191 }
2192
2193 void zoom_extended(GtkWidget * widget, gpointer user_data)
2194 {
2195 zoom(widget, 0);
2196 }
2197
2198 void go_to_time(GtkWidget * widget, gpointer user_data)
2199 {
2200 g_info("Go to time\n");
2201 }
2202
2203 void show_time_frame(GtkWidget * widget, gpointer user_data)
2204 {
2205 g_info("Show time frame\n");
2206 }
2207
2208
2209 /* callback function */
2210
2211 void
2212 on_empty_traceset_activate (GtkMenuItem *menuitem,
2213 gpointer user_data)
2214 {
2215 create_new_window((GtkWidget*)menuitem, user_data, FALSE);
2216 }
2217
2218
2219 void
2220 on_clone_traceset_activate (GtkMenuItem *menuitem,
2221 gpointer user_data)
2222 {
2223 create_new_window((GtkWidget*)menuitem, user_data, TRUE);
2224 }
2225
2226
2227 /* create_new_tab calls create_tab to construct a new tab in the main window
2228 */
2229
2230 Tab *create_new_tab(GtkWidget* widget, gpointer user_data){
2231 gchar label[PATH_MAX];
2232 MainWindow * mw_data = get_window_data_struct(widget);
2233
2234 GtkNotebook * notebook = (GtkNotebook *)lookup_widget(widget, "MNotebook");
2235 if(notebook == NULL){
2236 g_info("Notebook does not exist\n");
2237 return NULL;
2238 }
2239 GtkWidget *page = gtk_notebook_get_nth_page(GTK_NOTEBOOK(notebook),
2240 gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook)));
2241 Tab *copy_tab;
2242
2243 if(!page) {
2244 copy_tab = NULL;
2245 } else {
2246 copy_tab = (Tab *)g_object_get_data(G_OBJECT(page), "Tab_Info");
2247 }
2248
2249 strcpy(label,"Page");
2250 if(get_label(mw_data, label,"Get the name of the tab","Please input tab's name"))
2251 return (create_tab (mw_data, copy_tab, notebook, label));
2252 else
2253 return NULL;
2254 }
2255
2256 void
2257 on_tab_activate (GtkMenuItem *menuitem,
2258 gpointer user_data)
2259 {
2260 create_new_tab((GtkWidget*)menuitem, user_data);
2261 }
2262
2263
2264 void
2265 on_open_activate (GtkMenuItem *menuitem,
2266 gpointer user_data)
2267 {
2268 open_traceset((GtkWidget*)menuitem, user_data);
2269 }
2270
2271
2272 void
2273 on_close_activate (GtkMenuItem *menuitem,
2274 gpointer user_data)
2275 {
2276 MainWindow * mw_data = get_window_data_struct((GtkWidget*)menuitem);
2277 main_window_destructor(mw_data);
2278 }
2279
2280
2281 /* remove the current tab from the main window
2282 */
2283
2284 void
2285 on_close_tab_activate (GtkWidget *widget,
2286 gpointer user_data)
2287 {
2288 gint page_num;
2289 GtkWidget * notebook;
2290 GtkWidget * page;
2291 MainWindow * mw_data = get_window_data_struct(widget);
2292 notebook = lookup_widget(widget, "MNotebook");
2293 if(notebook == NULL){
2294 g_info("Notebook does not exist\n");
2295 return;
2296 }
2297
2298 page_num = gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook));
2299
2300 gtk_notebook_remove_page(GTK_NOTEBOOK(notebook), page_num);
2301
2302 }
2303
2304 void
2305 on_close_tab_X_clicked (GtkWidget *widget,
2306 gpointer user_data)
2307 {
2308 gint page_num;
2309 GtkWidget *notebook = lookup_widget(widget, "MNotebook");
2310 if(notebook == NULL){
2311 g_info("Notebook does not exist\n");
2312 return;
2313 }
2314
2315 if((page_num = gtk_notebook_page_num(GTK_NOTEBOOK(notebook), widget)) != -1)
2316 gtk_notebook_remove_page(GTK_NOTEBOOK(notebook), page_num);
2317
2318 }
2319
2320
2321 void
2322 on_add_trace_activate (GtkMenuItem *menuitem,
2323 gpointer user_data)
2324 {
2325 add_trace((GtkWidget*)menuitem, user_data);
2326 }
2327
2328
2329 void
2330 on_remove_trace_activate (GtkMenuItem *menuitem,
2331 gpointer user_data)
2332 {
2333 remove_trace((GtkWidget*)menuitem, user_data);
2334 }
2335
2336
2337 void
2338 on_save_activate (GtkMenuItem *menuitem,
2339 gpointer user_data)
2340 {
2341 save((GtkWidget*)menuitem, user_data);
2342 }
2343
2344
2345 void
2346 on_save_as_activate (GtkMenuItem *menuitem,
2347 gpointer user_data)
2348 {
2349 save_as((GtkWidget*)menuitem, user_data);
2350 }
2351
2352
2353 void
2354 on_quit_activate (GtkMenuItem *menuitem,
2355 gpointer user_data)
2356 {
2357 mainwindow_quit();
2358 }
2359
2360
2361 void
2362 on_cut_activate (GtkMenuItem *menuitem,
2363 gpointer user_data)
2364 {
2365 g_info("Cut\n");
2366 }
2367
2368
2369 void
2370 on_copy_activate (GtkMenuItem *menuitem,
2371 gpointer user_data)
2372 {
2373 g_info("Copye\n");
2374 }
2375
2376
2377 void
2378 on_paste_activate (GtkMenuItem *menuitem,
2379 gpointer user_data)
2380 {
2381 g_info("Paste\n");
2382 }
2383
2384
2385 void
2386 on_delete_activate (GtkMenuItem *menuitem,
2387 gpointer user_data)
2388 {
2389 g_info("Delete\n");
2390 }
2391
2392
2393 void
2394 on_zoom_in_activate (GtkMenuItem *menuitem,
2395 gpointer user_data)
2396 {
2397 zoom_in((GtkWidget*)menuitem, user_data);
2398 }
2399
2400
2401 void
2402 on_zoom_out_activate (GtkMenuItem *menuitem,
2403 gpointer user_data)
2404 {
2405 zoom_out((GtkWidget*)menuitem, user_data);
2406 }
2407
2408
2409 void
2410 on_zoom_extended_activate (GtkMenuItem *menuitem,
2411 gpointer user_data)
2412 {
2413 zoom_extended((GtkWidget*)menuitem, user_data);
2414 }
2415
2416
2417 void
2418 on_go_to_time_activate (GtkMenuItem *menuitem,
2419 gpointer user_data)
2420 {
2421 go_to_time((GtkWidget*)menuitem, user_data);
2422 }
2423
2424
2425 void
2426 on_show_time_frame_activate (GtkMenuItem *menuitem,
2427 gpointer user_data)
2428 {
2429 show_time_frame((GtkWidget*)menuitem, user_data);
2430 }
2431
2432
2433 void
2434 on_move_viewer_up_activate (GtkMenuItem *menuitem,
2435 gpointer user_data)
2436 {
2437 move_up_viewer((GtkWidget*)menuitem, user_data);
2438 }
2439
2440
2441 void
2442 on_move_viewer_down_activate (GtkMenuItem *menuitem,
2443 gpointer user_data)
2444 {
2445 move_down_viewer((GtkWidget*)menuitem, user_data);
2446 }
2447
2448
2449 void
2450 on_remove_viewer_activate (GtkMenuItem *menuitem,
2451 gpointer user_data)
2452 {
2453 delete_viewer((GtkWidget*)menuitem, user_data);
2454 }
2455
2456 void
2457 on_trace_facility_activate (GtkMenuItem *menuitem,
2458 gpointer user_data)
2459 {
2460 g_info("Trace facility selector: %s\n");
2461 }
2462
2463
2464 /* Dispaly a file selection dialogue to let user select a library, then call
2465 * lttv_library_load().
2466 */
2467
2468 void
2469 on_load_library_activate (GtkMenuItem *menuitem,
2470 gpointer user_data)
2471 {
2472 GError *error = NULL;
2473 MainWindow * mw_data = get_window_data_struct((GtkWidget*)menuitem);
2474
2475 gchar load_module_path_alter[PATH_MAX];
2476 {
2477 GPtrArray *name;
2478 guint nb,i;
2479 gchar *load_module_path;
2480 name = g_ptr_array_new();
2481 nb = lttv_library_path_number();
2482 /* ask for the library path */
2483
2484 for(i=0;i<nb;i++){
2485 gchar *path;
2486 path = lttv_library_path_get(i);
2487 g_ptr_array_add(name, path);
2488 }
2489
2490 load_module_path = get_selection(mw_data,
2491 (char **)(name->pdata), name->len,
2492 "Select a library path", "Library paths");
2493 if(load_module_path != NULL)
2494 strncpy(load_module_path_alter, load_module_path, PATH_MAX-1); // -1 for /
2495
2496 g_ptr_array_free(name, TRUE);
2497
2498 if(load_module_path == NULL) return;
2499 }
2500
2501 {
2502 /* Make sure the module path ends with a / */
2503 gchar *ptr = load_module_path_alter;
2504
2505 ptr = strchr(ptr, '\0');
2506
2507 if(*(ptr-1) != '/') {
2508 *ptr = '/';
2509 *(ptr+1) = '\0';
2510 }
2511 }
2512
2513 {
2514 /* Ask for the library to load : list files in the previously selected
2515 * directory */
2516 gchar str[PATH_MAX];
2517 gchar ** dir;
2518 gint id;
2519 GtkFileSelection * file_selector =
2520 (GtkFileSelection *)gtk_file_selection_new("Select a module");
2521 gtk_file_selection_set_filename(file_selector, load_module_path_alter);
2522 gtk_file_selection_hide_fileop_buttons(file_selector);
2523
2524 gtk_window_set_transient_for(GTK_WINDOW(file_selector),
2525 GTK_WINDOW(mw_data->mwindow));
2526
2527 str[0] = '\0';
2528 id = gtk_dialog_run(GTK_DIALOG(file_selector));
2529 switch(id){
2530 case GTK_RESPONSE_ACCEPT:
2531 case GTK_RESPONSE_OK:
2532 dir = gtk_file_selection_get_selections (file_selector);
2533 strncpy(str,dir[0],PATH_MAX);
2534 strncpy(remember_plugins_dir,dir[0],PATH_MAX);
2535 /* only keep file name */
2536 gchar *str1;
2537 str1 = strrchr(str,'/');
2538 if(str1)str1++;
2539 else{
2540 str1 = strrchr(str,'\\');
2541 str1++;
2542 }
2543 #if 0
2544 /* remove "lib" */
2545 if(*str1 == 'l' && *(str1+1)== 'i' && *(str1+2)=='b')
2546 str1=str1+3;
2547 remove info after . */
2548 {
2549 gchar *str2 = str1;
2550
2551 str2 = strrchr(str2, '.');
2552 if(str2 != NULL) *str2 = '\0';
2553 }
2554 lttv_module_require(str1, &error);
2555 #endif //0
2556 lttv_library_load(str1, &error);
2557 if(error != NULL) g_warning("%s", error->message);
2558 else g_info("Load library: %s\n", str);
2559 g_strfreev(dir);
2560 case GTK_RESPONSE_REJECT:
2561 case GTK_RESPONSE_CANCEL:
2562 default:
2563 gtk_widget_destroy((GtkWidget*)file_selector);
2564 break;
2565 }
2566
2567 }
2568
2569
2570
2571 }
2572
2573
2574 /* Display all loaded modules, let user to select a module to unload
2575 * by calling lttv_module_unload
2576 */
2577
2578 void
2579 on_unload_library_activate (GtkMenuItem *menuitem,
2580 gpointer user_data)
2581 {
2582 MainWindow * mw_data = get_window_data_struct((GtkWidget*)menuitem);
2583
2584 LttvLibrary *library = NULL;
2585
2586 GPtrArray *name;
2587 guint nb,i;
2588 gchar *lib_name;
2589 name = g_ptr_array_new();
2590 nb = lttv_library_number();
2591 LttvLibraryInfo *lib_info = g_new(LttvLibraryInfo,nb);
2592 /* ask for the library name */
2593
2594 for(i=0;i<nb;i++){
2595 LttvLibrary *iter_lib = lttv_library_get(i);
2596 lttv_library_info(iter_lib, &lib_info[i]);
2597
2598 gchar *path = lib_info[i].name;
2599 g_ptr_array_add(name, path);
2600 }
2601 lib_name = get_selection(mw_data, (char **)(name->pdata), name->len,
2602 "Select a library", "Libraries");
2603 if(lib_name != NULL) {
2604 for(i=0;i<nb;i++){
2605 if(strcmp(lib_name, lib_info[i].name) == 0) {
2606 library = lttv_library_get(i);
2607 break;
2608 }
2609 }
2610 }
2611 g_ptr_array_free(name, TRUE);
2612 g_free(lib_info);
2613
2614 if(lib_name == NULL) return;
2615
2616 if(library != NULL) lttv_library_unload(library);
2617 }
2618
2619
2620 /* Dispaly a file selection dialogue to let user select a module, then call
2621 * lttv_module_require().
2622 */
2623
2624 void
2625 on_load_module_activate (GtkMenuItem *menuitem,
2626 gpointer user_data)
2627 {
2628 GError *error = NULL;
2629 MainWindow * mw_data = get_window_data_struct((GtkWidget*)menuitem);
2630
2631 LttvLibrary *library = NULL;
2632 {
2633 GPtrArray *name;
2634 guint nb,i;
2635 gchar *lib_name;
2636 name = g_ptr_array_new();
2637 nb = lttv_library_number();
2638 LttvLibraryInfo *lib_info = g_new(LttvLibraryInfo,nb);
2639 /* ask for the library name */
2640
2641 for(i=0;i<nb;i++){
2642 LttvLibrary *iter_lib = lttv_library_get(i);
2643 lttv_library_info(iter_lib, &lib_info[i]);
2644
2645 gchar *path = lib_info[i].name;
2646 g_ptr_array_add(name, path);
2647 }
2648 lib_name = get_selection(mw_data,(char **)(name->pdata), name->len,
2649 "Select a library", "Libraries");
2650 if(lib_name != NULL) {
2651 for(i=0;i<nb;i++){
2652 if(strcmp(lib_name, lib_info[i].name) == 0) {
2653 library = lttv_library_get(i);
2654 break;
2655 }
2656 }
2657 }
2658 g_ptr_array_free(name, TRUE);
2659 g_free(lib_info);
2660
2661 if(lib_name == NULL) return;
2662 }
2663
2664 //LttvModule *module;
2665 gchar module_name_out[PATH_MAX];
2666 {
2667 /* Ask for the module to load : list modules in the selected lib */
2668 GPtrArray *name;
2669 guint nb,i;
2670 gchar *module_name;
2671 nb = lttv_library_module_number(library);
2672 LttvModuleInfo *module_info = g_new(LttvModuleInfo,nb);
2673 name = g_ptr_array_new();
2674 /* ask for the module name */
2675
2676 for(i=0;i<nb;i++){
2677 LttvModule *iter_module = lttv_library_module_get(library, i);
2678 lttv_module_info(iter_module, &module_info[i]);
2679
2680 gchar *path = module_info[i].name;
2681 g_ptr_array_add(name, path);
2682 }
2683 module_name = get_selection(mw_data, (char **)(name->pdata), name->len,
2684 "Select a module", "Modules");
2685 if(module_name != NULL) {
2686 for(i=0;i<nb;i++){
2687 if(strcmp(module_name, module_info[i].name) == 0) {
2688 strncpy(module_name_out, module_name, PATH_MAX);
2689 //module = lttv_library_module_get(i);
2690 break;
2691 }
2692 }
2693 }
2694
2695 g_ptr_array_free(name, TRUE);
2696 g_free(module_info);
2697
2698 if(module_name == NULL) return;
2699 }
2700
2701 lttv_module_require(module_name_out, &error);
2702 if(error != NULL) g_warning("%s", error->message);
2703 else g_info("Load module: %s", module_name_out);
2704
2705
2706 #if 0
2707 {
2708
2709
2710 gchar str[PATH_MAX];
2711 gchar ** dir;
2712 gint id;
2713 GtkFileSelection * file_selector =
2714 (GtkFileSelection *)gtk_file_selection_new("Select a module");
2715 gtk_file_selection_set_filename(file_selector, load_module_path_alter);
2716 gtk_file_selection_hide_fileop_buttons(file_selector);
2717
2718 str[0] = '\0';
2719 id = gtk_dialog_run(GTK_DIALOG(file_selector));
2720 switch(id){
2721 case GTK_RESPONSE_ACCEPT:
2722 case GTK_RESPONSE_OK:
2723 dir = gtk_file_selection_get_selections (file_selector);
2724 strncpy(str,dir[0],PATH_MAX);
2725 strncpy(remember_plugins_dir,dir[0],PATH_MAX);
2726 {
2727 /* only keep file name */
2728 gchar *str1;
2729 str1 = strrchr(str,'/');
2730 if(str1)str1++;
2731 else{
2732 str1 = strrchr(str,'\\');
2733 str1++;
2734 }
2735 #if 0
2736 /* remove "lib" */
2737 if(*str1 == 'l' && *(str1+1)== 'i' && *(str1+2)=='b')
2738 str1=str1+3;
2739 remove info after . */
2740 {
2741 gchar *str2 = str1;
2742
2743 str2 = strrchr(str2, '.');
2744 if(str2 != NULL) *str2 = '\0';
2745 }
2746 lttv_module_require(str1, &error);
2747 #endif //0
2748 lttv_library_load(str1, &error);
2749 if(error != NULL) g_warning(error->message);
2750 else g_info("Load library: %s\n", str);
2751 g_strfreev(dir);
2752 case GTK_RESPONSE_REJECT:
2753 case GTK_RESPONSE_CANCEL:
2754 default:
2755 gtk_widget_destroy((GtkWidget*)file_selector);
2756 break;
2757 }
2758
2759 }
2760 #endif //0
2761
2762
2763 }
2764
2765
2766
2767 /* Display all loaded modules, let user to select a module to unload
2768 * by calling lttv_module_unload
2769 */
2770
2771 void
2772 on_unload_module_activate (GtkMenuItem *menuitem,
2773 gpointer user_data)
2774 {
2775 GError *error = NULL;
2776 MainWindow * mw_data = get_window_data_struct((GtkWidget*)menuitem);
2777
2778 LttvLibrary *library;
2779 {
2780 GPtrArray *name;
2781 guint nb,i;
2782 gchar *lib_name;
2783 name = g_ptr_array_new();
2784 nb = lttv_library_number();
2785 LttvLibraryInfo *lib_info = g_new(LttvLibraryInfo,nb);
2786 /* ask for the library name */
2787
2788 for(i=0;i<nb;i++){
2789 LttvLibrary *iter_lib = lttv_library_get(i);
2790 lttv_library_info(iter_lib, &lib_info[i]);
2791
2792 gchar *path = lib_info[i].name;
2793 g_ptr_array_add(name, path);
2794 }
2795 lib_name = get_selection(mw_data, (char **)(name->pdata), name->len,
2796 "Select a library", "Libraries");
2797 if(lib_name != NULL) {
2798 for(i=0;i<nb;i++){
2799 if(strcmp(lib_name, lib_info[i].name) == 0) {
2800 library = lttv_library_get(i);
2801 break;
2802 }
2803 }
2804 }
2805 g_ptr_array_free(name, TRUE);
2806 g_free(lib_info);
2807
2808 if(lib_name == NULL) return;
2809 }
2810
2811 LttvModule *module = NULL;
2812 {
2813 /* Ask for the module to load : list modules in the selected lib */
2814 GPtrArray *name;
2815 guint nb,i;
2816 gchar *module_name;
2817 nb = lttv_library_module_number(library);
2818 LttvModuleInfo *module_info = g_new(LttvModuleInfo,nb);
2819 name = g_ptr_array_new();
2820 /* ask for the module name */
2821
2822 for(i=0;i<nb;i++){
2823 LttvModule *iter_module = lttv_library_module_get(library, i);
2824 lttv_module_info(iter_module, &module_info[i]);
2825
2826 gchar *path = module_info[i].name;
2827 if(module_info[i].use_count > 0) g_ptr_array_add(name, path);
2828 }
2829 module_name = get_selection(mw_data, (char **)(name->pdata), name->len,
2830 "Select a module", "Modules");
2831 if(module_name != NULL) {
2832 for(i=0;i<nb;i++){
2833 if(strcmp(module_name, module_info[i].name) == 0) {
2834 module = lttv_library_module_get(library, i);
2835 break;
2836 }
2837 }
2838 }
2839
2840 g_ptr_array_free(name, TRUE);
2841 g_free(module_info);
2842
2843 if(module_name == NULL) return;
2844 }
2845
2846 LttvModuleInfo module_info;
2847 lttv_module_info(module, &module_info);
2848 g_info("Release module: %s\n", module_info.name);
2849
2850 lttv_module_release(module);
2851 }
2852
2853
2854 /* Display a directory dialogue to let user select a path for library searching
2855 */
2856
2857 void
2858 on_add_library_search_path_activate (GtkMenuItem *menuitem,
2859 gpointer user_data)
2860 {
2861 MainWindow * mw_data = get_window_data_struct((GtkWidget*)menuitem);
2862 //GtkDirSelection * file_selector = (GtkDirSelection *)gtk_dir_selection_new("Select library path");
2863 GtkFileSelection * file_selector = (GtkFileSelection *)gtk_file_selection_new("Select a trace");
2864 gtk_widget_hide( (file_selector)->file_list->parent) ;
2865
2866 gtk_window_set_transient_for(GTK_WINDOW(file_selector),
2867 GTK_WINDOW(mw_data->mwindow));
2868
2869 const char * dir;
2870 gint id;
2871
2872 if(remember_plugins_dir[0] != '\0')
2873 gtk_file_selection_set_filename(file_selector, remember_plugins_dir);
2874
2875 id = gtk_dialog_run(GTK_DIALOG(file_selector));
2876 switch(id){
2877 case GTK_RESPONSE_ACCEPT:
2878 case GTK_RESPONSE_OK:
2879 dir = gtk_file_selection_get_filename (file_selector);
2880 strncpy(remember_plugins_dir,dir,PATH_MAX);
2881 strncat(remember_plugins_dir,"/",PATH_MAX);
2882 lttv_library_path_add(dir);
2883 case GTK_RESPONSE_REJECT:
2884 case GTK_RESPONSE_CANCEL:
2885 default:
2886 gtk_widget_destroy((GtkWidget*)file_selector);
2887 break;
2888 }
2889 }
2890
2891
2892 /* Display a directory dialogue to let user select a path for library searching
2893 */
2894
2895 void
2896 on_remove_library_search_path_activate (GtkMenuItem *menuitem,
2897 gpointer user_data)
2898 {
2899 MainWindow * mw_data = get_window_data_struct((GtkWidget*)menuitem);
2900
2901 const char *lib_path;
2902 {
2903 GPtrArray *name;
2904 guint nb,i;
2905 gchar *lib_name;
2906 name = g_ptr_array_new();
2907 nb = lttv_library_path_number();
2908 /* ask for the library name */
2909
2910 for(i=0;i<nb;i++){
2911 gchar *path = lttv_library_path_get(i);
2912 g_ptr_array_add(name, path);
2913 }
2914 lib_path = get_selection(mw_data, (char **)(name->pdata), name->len,
2915 "Select a library path", "Library paths");
2916
2917 g_ptr_array_free(name, TRUE);
2918
2919 if(lib_path == NULL) return;
2920 }
2921
2922 lttv_library_path_remove(lib_path);
2923 }
2924
2925 void
2926 on_color_activate (GtkMenuItem *menuitem,
2927 gpointer user_data)
2928 {
2929 g_info("Color\n");
2930 }
2931
2932
2933 void
2934 on_save_configuration_activate (GtkMenuItem *menuitem,
2935 gpointer user_data)
2936 {
2937 g_info("Save configuration\n");
2938 }
2939
2940
2941 void
2942 on_content_activate (GtkMenuItem *menuitem,
2943 gpointer user_data)
2944 {
2945 g_info("Content\n");
2946 }
2947
2948
2949 static void
2950 on_about_close_activate (GtkButton *button,
2951 gpointer user_data)
2952 {
2953 GtkWidget *about_widget = GTK_WIDGET(user_data);
2954
2955 gtk_widget_destroy(about_widget);
2956 }
2957
2958 void
2959 on_about_activate (GtkMenuItem *menuitem,
2960 gpointer user_data)
2961 {
2962 MainWindow *main_window = get_window_data_struct(GTK_WIDGET(menuitem));
2963 GtkWidget *window_widget = main_window->mwindow;
2964 GtkWidget *about_widget = gtk_window_new(GTK_WINDOW_TOPLEVEL);
2965 GtkWindow *about_window = GTK_WINDOW(about_widget);
2966 gint window_width, window_height;
2967
2968 gtk_window_set_title(about_window, "About Linux Trace Toolkit");
2969
2970 gtk_window_set_resizable(about_window, FALSE);
2971 gtk_window_set_transient_for(GTK_WINDOW(window_widget), about_window);
2972 gtk_window_set_destroy_with_parent(about_window, TRUE);
2973 gtk_window_set_modal(about_window, FALSE);
2974
2975 /* Put the about window at the center of the screen */
2976 gtk_window_get_size(about_window, &window_width, &window_height);
2977 gtk_window_move (about_window,
2978 (gdk_screen_width() - window_width)/2,
2979 (gdk_screen_height() - window_height)/2);
2980
2981 GtkWidget *vbox = gtk_vbox_new(FALSE, 1);
2982
2983 gtk_container_add(GTK_CONTAINER(about_widget), vbox);
2984
2985
2986 /* Text to show */
2987 GtkWidget *label1 = gtk_label_new("");
2988 gtk_misc_set_padding(GTK_MISC(label1), 10, 20);
2989 gtk_label_set_markup(GTK_LABEL(label1), "\
2990 <big>Linux Trace Toolkit</big>");
2991 gtk_label_set_justify(GTK_LABEL(label1), GTK_JUSTIFY_CENTER);
2992
2993 GtkWidget *label2 = gtk_label_new("");
2994 gtk_misc_set_padding(GTK_MISC(label2), 10, 20);
2995 gtk_label_set_markup(GTK_LABEL(label2), "\
2996 Contributors :\n\
2997 \n\
2998 Michel Dagenais (New trace format, lttv main)\n\
2999 Mathieu Desnoyers (Kernel Tracer, Directory structure, build with automake/conf,\n\
3000 lttv gui, control flow view, gui cooperative trace reading\n\
3001 scheduler with interruptible foreground and background\n\
3002 computation, detailed event list (rewrite), trace reading\n\
3003 library (rewrite))\n\
3004 Benoit Des Ligneris, Eric Clement (Cluster adaptation, work in progress)\n\
3005 Xang-Xiu Yang (new trace reading library and converter, lttv gui, \n\
3006 detailed event list and statistics view)\n\
3007 Tom Zanussi (RelayFS)\n\
3008 \n\
3009 Strongly inspired from the original Linux Trace Toolkit Visualizer made by\n\
3010 Karim Yaghmour");
3011
3012 GtkWidget *label3 = gtk_label_new("");
3013 gtk_label_set_markup(GTK_LABEL(label3), "\
3014 Linux Trace Toolkit Viewer, Copyright (C) 2004\n\
3015 Michel Dagenais\n\
3016 Mathieu Desnoyers\n\
3017 Xang-Xiu Yang\n\
3018 Linux Trace Toolkit comes with ABSOLUTELY NO WARRANTY.\n\
3019 This is free software, and you are welcome to redistribute it\n\
3020 under certain conditions. See COPYING for details.");
3021 gtk_misc_set_padding(GTK_MISC(label3), 10, 20);
3022
3023 gtk_box_pack_start_defaults(GTK_BOX(vbox), label1);
3024 gtk_box_pack_start_defaults(GTK_BOX(vbox), label2);
3025 gtk_box_pack_start_defaults(GTK_BOX(vbox), label3);
3026
3027 GtkWidget *hbox = gtk_hbox_new(TRUE, 0);
3028 gtk_box_pack_end(GTK_BOX(vbox), hbox, FALSE, FALSE, 0);
3029 GtkWidget *close_button = gtk_button_new_with_mnemonic("_Close");
3030 gtk_box_pack_end(GTK_BOX(hbox), close_button, FALSE, FALSE, 0);
3031 gtk_container_set_border_width(GTK_CONTAINER(close_button), 20);
3032
3033 g_signal_connect(G_OBJECT(close_button), "clicked",
3034 G_CALLBACK(on_about_close_activate),
3035 (gpointer)about_widget);
3036
3037 gtk_widget_show_all(about_widget);
3038 }
3039
3040
3041 void
3042 on_button_new_clicked (GtkButton *button,
3043 gpointer user_data)
3044 {
3045 create_new_window((GtkWidget*)button, user_data, TRUE);
3046 }
3047
3048 void
3049 on_button_new_tab_clicked (GtkButton *button,
3050 gpointer user_data)
3051 {
3052 create_new_tab((GtkWidget*)button, user_data);
3053 }
3054
3055 void
3056 on_button_open_clicked (GtkButton *button,
3057 gpointer user_data)
3058 {
3059 open_traceset((GtkWidget*)button, user_data);
3060 }
3061
3062
3063 void
3064 on_button_add_trace_clicked (GtkButton *button,
3065 gpointer user_data)
3066 {
3067 add_trace((GtkWidget*)button, user_data);
3068 }
3069
3070
3071 void
3072 on_button_remove_trace_clicked (GtkButton *button,
3073 gpointer user_data)
3074 {
3075 remove_trace((GtkWidget*)button, user_data);
3076 }
3077
3078 void
3079 on_button_redraw_clicked (GtkButton *button,
3080 gpointer user_data)
3081 {
3082 redraw((GtkWidget*)button, user_data);
3083 }
3084
3085 void
3086 on_button_continue_processing_clicked (GtkButton *button,
3087 gpointer user_data)
3088 {
3089 continue_processing((GtkWidget*)button, user_data);
3090 }
3091
3092 void
3093 on_button_stop_processing_clicked (GtkButton *button,
3094 gpointer user_data)
3095 {
3096 stop_processing((GtkWidget*)button, user_data);
3097 }
3098
3099
3100
3101 void
3102 on_button_save_clicked (GtkButton *button,
3103 gpointer user_data)
3104 {
3105 save((GtkWidget*)button, user_data);
3106 }
3107
3108
3109 void
3110 on_button_save_as_clicked (GtkButton *button,
3111 gpointer user_data)
3112 {
3113 save_as((GtkWidget*)button, user_data);
3114 }
3115
3116
3117 void
3118 on_button_zoom_in_clicked (GtkButton *button,
3119 gpointer user_data)
3120 {
3121 zoom_in((GtkWidget*)button, user_data);
3122 }
3123
3124
3125 void
3126 on_button_zoom_out_clicked (GtkButton *button,
3127 gpointer user_data)
3128 {
3129 zoom_out((GtkWidget*)button, user_data);
3130 }
3131
3132
3133 void
3134 on_button_zoom_extended_clicked (GtkButton *button,
3135 gpointer user_data)
3136 {
3137 zoom_extended((GtkWidget*)button, user_data);
3138 }
3139
3140
3141 void
3142 on_button_go_to_time_clicked (GtkButton *button,
3143 gpointer user_data)
3144 {
3145 go_to_time((GtkWidget*)button, user_data);
3146 }
3147
3148
3149 void
3150 on_button_show_time_frame_clicked (GtkButton *button,
3151 gpointer user_data)
3152 {
3153 show_time_frame((GtkWidget*)button, user_data);
3154 }
3155
3156
3157 void
3158 on_button_move_up_clicked (GtkButton *button,
3159 gpointer user_data)
3160 {
3161 move_up_viewer((GtkWidget*)button, user_data);
3162 }
3163
3164
3165 void
3166 on_button_move_down_clicked (GtkButton *button,
3167 gpointer user_data)
3168 {
3169 move_down_viewer((GtkWidget*)button, user_data);
3170 }
3171
3172
3173 void
3174 on_button_delete_viewer_clicked (GtkButton *button,
3175 gpointer user_data)
3176 {
3177 delete_viewer((GtkWidget*)button, user_data);
3178 }
3179
3180 void
3181 on_MWindow_destroy (GtkWidget *widget,
3182 gpointer user_data)
3183 {
3184 MainWindow *main_window = get_window_data_struct(widget);
3185 LttvIAttribute *attributes = main_window->attributes;
3186 LttvAttributeValue value;
3187
3188 //This is unnecessary, since widgets will be destroyed
3189 //by the main window widget anyway.
3190 //remove_all_menu_toolbar_constructors(main_window, NULL);
3191
3192 g_assert(lttv_iattribute_find_by_path(attributes,
3193 "viewers/menu", LTTV_POINTER, &value));
3194 lttv_menus_destroy((LttvMenus*)*(value.v_pointer));
3195
3196 g_assert(lttv_iattribute_find_by_path(attributes,
3197 "viewers/toolbar", LTTV_POINTER, &value));
3198 lttv_toolbars_destroy((LttvToolbars*)*(value.v_pointer));
3199
3200 g_object_unref(main_window->attributes);
3201 g_main_window_list = g_slist_remove(g_main_window_list, main_window);
3202
3203 g_info("There are now : %d windows\n",g_slist_length(g_main_window_list));
3204 if(g_slist_length(g_main_window_list) == 0)
3205 mainwindow_quit();
3206 }
3207
3208 gboolean
3209 on_MWindow_configure (GtkWidget *widget,
3210 GdkEventConfigure *event,
3211 gpointer user_data)
3212 {
3213 MainWindow * mw_data = get_window_data_struct((GtkWidget*)widget);
3214
3215 // MD : removed time width modification upon resizing of the main window.
3216 // The viewers will redraw themselves completely, without time interval
3217 // modification.
3218 /* while(tab){
3219 if(mw_data->window_width){
3220 time_span = LTTV_TRACESET_CONTEXT(tab->traceset_info->traceset_context)->Time_Span ;
3221 time_win = tab->time_window;
3222 ratio = width / mw_data->window_width;
3223 tab->time_window.time_width = ltt_time_mul(time_win.time_width,ratio);
3224 time = ltt_time_sub(time_span->endTime, time_win.start_time);
3225 if(ltt_time_compare(time, tab->time_window.time_width) < 0){
3226 tab->time_window.time_width = time;
3227 }
3228 }
3229 tab = tab->next;
3230 }
3231
3232 mw_data->window_width = (int)width;
3233 */
3234 return FALSE;
3235 }
3236
3237 /* Set current tab
3238 */
3239
3240 void
3241 on_MNotebook_switch_page (GtkNotebook *notebook,
3242 GtkNotebookPage *page,
3243 guint page_num,
3244 gpointer user_data)
3245 {
3246
3247 }
3248
3249
3250 void time_change_manager (Tab *tab,
3251 TimeWindow new_time_window)
3252 {
3253 /* Only one source of time change */
3254 if(tab->time_manager_lock == TRUE) return;
3255
3256 tab->time_manager_lock = TRUE;
3257
3258 LttvTracesetContext *tsc = LTTV_TRACESET_CONTEXT(tab->traceset_info->traceset_context);
3259 TimeInterval time_span = tsc->time_span;
3260 LttTime start_time = new_time_window.start_time;
3261 LttTime end_time = new_time_window.end_time;
3262
3263 g_assert(ltt_time_compare(start_time, end_time) < 0);
3264
3265 /* Set scrollbar */
3266 GtkAdjustment *adjustment = gtk_range_get_adjustment(GTK_RANGE(tab->scrollbar));
3267 LttTime upper = ltt_time_sub(time_span.end_time, time_span.start_time);
3268 #if 0
3269 gtk_range_set_increments(GTK_RANGE(tab->scrollbar),
3270 ltt_time_to_double(new_time_window.time_width)
3271 / SCROLL_STEP_PER_PAGE
3272 * NANOSECONDS_PER_SECOND, /* step increment */
3273 ltt_time_to_double(new_time_window.time_width)
3274 * NANOSECONDS_PER_SECOND); /* page increment */
3275 gtk_range_set_range(GTK_RANGE(tab->scrollbar),
3276 0.0, /* lower */
3277 ltt_time_to_double(upper)
3278 * NANOSECONDS_PER_SECOND); /* upper */
3279 #endif //0
3280 g_object_set(G_OBJECT(adjustment),
3281 "lower",
3282 0.0, /* lower */
3283 "upper",
3284 ltt_time_to_double(upper), /* upper */
3285 "step_increment",
3286 new_time_window.time_width_double
3287 / SCROLL_STEP_PER_PAGE, /* step increment */
3288 "page_increment",
3289 new_time_window.time_width_double,
3290 /* page increment */
3291 "page_size",
3292 new_time_window.time_width_double, /* page size */
3293 NULL);
3294 gtk_adjustment_changed(adjustment);
3295
3296 // g_object_set(G_OBJECT(adjustment),
3297 // "value",
3298 // ltt_time_to_double(
3299 // ltt_time_sub(start_time, time_span.start_time))
3300 // , /* value */
3301 // NULL);
3302 //gtk_adjustment_value_changed(adjustment);
3303 gtk_range_set_value(GTK_RANGE(tab->scrollbar),
3304 ltt_time_to_double(
3305 ltt_time_sub(start_time, time_span.start_time)) /* value */);
3306
3307 /* set the time bar. */
3308 /* start seconds */
3309 gtk_spin_button_set_range(GTK_SPIN_BUTTON(tab->MEntry1),
3310 (double)time_span.start_time.tv_sec,
3311 (double)time_span.end_time.tv_sec);
3312 gtk_spin_button_set_value(GTK_SPIN_BUTTON(tab->MEntry1),
3313 (double)start_time.tv_sec);
3314
3315 /* start nanoseconds */
3316 if(start_time.tv_sec == time_span.start_time.tv_sec) {
3317 /* can be both beginning and end at the same time. */
3318 if(start_time.tv_sec == time_span.end_time.tv_sec) {
3319 /* If we are at the end, max nsec to end.. -1 (not zero length) */
3320 gtk_spin_button_set_range(GTK_SPIN_BUTTON(tab->MEntry2),
3321 (double)time_span.start_time.tv_nsec,
3322 (double)time_span.end_time.tv_nsec-1);
3323 } else {
3324 gtk_spin_button_set_range(GTK_SPIN_BUTTON(tab->MEntry2),
3325 (double)time_span.start_time.tv_nsec,
3326 (double)NANOSECONDS_PER_SECOND-1);
3327 }
3328 } else if(start_time.tv_sec == time_span.end_time.tv_sec) {
3329 /* If we are at the end, max nsec to end.. -1 (not zero length) */
3330 gtk_spin_button_set_range(GTK_SPIN_BUTTON(tab->MEntry2),
3331 0.0,
3332 (double)time_span.end_time.tv_nsec-1);
3333 } else /* anywhere else */
3334 gtk_spin_button_set_range(GTK_SPIN_BUTTON(tab->MEntry2),
3335 0.0,
3336 (double)NANOSECONDS_PER_SECOND-1);
3337 gtk_spin_button_set_value(GTK_SPIN_BUTTON(tab->MEntry2),
3338 (double)start_time.tv_nsec);
3339
3340 /* end seconds */
3341 gtk_spin_button_set_range(GTK_SPIN_BUTTON(tab->MEntry3),
3342 (double)time_span.start_time.tv_sec,
3343 (double)time_span.end_time.tv_sec);
3344 gtk_spin_button_set_value(GTK_SPIN_BUTTON(tab->MEntry3),
3345 (double)end_time.tv_sec);
3346
3347 /* end nanoseconds */
3348 if(end_time.tv_sec == time_span.start_time.tv_sec) {
3349 /* can be both beginning and end at the same time. */
3350 if(end_time.tv_sec == time_span.end_time.tv_sec) {
3351 /* If we are at the end, max nsec to end.. */
3352 gtk_spin_button_set_range(GTK_SPIN_BUTTON(tab->MEntry4),
3353 (double)time_span.start_time.tv_nsec+1,
3354 (double)time_span.end_time.tv_nsec);
3355 } else {
3356 gtk_spin_button_set_range(GTK_SPIN_BUTTON(tab->MEntry4),
3357 (double)time_span.start_time.tv_nsec+1,
3358 (double)NANOSECONDS_PER_SECOND-1);
3359 }
3360 }
3361 else if(end_time.tv_sec == time_span.end_time.tv_sec) {
3362 /* If we are at the end, max nsec to end.. */
3363 gtk_spin_button_set_range(GTK_SPIN_BUTTON(tab->MEntry4),
3364 0.0,
3365 (double)time_span.end_time.tv_nsec);
3366 }
3367 else /* anywhere else */
3368 gtk_spin_button_set_range(GTK_SPIN_BUTTON(tab->MEntry4),
3369 0.0,
3370 (double)NANOSECONDS_PER_SECOND-1);
3371 gtk_spin_button_set_value(GTK_SPIN_BUTTON(tab->MEntry4),
3372 (double)end_time.tv_nsec);
3373
3374 /* call viewer hooks for new time window */
3375 set_time_window(tab, &new_time_window);
3376
3377 tab->time_manager_lock = FALSE;
3378 }
3379
3380
3381 /* value changed for frame start s
3382 *
3383 * Check time span : if ns is out of range, clip it the nearest good value.
3384 */
3385 void
3386 on_MEntry1_value_changed (GtkSpinButton *spinbutton,
3387 gpointer user_data)
3388 {
3389 Tab *tab =(Tab *)user_data;
3390 LttvTracesetContext * tsc =
3391 LTTV_TRACESET_CONTEXT(tab->traceset_info->traceset_context);
3392 TimeInterval time_span = tsc->time_span;
3393 gint value = gtk_spin_button_get_value_as_int(spinbutton);
3394
3395 TimeWindow new_time_window = tab->time_window;
3396
3397 LttTime end_time = new_time_window.end_time;
3398
3399 new_time_window.start_time.tv_sec = value;
3400
3401 /* start nanoseconds */
3402 if(new_time_window.start_time.tv_sec == time_span.start_time.tv_sec) {
3403 if(new_time_window.start_time.tv_sec == time_span.end_time.tv_sec) {
3404 if(new_time_window.start_time.tv_nsec > time_span.end_time.tv_nsec)
3405 new_time_window.start_time.tv_nsec = time_span.end_time.tv_nsec-1;
3406 if(new_time_window.start_time.tv_nsec < time_span.start_time.tv_nsec)
3407 new_time_window.start_time.tv_nsec = time_span.start_time.tv_nsec;
3408 } else {
3409 if(new_time_window.start_time.tv_nsec < time_span.start_time.tv_nsec)
3410 new_time_window.start_time.tv_nsec = time_span.start_time.tv_nsec;
3411 }
3412 }
3413 else if(new_time_window.start_time.tv_sec == time_span.end_time.tv_sec) {
3414 if(new_time_window.start_time.tv_nsec > time_span.end_time.tv_nsec)
3415 new_time_window.start_time.tv_nsec = time_span.end_time.tv_nsec-1;
3416 }
3417
3418 if(ltt_time_compare(new_time_window.start_time, end_time) >= 0) {
3419 /* Then, we must push back end time : keep the same time width
3420 * if possible, else end traceset time */
3421 end_time = LTT_TIME_MIN(ltt_time_add(new_time_window.start_time,
3422 new_time_window.time_width),
3423 time_span.end_time);
3424 }
3425
3426 /* Fix the time width to fit start time and end time */
3427 new_time_window.time_width = ltt_time_sub(end_time,
3428 new_time_window.start_time);
3429 new_time_window.time_width_double =
3430 ltt_time_to_double(new_time_window.time_width);
3431
3432 new_time_window.end_time = end_time;
3433
3434 time_change_manager(tab, new_time_window);
3435
3436 }
3437
3438 void
3439 on_MEntry2_value_changed (GtkSpinButton *spinbutton,
3440 gpointer user_data)
3441 {
3442 Tab *tab =(Tab *)user_data;
3443 LttvTracesetContext * tsc =
3444 LTTV_TRACESET_CONTEXT(tab->traceset_info->traceset_context);
3445 TimeInterval time_span = tsc->time_span;
3446 gint value = gtk_spin_button_get_value_as_int(spinbutton);
3447
3448 TimeWindow new_time_window = tab->time_window;
3449
3450 LttTime end_time = new_time_window.end_time;
3451
3452 new_time_window.start_time.tv_nsec = value;
3453
3454 if(ltt_time_compare(new_time_window.start_time, end_time) >= 0) {
3455 /* Then, we must push back end time : keep the same time width
3456 * if possible, else end traceset time */
3457 end_time = LTT_TIME_MIN(ltt_time_add(new_time_window.start_time,
3458 new_time_window.time_width),
3459 time_span.end_time);
3460 }
3461
3462 /* Fix the time width to fit start time and end time */
3463 new_time_window.time_width = ltt_time_sub(end_time,
3464 new_time_window.start_time);
3465 new_time_window.time_width_double =
3466 ltt_time_to_double(new_time_window.time_width);
3467
3468 new_time_window.end_time = end_time;
3469
3470 time_change_manager(tab, new_time_window);
3471
3472 }
3473
3474 void
3475 on_MEntry3_value_changed (GtkSpinButton *spinbutton,
3476 gpointer user_data)
3477 {
3478 Tab *tab =(Tab *)user_data;
3479 LttvTracesetContext * tsc =
3480 LTTV_TRACESET_CONTEXT(tab->traceset_info->traceset_context);
3481 TimeInterval time_span = tsc->time_span;
3482 gint value = gtk_spin_button_get_value_as_int(spinbutton);
3483
3484 TimeWindow new_time_window = tab->time_window;
3485
3486 LttTime end_time = new_time_window.end_time;
3487
3488 end_time.tv_sec = value;
3489
3490 /* end nanoseconds */
3491 if(end_time.tv_sec == time_span.start_time.tv_sec) {
3492 if(end_time.tv_sec == time_span.end_time.tv_sec) {
3493 if(end_time.tv_nsec > time_span.end_time.tv_nsec)
3494 end_time.tv_nsec = time_span.end_time.tv_nsec;
3495 if(end_time.tv_nsec < time_span.start_time.tv_nsec)
3496 end_time.tv_nsec = time_span.start_time.tv_nsec+1;
3497 } else {
3498 if(end_time.tv_nsec < time_span.start_time.tv_nsec)
3499 end_time.tv_nsec = time_span.start_time.tv_nsec+1;
3500 }
3501 }
3502 else if(end_time.tv_sec == time_span.end_time.tv_sec) {
3503 if(end_time.tv_nsec > time_span.end_time.tv_nsec)
3504 end_time.tv_nsec = time_span.end_time.tv_nsec;
3505 }
3506
3507 if(ltt_time_compare(new_time_window.start_time, end_time) >= 0) {
3508 /* Then, we must push front start time : keep the same time width
3509 * if possible, else end traceset time */
3510 new_time_window.start_time = LTT_TIME_MAX(
3511 ltt_time_sub(end_time,
3512 new_time_window.time_width),
3513 time_span.start_time);
3514 }
3515
3516 /* Fix the time width to fit start time and end time */
3517 new_time_window.time_width = ltt_time_sub(end_time,
3518 new_time_window.start_time);
3519 new_time_window.time_width_double =
3520 ltt_time_to_double(new_time_window.time_width);
3521
3522 new_time_window.end_time = end_time;
3523
3524 time_change_manager(tab, new_time_window);
3525
3526 }
3527
3528 void
3529 on_MEntry4_value_changed (GtkSpinButton *spinbutton,
3530 gpointer user_data)
3531 {
3532 Tab *tab =(Tab *)user_data;
3533 LttvTracesetContext * tsc =
3534 LTTV_TRACESET_CONTEXT(tab->traceset_info->traceset_context);
3535 TimeInterval time_span = tsc->time_span;
3536 gint value = gtk_spin_button_get_value_as_int(spinbutton);
3537
3538 TimeWindow new_time_window = tab->time_window;
3539
3540 LttTime end_time = new_time_window.end_time;
3541
3542 end_time.tv_nsec = value;
3543
3544 if(ltt_time_compare(new_time_window.start_time, end_time) >= 0) {
3545 /* Then, we must push front start time : keep the same time width
3546 * if possible, else end traceset time */
3547 new_time_window.start_time = LTT_TIME_MAX(
3548 ltt_time_sub(end_time,
3549 new_time_window.time_width),
3550 time_span.start_time);
3551 }
3552
3553 /* Fix the time width to fit start time and end time */
3554 new_time_window.time_width = ltt_time_sub(end_time,
3555 new_time_window.start_time);
3556 new_time_window.time_width_double =
3557 ltt_time_to_double(new_time_window.time_width);
3558 new_time_window.end_time = end_time;
3559
3560 time_change_manager(tab, new_time_window);
3561
3562 }
3563
3564
3565 void current_time_change_manager (Tab *tab,
3566 LttTime new_current_time)
3567 {
3568 /* Only one source of time change */
3569 if(tab->current_time_manager_lock == TRUE) return;
3570
3571 tab->current_time_manager_lock = TRUE;
3572
3573 LttvTracesetContext *tsc = LTTV_TRACESET_CONTEXT(tab->traceset_info->traceset_context);
3574 TimeInterval time_span = tsc->time_span;
3575
3576 /* current seconds */
3577 gtk_spin_button_set_range(GTK_SPIN_BUTTON(tab->MEntry5),
3578 (double)time_span.start_time.tv_sec,
3579 (double)time_span.end_time.tv_sec);
3580 gtk_spin_button_set_value(GTK_SPIN_BUTTON(tab->MEntry5),
3581 (double)new_current_time.tv_sec);
3582
3583
3584 /* start nanoseconds */
3585 if(new_current_time.tv_sec == time_span.start_time.tv_sec) {
3586 /* can be both beginning and end at the same time. */
3587 if(new_current_time.tv_sec == time_span.end_time.tv_sec) {
3588 /* If we are at the end, max nsec to end.. */
3589 gtk_spin_button_set_range(GTK_SPIN_BUTTON(tab->MEntry6),
3590 (double)time_span.start_time.tv_nsec,
3591 (double)time_span.end_time.tv_nsec);
3592 } else {
3593 gtk_spin_button_set_range(GTK_SPIN_BUTTON(tab->MEntry6),
3594 (double)time_span.start_time.tv_nsec,
3595 (double)NANOSECONDS_PER_SECOND-1);
3596 }
3597 } else if(new_current_time.tv_sec == time_span.end_time.tv_sec) {
3598 /* If we are at the end, max nsec to end.. */
3599 gtk_spin_button_set_range(GTK_SPIN_BUTTON(tab->MEntry6),
3600 0.0,
3601 (double)time_span.end_time.tv_nsec);
3602 } else /* anywhere else */
3603 gtk_spin_button_set_range(GTK_SPIN_BUTTON(tab->MEntry6),
3604 0.0,
3605 (double)NANOSECONDS_PER_SECOND-1);
3606
3607 gtk_spin_button_set_value(GTK_SPIN_BUTTON(tab->MEntry6),
3608 (double)new_current_time.tv_nsec);
3609
3610 set_current_time(tab, &new_current_time);
3611
3612 tab->current_time_manager_lock = FALSE;
3613 }
3614
3615 void current_position_change_manager(Tab *tab,
3616 LttvTracesetContextPosition *pos)
3617 {
3618 LttvTracesetContext *tsc =
3619 LTTV_TRACESET_CONTEXT(tab->traceset_info->traceset_context);
3620 TimeInterval time_span = tsc->time_span;
3621
3622 g_assert(lttv_process_traceset_seek_position(tsc, pos) == 0);
3623 LttTime new_time = lttv_traceset_context_position_get_time(pos);
3624 /* Put the context in a state coherent position */
3625 lttv_state_traceset_seek_time_closest((LttvTracesetState*)tsc, ltt_time_zero);
3626
3627 current_time_change_manager(tab, new_time);
3628
3629 set_current_position(tab, pos);
3630 }
3631
3632
3633 void
3634 on_MEntry5_value_changed (GtkSpinButton *spinbutton,
3635 gpointer user_data)
3636 {
3637 Tab *tab = (Tab*)user_data;
3638 LttvTracesetContext * tsc =
3639 LTTV_TRACESET_CONTEXT(tab->traceset_info->traceset_context);
3640 TimeInterval time_span = tsc->time_span;
3641 gint value = gtk_spin_button_get_value_as_int(spinbutton);
3642 LttTime new_current_time = tab->current_time;
3643 new_current_time.tv_sec = value;
3644
3645 /* current nanoseconds */
3646 if(new_current_time.tv_sec == time_span.start_time.tv_sec) {
3647 if(new_current_time.tv_sec == time_span.end_time.tv_sec) {
3648 if(new_current_time.tv_nsec > time_span.end_time.tv_nsec)
3649 new_current_time.tv_nsec = time_span.end_time.tv_nsec;
3650 if(new_current_time.tv_nsec < time_span.start_time.tv_nsec)
3651 new_current_time.tv_nsec = time_span.start_time.tv_nsec;
3652 } else {
3653 if(new_current_time.tv_nsec < time_span.start_time.tv_nsec)
3654 new_current_time.tv_nsec = time_span.start_time.tv_nsec;
3655 }
3656 }
3657 else if(new_current_time.tv_sec == time_span.end_time.tv_sec) {
3658 if(new_current_time.tv_nsec > time_span.end_time.tv_nsec)
3659 new_current_time.tv_nsec = time_span.end_time.tv_nsec;
3660 }
3661
3662 current_time_change_manager(tab, new_current_time);
3663 }
3664
3665 void
3666 on_MEntry6_value_changed (GtkSpinButton *spinbutton,
3667 gpointer user_data)
3668 {
3669 Tab *tab = (Tab*)user_data;
3670 gint value = gtk_spin_button_get_value_as_int(spinbutton);
3671 LttTime new_current_time = tab->current_time;
3672 new_current_time.tv_nsec = value;
3673
3674 current_time_change_manager(tab, new_current_time);
3675 }
3676
3677
3678 void scroll_value_changed_cb(GtkWidget *scrollbar,
3679 gpointer user_data)
3680 {
3681 Tab *tab = (Tab *)user_data;
3682 TimeWindow new_time_window;
3683 LttTime time;
3684 GtkAdjustment *adjust = gtk_range_get_adjustment(GTK_RANGE(scrollbar));
3685 gdouble value = gtk_adjustment_get_value(adjust);
3686 // gdouble upper, lower, ratio, page_size;
3687 gdouble page_size;
3688 LttvTracesetContext * tsc =
3689 LTTV_TRACESET_CONTEXT(tab->traceset_info->traceset_context);
3690 TimeInterval time_span = tsc->time_span;
3691
3692 time = ltt_time_add(ltt_time_from_double(value),
3693 time_span.start_time);
3694
3695 new_time_window.start_time = time;
3696
3697 page_size = adjust->page_size;
3698
3699 new_time_window.time_width =
3700 ltt_time_from_double(page_size);
3701
3702 new_time_window.time_width_double =
3703 page_size;
3704
3705 new_time_window.end_time = ltt_time_add(new_time_window.start_time,
3706 new_time_window.time_width);
3707
3708
3709 time_change_manager(tab, new_time_window);
3710 #if 0
3711 //time_window = tab->time_window;
3712
3713 lower = adjust->lower;
3714 upper = adjust->upper;
3715 ratio = (value - lower) / (upper - lower);
3716 g_info("lower %lu, upper %lu, value %lu, ratio %lu", lower, upper, value, ratio);
3717
3718 //time = ltt_time_sub(time_span->end_time, time_span->start_time);
3719 //time = ltt_time_mul(time, (float)ratio);
3720 //time = ltt_time_add(time_span->start_time, time);
3721 time = ltt_time_add(ltt_time_from_double(value),
3722 time_span.start_time);
3723
3724 time_window.start_time = time;
3725
3726 page_size = adjust->page_size;
3727
3728 time_window.time_width =
3729 ltt_time_from_double(page_size);
3730 //time = ltt_time_sub(time_span.end_time, time);
3731 //if(ltt_time_compare(time,time_window.time_width) < 0){
3732 // time_window.time_width = time;
3733 //}
3734
3735 /* call viewer hooks for new time window */
3736 set_time_window(tab, &time_window);
3737 #endif //0
3738 }
3739
3740
3741 /* Display a dialogue showing all eventtypes and traces, let user to select the interested
3742 * eventtypes, tracefiles and traces (filter)
3743 */
3744
3745 /* Select a trace which will be removed from traceset
3746 */
3747
3748 char * get_remove_trace(MainWindow *mw_data,
3749 char ** all_trace_name, int nb_trace)
3750 {
3751 return get_selection(mw_data, all_trace_name, nb_trace,
3752 "Select a trace", "Trace pathname");
3753 }
3754
3755
3756 /* Select a module which will be loaded
3757 */
3758
3759 char * get_load_module(MainWindow *mw_data,
3760 char ** load_module_name, int nb_module)
3761 {
3762 return get_selection(mw_data, load_module_name, nb_module,
3763 "Select a module to load", "Module name");
3764 }
3765
3766
3767
3768
3769 /* Select a module which will be unloaded
3770 */
3771
3772 char * get_unload_module(MainWindow *mw_data,
3773 char ** loaded_module_name, int nb_module)
3774 {
3775 return get_selection(mw_data, loaded_module_name, nb_module,
3776 "Select a module to unload", "Module name");
3777 }
3778
3779
3780 /* Display a dialogue which shows all selectable items, let user to
3781 * select one of them
3782 */
3783
3784 char * get_selection(MainWindow *mw_data,
3785 char ** loaded_module_name, int nb_module,
3786 char *title, char * column_title)
3787 {
3788 GtkWidget * dialogue;
3789 GtkWidget * scroll_win;
3790 GtkWidget * tree;
3791 GtkListStore * store;
3792 GtkTreeViewColumn * column;
3793 GtkCellRenderer * renderer;
3794 GtkTreeSelection * select;
3795 GtkTreeIter iter;
3796 gint id, i;
3797 char * unload_module_name = NULL;
3798
3799 dialogue = gtk_dialog_new_with_buttons(title,
3800 NULL,
3801 GTK_DIALOG_MODAL,
3802 GTK_STOCK_OK,GTK_RESPONSE_ACCEPT,
3803 GTK_STOCK_CANCEL,GTK_RESPONSE_REJECT,
3804 NULL);
3805 gtk_window_set_default_size((GtkWindow*)dialogue, 500, 200);
3806 gtk_window_set_transient_for(GTK_WINDOW(dialogue),
3807 GTK_WINDOW(mw_data->mwindow));
3808
3809 scroll_win = gtk_scrolled_window_new (NULL, NULL);
3810 gtk_widget_show ( scroll_win);
3811 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll_win),
3812 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
3813
3814 store = gtk_list_store_new (N_COLUMNS,G_TYPE_STRING);
3815 tree = gtk_tree_view_new_with_model(GTK_TREE_MODEL (store));
3816 gtk_widget_show ( tree);
3817 g_object_unref (G_OBJECT (store));
3818
3819 renderer = gtk_cell_renderer_text_new ();
3820 column = gtk_tree_view_column_new_with_attributes (column_title,
3821 renderer,
3822 "text", MODULE_COLUMN,
3823 NULL);
3824 gtk_tree_view_column_set_alignment (column, 0.5);
3825 gtk_tree_view_column_set_fixed_width (column, 150);
3826 gtk_tree_view_append_column (GTK_TREE_VIEW (tree), column);
3827
3828 select = gtk_tree_view_get_selection (GTK_TREE_VIEW (tree));
3829 gtk_tree_selection_set_mode (select, GTK_SELECTION_SINGLE);
3830
3831 gtk_container_add (GTK_CONTAINER (scroll_win), tree);
3832
3833 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialogue)->vbox), scroll_win,TRUE, TRUE,0);
3834
3835 for(i=0;i<nb_module;i++){
3836 gtk_list_store_append (store, &iter);
3837 gtk_list_store_set (store, &iter, MODULE_COLUMN,loaded_module_name[i],-1);
3838 }
3839
3840 id = gtk_dialog_run(GTK_DIALOG(dialogue));
3841 GtkTreeModel **store_model = (GtkTreeModel**)&store;
3842 switch(id){
3843 case GTK_RESPONSE_ACCEPT:
3844 case GTK_RESPONSE_OK:
3845 if (gtk_tree_selection_get_selected (select, store_model, &iter)){
3846 gtk_tree_model_get ((GtkTreeModel*)store, &iter, MODULE_COLUMN, &unload_module_name, -1);
3847 }
3848 case GTK_RESPONSE_REJECT:
3849 case GTK_RESPONSE_CANCEL:
3850 default:
3851 gtk_widget_destroy(dialogue);
3852 break;
3853 }
3854
3855 return unload_module_name;
3856 }
3857
3858
3859 /* Insert all menu entry and tool buttons into this main window
3860 * for modules.
3861 *
3862 */
3863
3864 void add_all_menu_toolbar_constructors(MainWindow * mw, gpointer user_data)
3865 {
3866 guint i;
3867 GdkPixbuf *pixbuf;
3868 lttvwindow_viewer_constructor constructor;
3869 LttvMenus * global_menu, * instance_menu;
3870 LttvToolbars * global_toolbar, * instance_toolbar;
3871 LttvMenuClosure *menu_item;
3872 LttvToolbarClosure *toolbar_item;
3873 LttvAttributeValue value;
3874 LttvIAttribute *global_attributes = LTTV_IATTRIBUTE(lttv_global_attributes());
3875 LttvIAttribute *attributes = mw->attributes;
3876 GtkWidget * tool_menu_title_menu, *new_widget, *pixmap;
3877
3878 g_assert(lttv_iattribute_find_by_path(global_attributes,
3879 "viewers/menu", LTTV_POINTER, &value));
3880 if(*(value.v_pointer) == NULL)
3881 *(value.v_pointer) = lttv_menus_new();
3882 global_menu = (LttvMenus*)*(value.v_pointer);
3883
3884 g_assert(lttv_iattribute_find_by_path(attributes,
3885 "viewers/menu", LTTV_POINTER, &value));
3886 if(*(value.v_pointer) == NULL)
3887 *(value.v_pointer) = lttv_menus_new();
3888 instance_menu = (LttvMenus*)*(value.v_pointer);
3889
3890
3891
3892 g_assert(lttv_iattribute_find_by_path(global_attributes,
3893 "viewers/toolbar", LTTV_POINTER, &value));
3894 if(*(value.v_pointer) == NULL)
3895 *(value.v_pointer) = lttv_toolbars_new();
3896 global_toolbar = (LttvToolbars*)*(value.v_pointer);
3897
3898 g_assert(lttv_iattribute_find_by_path(attributes,
3899 "viewers/toolbar", LTTV_POINTER, &value));
3900 if(*(value.v_pointer) == NULL)
3901 *(value.v_pointer) = lttv_toolbars_new();
3902 instance_toolbar = (LttvToolbars*)*(value.v_pointer);
3903
3904 /* Add missing menu entries to window instance */
3905 for(i=0;i<global_menu->len;i++) {
3906 menu_item = &g_array_index(global_menu, LttvMenuClosure, i);
3907
3908 //add menu_item to window instance;
3909 constructor = menu_item->con;
3910 tool_menu_title_menu = lookup_widget(mw->mwindow,"ToolMenuTitle_menu");
3911 new_widget =
3912 gtk_menu_item_new_with_mnemonic (menu_item->menu_text);
3913 gtk_container_add (GTK_CONTAINER (tool_menu_title_menu),
3914 new_widget);
3915 g_signal_connect ((gpointer) new_widget, "activate",
3916 G_CALLBACK (insert_viewer_wrap),
3917 constructor);
3918 gtk_widget_show (new_widget);
3919 lttv_menus_add(instance_menu, menu_item->con,
3920 menu_item->menu_path,
3921 menu_item->menu_text,
3922 new_widget);
3923
3924 }
3925
3926 /* Add missing toolbar entries to window instance */
3927 for(i=0;i<global_toolbar->len;i++) {
3928 toolbar_item = &g_array_index(global_toolbar, LttvToolbarClosure, i);
3929
3930 //add toolbar_item to window instance;
3931 constructor = toolbar_item->con;
3932 tool_menu_title_menu = lookup_widget(mw->mwindow,"MToolbar1");
3933 pixbuf = gdk_pixbuf_new_from_xpm_data((const char**)toolbar_item->pixmap);
3934 pixmap = gtk_image_new_from_pixbuf(pixbuf);
3935 new_widget =
3936 gtk_toolbar_append_element (GTK_TOOLBAR (tool_menu_title_menu),
3937 GTK_TOOLBAR_CHILD_BUTTON,
3938 NULL,
3939 "",
3940 toolbar_item->tooltip, NULL,
3941 pixmap, NULL, NULL);
3942 gtk_label_set_use_underline(
3943 GTK_LABEL (((GtkToolbarChild*) (
3944 g_list_last (GTK_TOOLBAR
3945 (tool_menu_title_menu)->children)->data))->label),
3946 TRUE);
3947 gtk_container_set_border_width (GTK_CONTAINER (new_widget), 1);
3948 g_signal_connect ((gpointer) new_widget,
3949 "clicked",
3950 G_CALLBACK (insert_viewer_wrap),
3951 constructor);
3952 gtk_widget_show (new_widget);
3953
3954 lttv_toolbars_add(instance_toolbar, toolbar_item->con,
3955 toolbar_item->tooltip,
3956 toolbar_item->pixmap,
3957 new_widget);
3958
3959 }
3960
3961 }
3962
3963
3964 /* Create a main window
3965 */
3966
3967 void construct_main_window(MainWindow * parent)
3968 {
3969 g_debug("construct_main_window()");
3970 GtkWidget * new_window; /* New generated main window */
3971 MainWindow * new_m_window;/* New main window structure */
3972 GtkNotebook * notebook;
3973 LttvIAttribute *attributes =
3974 LTTV_IATTRIBUTE(g_object_new(LTTV_ATTRIBUTE_TYPE, NULL));
3975 LttvAttributeValue value;
3976 Tab *new_tab;
3977
3978 new_m_window = g_new(MainWindow, 1);
3979
3980 // Add the object's information to the module's array
3981 g_main_window_list = g_slist_append(g_main_window_list, new_m_window);
3982
3983 new_window = create_MWindow();
3984 gtk_widget_show (new_window);
3985
3986 new_m_window->mwindow = new_window;
3987 new_m_window->attributes = attributes;
3988
3989 g_assert(lttv_iattribute_find_by_path(attributes,
3990 "viewers/menu", LTTV_POINTER, &value));
3991 *(value.v_pointer) = lttv_menus_new();
3992
3993 g_assert(lttv_iattribute_find_by_path(attributes,
3994 "viewers/toolbar", LTTV_POINTER, &value));
3995 *(value.v_pointer) = lttv_toolbars_new();
3996
3997 add_all_menu_toolbar_constructors(new_m_window, NULL);
3998
3999 g_object_set_data_full(G_OBJECT(new_window),
4000 "main_window_data",
4001 (gpointer)new_m_window,
4002 (GDestroyNotify)g_free);
4003 //create a default tab
4004 notebook = (GtkNotebook *)lookup_widget(new_m_window->mwindow, "MNotebook");
4005 if(notebook == NULL){
4006 g_info("Notebook does not exist\n");
4007 return;
4008 }
4009 //gtk_notebook_popup_enable (GTK_NOTEBOOK(notebook));
4010 //for now there is no name field in LttvTraceset structure
4011 //Use "Traceset" as the label for the default tab
4012 if(parent) {
4013 GtkWidget * parent_notebook = lookup_widget(parent->mwindow, "MNotebook");
4014 GtkWidget *page = gtk_notebook_get_nth_page(GTK_NOTEBOOK(parent_notebook),
4015 gtk_notebook_get_current_page(GTK_NOTEBOOK(parent_notebook)));
4016 Tab *parent_tab;
4017
4018 if(!page) {
4019 parent_tab = NULL;
4020 } else {
4021 parent_tab = (Tab *)g_object_get_data(G_OBJECT(page), "Tab_Info");
4022 }
4023 new_tab = create_tab(new_m_window, parent_tab, notebook, "Traceset");
4024 } else {
4025 new_tab = create_tab(new_m_window, NULL, notebook, "Traceset");
4026 /* First window, use command line trace */
4027 if(g_init_trace != NULL){
4028 lttvwindow_add_trace(new_tab,
4029 g_init_trace);
4030
4031 }
4032 LttvTraceset *traceset = new_tab->traceset_info->traceset;
4033 SetTraceset(new_tab, traceset);
4034
4035 /* Insert default viewers */
4036 {
4037 LttvAttributeType type;
4038 LttvAttributeName name;
4039 LttvAttributeValue value;
4040 LttvAttribute *attribute;
4041
4042 LttvIAttribute *attributes_global =
4043 LTTV_IATTRIBUTE(lttv_global_attributes());
4044
4045 g_assert(attribute =
4046 LTTV_ATTRIBUTE(lttv_iattribute_find_subdir(
4047 LTTV_IATTRIBUTE(attributes_global),
4048 LTTV_VIEWER_CONSTRUCTORS)));
4049
4050 name = g_quark_from_string("guievents");
4051 type = lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(attribute),
4052 name, &value);
4053 if(type == LTTV_POINTER) {
4054 lttvwindow_viewer_constructor viewer_constructor =
4055 (lttvwindow_viewer_constructor)*value.v_pointer;
4056 insert_viewer(new_window, viewer_constructor);
4057 }
4058
4059 name = g_quark_from_string("guicontrolflow");
4060 type = lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(attribute),
4061 name, &value);
4062 if(type == LTTV_POINTER) {
4063 lttvwindow_viewer_constructor viewer_constructor =
4064 (lttvwindow_viewer_constructor)*value.v_pointer;
4065 insert_viewer(new_window, viewer_constructor);
4066 }
4067
4068 name = g_quark_from_string("guistatistics");
4069 type = lttv_iattribute_get_by_name(LTTV_IATTRIBUTE(attribute),
4070 name, &value);
4071 if(type == LTTV_POINTER) {
4072 lttvwindow_viewer_constructor viewer_constructor =
4073 (lttvwindow_viewer_constructor)*value.v_pointer;
4074 insert_viewer(new_window, viewer_constructor);
4075 }
4076
4077 }
4078 }
4079
4080 g_info("There are now : %d windows\n",g_slist_length(g_main_window_list));
4081 }
4082
4083
4084 /* Free the memory occupied by a tab structure
4085 * destroy the tab
4086 */
4087
4088 void tab_destructor(Tab * tab)
4089 {
4090 int i, nb, ref_count;
4091 LttvTrace * trace;
4092
4093 gtk_object_destroy(GTK_OBJECT(tab->tooltips));
4094
4095 if(tab->attributes)
4096 g_object_unref(tab->attributes);
4097
4098 if(tab->interrupted_state)
4099 g_object_unref(tab->interrupted_state);
4100
4101
4102 if(tab->traceset_info->traceset_context != NULL){
4103 //remove state update hooks
4104 lttv_state_remove_event_hooks(
4105 (LttvTracesetState*)tab->traceset_info->
4106 traceset_context);
4107 lttv_context_fini(LTTV_TRACESET_CONTEXT(tab->traceset_info->
4108 traceset_context));
4109 g_object_unref(tab->traceset_info->traceset_context);
4110 }
4111 if(tab->traceset_info->traceset != NULL) {
4112 nb = lttv_traceset_number(tab->traceset_info->traceset);
4113 for(i = 0 ; i < nb ; i++) {
4114 trace = lttv_traceset_get(tab->traceset_info->traceset, i);
4115 ref_count = lttv_trace_get_ref_number(trace);
4116 if(ref_count <= 1){
4117 ltt_trace_close(lttv_trace(trace));
4118 }
4119 }
4120 }
4121 lttv_filter_destroy(tab->filter);
4122 lttv_traceset_destroy(tab->traceset_info->traceset);
4123 /* Remove the idle events requests processing function of the tab */
4124 g_idle_remove_by_data(tab);
4125
4126 g_slist_free(tab->events_requests);
4127 g_free(tab->traceset_info);
4128 g_free(tab);
4129 }
4130
4131
4132 /* Create a tab and insert it into the current main window
4133 */
4134
4135 Tab* create_tab(MainWindow * mw, Tab *copy_tab,
4136 GtkNotebook * notebook, char * label)
4137 {
4138 GList * list;
4139 Tab * tab;
4140
4141 //create a new tab data structure
4142 tab = g_new(Tab,1);
4143
4144 //construct and initialize the traceset_info
4145 tab->traceset_info = g_new(TracesetInfo,1);
4146
4147 if(copy_tab) {
4148 tab->traceset_info->traceset =
4149 lttv_traceset_copy(copy_tab->traceset_info->traceset);
4150
4151 /* Copy the previous tab's filter */
4152 /* We can clone the filter, as we copy the trace set also */
4153 /* The filter must always be in sync with the trace set */
4154 tab->filter = lttv_filter_clone(copy_tab->filter);
4155 } else {
4156 tab->traceset_info->traceset = lttv_traceset_new();
4157 tab->filter = NULL;
4158 }
4159 #ifdef DEBUG
4160 lttv_attribute_write_xml(
4161 lttv_traceset_attribute(tab->traceset_info->traceset),
4162 stdout,
4163 0, 4);
4164 fflush(stdout);
4165 #endif //DEBUG
4166
4167 tab->time_manager_lock = FALSE;
4168 tab->current_time_manager_lock = FALSE;
4169
4170 //FIXME copy not implemented in lower level
4171 tab->traceset_info->traceset_context =
4172 g_object_new(LTTV_TRACESET_STATS_TYPE, NULL);
4173 g_assert(tab->traceset_info->traceset_context != NULL);
4174 lttv_context_init(
4175 LTTV_TRACESET_CONTEXT(tab->traceset_info->traceset_context),
4176 tab->traceset_info->traceset);
4177 //add state update hooks
4178 lttv_state_add_event_hooks(
4179 (LttvTracesetState*)tab->traceset_info->traceset_context);
4180
4181 //determine the current_time and time_window of the tab
4182 #if 0
4183 if(copy_tab != NULL){
4184 tab->time_window = copy_tab->time_window;
4185 tab->current_time = copy_tab->current_time;
4186 }else{
4187 tab->time_window.start_time =
4188 LTTV_TRACESET_CONTEXT(tab->traceset_info->traceset_context)->
4189 time_span.start_time;
4190 if(DEFAULT_TIME_WIDTH_S <
4191 LTTV_TRACESET_CONTEXT(tab->traceset_info->traceset_context)->
4192 time_span.end_time.tv_sec)
4193 tmp_time.tv_sec = DEFAULT_TIME_WIDTH_S;
4194 else
4195 tmp_time.tv_sec =
4196 LTTV_TRACESET_CONTEXT(tab->traceset_info->traceset_context)->
4197 time_span.end_time.tv_sec;
4198 tmp_time.tv_nsec = 0;
4199 tab->time_window.time_width = tmp_time ;
4200 tab->current_time.tv_sec =
4201 LTTV_TRACESET_CONTEXT(tab->traceset_info->traceset_context)->
4202 time_span.start_time.tv_sec;
4203 tab->current_time.tv_nsec =
4204 LTTV_TRACESET_CONTEXT(tab->traceset_info->traceset_context)->
4205 time_span.start_time.tv_nsec;
4206 }
4207 #endif //0
4208 tab->attributes = LTTV_IATTRIBUTE(g_object_new(LTTV_ATTRIBUTE_TYPE, NULL));
4209 tab->interrupted_state = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
4210
4211 tab->vbox = gtk_vbox_new(FALSE, 2);
4212 tab->viewer_container = gtk_vbox_new(TRUE, 2);
4213 tab->scrollbar = gtk_hscrollbar_new(NULL);
4214 //tab->multivpaned = gtk_multi_vpaned_new();
4215
4216 gtk_box_pack_start(GTK_BOX(tab->vbox),
4217 tab->viewer_container,
4218 TRUE, /* expand */
4219 TRUE, /* Give the extra space to the child */
4220 0); /* No padding */
4221
4222 // if(copy_tab) {
4223 // tab->time_window = copy_tab->time_window;
4224 // tab->current_time = copy_tab->current_time;
4225 // }
4226
4227 /* Create the timebar */
4228 {
4229 tab->MTimebar = gtk_hbox_new(FALSE, 2);
4230 gtk_widget_show(tab->MTimebar);
4231 tab->tooltips = gtk_tooltips_new();
4232
4233 tab->MEventBox1a = gtk_event_box_new();
4234 gtk_widget_show(tab->MEventBox1a);
4235 gtk_tooltips_set_tip(tab->tooltips, tab->MEventBox1a,
4236 "Paste Start and End Times Here", "");
4237 tab->MText1a = gtk_label_new("Time Frame ");
4238 gtk_widget_show(tab->MText1a);
4239 gtk_container_add(GTK_CONTAINER(tab->MEventBox1a), tab->MText1a);
4240 tab->MEventBox1b = gtk_event_box_new();
4241 gtk_widget_show(tab->MEventBox1b);
4242 gtk_tooltips_set_tip(tab->tooltips, tab->MEventBox1b,
4243 "Paste Start Time Here", "");
4244 tab->MText1b = gtk_label_new("start: ");
4245 gtk_widget_show(tab->MText1b);
4246 gtk_container_add(GTK_CONTAINER(tab->MEventBox1b), tab->MText1b);
4247 tab->MText2 = gtk_label_new("s");
4248 gtk_widget_show(tab->MText2);
4249 tab->MText3a = gtk_label_new("ns");
4250 gtk_widget_show(tab->MText3a);
4251 tab->MEventBox3b = gtk_event_box_new();
4252 gtk_widget_show(tab->MEventBox3b);
4253 gtk_tooltips_set_tip(tab->tooltips, tab->MEventBox3b,
4254 "Paste End Time Here", "");
4255 tab->MText3b = gtk_label_new("end:");
4256 gtk_widget_show(tab->MText3b);
4257 gtk_container_add(GTK_CONTAINER(tab->MEventBox3b), tab->MText3b);
4258 tab->MText4 = gtk_label_new("s");
4259 gtk_widget_show(tab->MText4);
4260 tab->MText5a = gtk_label_new("ns");
4261 gtk_widget_show(tab->MText5a);
4262 tab->MEventBox5b = gtk_event_box_new();
4263 gtk_widget_show(tab->MEventBox5b);
4264 gtk_tooltips_set_tip(tab->tooltips, tab->MEventBox5b,
4265 "Paste Current Time Here", "");
4266 tab->MText5b = gtk_label_new("Current Time:");
4267 gtk_widget_show(tab->MText5b);
4268 gtk_container_add(GTK_CONTAINER(tab->MEventBox5b), tab->MText5b);
4269 tab->MText6 = gtk_label_new("s");
4270 gtk_widget_show(tab->MText6);
4271 tab->MText7 = gtk_label_new("ns");
4272 gtk_widget_show(tab->MText7);
4273
4274 tab->MEntry1 = gtk_spin_button_new_with_range(0.0, 1.0, 1.0);
4275 gtk_spin_button_set_digits(GTK_SPIN_BUTTON(tab->MEntry1),0);
4276 gtk_spin_button_set_snap_to_ticks(GTK_SPIN_BUTTON(tab->MEntry1),TRUE);
4277 gtk_widget_show(tab->MEntry1);
4278 tab->MEntry2 = gtk_spin_button_new_with_range(0.0, 1.0, 1.0);
4279 gtk_spin_button_set_digits(GTK_SPIN_BUTTON(tab->MEntry2),0);
4280 gtk_spin_button_set_snap_to_ticks(GTK_SPIN_BUTTON(tab->MEntry2),TRUE);
4281 gtk_widget_show(tab->MEntry2);
4282 tab->MEntry3 = gtk_spin_button_new_with_range(0.0, 1.0, 1.0);
4283 gtk_spin_button_set_digits(GTK_SPIN_BUTTON(tab->MEntry3),0);
4284 gtk_spin_button_set_snap_to_ticks(GTK_SPIN_BUTTON(tab->MEntry3),TRUE);
4285 gtk_widget_show(tab->MEntry3);
4286 tab->MEntry4 = gtk_spin_button_new_with_range(0.0, 1.0, 1.0);
4287 gtk_spin_button_set_digits(GTK_SPIN_BUTTON(tab->MEntry4),0);
4288 gtk_spin_button_set_snap_to_ticks(GTK_SPIN_BUTTON(tab->MEntry4),TRUE);
4289 gtk_widget_show(tab->MEntry4);
4290 tab->MEntry5 = gtk_spin_button_new_with_range(0.0, 1.0, 1.0);
4291 gtk_spin_button_set_digits(GTK_SPIN_BUTTON(tab->MEntry5),0);
4292 gtk_spin_button_set_snap_to_ticks(GTK_SPIN_BUTTON(tab->MEntry5),TRUE);
4293 gtk_widget_show(tab->MEntry5);
4294 tab->MEntry6 = gtk_spin_button_new_with_range(0.0, 1.0, 1.0);
4295 gtk_spin_button_set_digits(GTK_SPIN_BUTTON(tab->MEntry6),0);
4296 gtk_spin_button_set_snap_to_ticks(GTK_SPIN_BUTTON(tab->MEntry6),TRUE);
4297 gtk_widget_show(tab->MEntry6);
4298
4299
4300 GtkWidget *temp_widget;
4301
4302 gtk_box_pack_start (GTK_BOX (tab->MTimebar), tab->MEventBox1a, FALSE,
4303 FALSE, 0);
4304 gtk_box_pack_start (GTK_BOX (tab->MTimebar), tab->MEventBox1b, FALSE,
4305 FALSE, 0);
4306 gtk_box_pack_start (GTK_BOX (tab->MTimebar), tab->MEntry1, FALSE, FALSE, 0);
4307 gtk_box_pack_start (GTK_BOX (tab->MTimebar), tab->MText2, FALSE, FALSE, 0);
4308 gtk_box_pack_start (GTK_BOX (tab->MTimebar), tab->MEntry2, FALSE, FALSE, 0);
4309 gtk_box_pack_start (GTK_BOX (tab->MTimebar), tab->MText3a, FALSE, FALSE, 0);
4310 temp_widget = gtk_vseparator_new();
4311 gtk_widget_show(temp_widget);
4312 gtk_box_pack_start (GTK_BOX (tab->MTimebar), temp_widget, FALSE, FALSE, 0);
4313 gtk_box_pack_start (GTK_BOX (tab->MTimebar), tab->MEventBox3b, FALSE,
4314 FALSE, 0);
4315 gtk_box_pack_start (GTK_BOX (tab->MTimebar), tab->MEntry3, FALSE, FALSE, 0);
4316 gtk_box_pack_start (GTK_BOX (tab->MTimebar), tab->MText4, FALSE, FALSE, 0);
4317 gtk_box_pack_start (GTK_BOX (tab->MTimebar), tab->MEntry4, FALSE, FALSE, 0);
4318 gtk_box_pack_start (GTK_BOX (tab->MTimebar), tab->MText5a, FALSE, FALSE, 0);
4319 temp_widget = gtk_vseparator_new();
4320 gtk_widget_show(temp_widget);
4321 gtk_box_pack_end (GTK_BOX (tab->MTimebar), tab->MText7, FALSE, FALSE, 0);
4322 gtk_box_pack_end (GTK_BOX (tab->MTimebar), tab->MEntry6, FALSE, FALSE, 0);
4323 gtk_box_pack_end (GTK_BOX (tab->MTimebar), tab->MText6, FALSE, FALSE, 0);
4324 gtk_box_pack_end (GTK_BOX (tab->MTimebar), tab->MEntry5, FALSE, FALSE, 0);
4325 gtk_box_pack_end (GTK_BOX (tab->MTimebar), tab->MEventBox5b, FALSE,
4326 FALSE, 0);
4327 gtk_box_pack_end (GTK_BOX (tab->MTimebar), temp_widget, FALSE, FALSE, 0);
4328
4329
4330 //GtkWidget *test = gtk_button_new_with_label("drop");
4331 //gtk_button_set_relief(GTK_BUTTON(test), GTK_RELIEF_NONE);
4332 //gtk_widget_show(test);
4333 //gtk_box_pack_end(GTK_BOX (tab->MTimebar), test, FALSE, FALSE, 0);
4334 //gtk_widget_add_events(tab->MText1, GDK_ALL_EVENTS_MASK);//GDK_BUTTON_PRESS_MASK);
4335 /*GtkWidget *event_box = gtk_event_box_new();
4336 gtk_widget_show(event_box);
4337 gtk_tooltips_set_tip(tooltips, event_box,
4338 "Paste Current Time Here", "");
4339 gtk_box_pack_end(GTK_BOX (tab->MTimebar), event_box, FALSE, FALSE, 0);
4340 GtkWidget *test = gtk_label_new("drop");
4341 gtk_container_add(GTK_CONTAINER(event_box), test);
4342 gtk_widget_show(test);
4343 g_signal_connect (G_OBJECT(event_box),
4344 "button-press-event",
4345 G_CALLBACK (on_MText1_paste),
4346 (gpointer)tab);
4347 */
4348
4349 g_signal_connect (G_OBJECT(tab->MEventBox1a),
4350 "button-press-event",
4351 G_CALLBACK (on_MEventBox1a_paste),
4352 (gpointer)tab);
4353
4354 g_signal_connect (G_OBJECT(tab->MEventBox1b),
4355 "button-press-event",
4356 G_CALLBACK (on_MEventBox1b_paste),
4357 (gpointer)tab);
4358 g_signal_connect (G_OBJECT(tab->MEventBox3b),
4359 "button-press-event",
4360 G_CALLBACK (on_MEventBox3b_paste),
4361 (gpointer)tab);
4362 g_signal_connect (G_OBJECT(tab->MEventBox5b),
4363 "button-press-event",
4364 G_CALLBACK (on_MEventBox5b_paste),
4365 (gpointer)tab);
4366 }
4367
4368 gtk_box_pack_end(GTK_BOX(tab->vbox),
4369 tab->scrollbar,
4370 FALSE, /* Do not expand */
4371 FALSE, /* Fill has no effect here (expand false) */
4372 0); /* No padding */
4373
4374 gtk_box_pack_end(GTK_BOX(tab->vbox),
4375 tab->MTimebar,
4376 FALSE, /* Do not expand */
4377 FALSE, /* Fill has no effect here (expand false) */
4378 0); /* No padding */
4379
4380 g_object_set_data(G_OBJECT(tab->viewer_container), "focused_viewer", NULL);
4381
4382
4383 tab->mw = mw;
4384
4385 /*{
4386 // Display a label with a X
4387 GtkWidget *w_hbox = gtk_hbox_new(FALSE, 4);
4388 GtkWidget *w_label = gtk_label_new (label);
4389 GtkWidget *pixmap = create_pixmap(GTK_WIDGET(notebook), "close.png");
4390 GtkWidget *w_button = gtk_button_new ();
4391 gtk_container_add(GTK_CONTAINER(w_button), pixmap);
4392 //GtkWidget *w_button = gtk_button_new_with_label("x");
4393
4394 gtk_button_set_relief(GTK_BUTTON(w_button), GTK_RELIEF_NONE);
4395
4396 gtk_box_pack_start(GTK_BOX(w_hbox), w_label, TRUE, TRUE, 0);
4397 gtk_box_pack_end(GTK_BOX(w_hbox), w_button, FALSE,
4398 FALSE, 0);
4399
4400 g_signal_connect_swapped (w_button, "clicked",
4401 G_CALLBACK (on_close_tab_X_clicked),
4402 tab->multi_vpaned);
4403
4404 gtk_widget_set_state(w_button, GTK_STATE_ACTIVE);
4405
4406 gtk_widget_show (w_label);
4407 gtk_widget_show (pixmap);
4408 gtk_widget_show (w_button);
4409 gtk_widget_show (w_hbox);
4410
4411 tab->label = w_hbox;
4412 }*/
4413
4414
4415 tab->label = gtk_label_new (label);
4416
4417 gtk_widget_show(tab->label);
4418 gtk_widget_show(tab->scrollbar);
4419 gtk_widget_show(tab->viewer_container);
4420 gtk_widget_show(tab->vbox);
4421 //gtk_widget_show(tab->multivpaned);
4422
4423
4424 /* Start with empty events requests list */
4425 tab->events_requests = NULL;
4426 tab->events_request_pending = FALSE;
4427
4428 g_object_set_data_full(
4429 G_OBJECT(tab->vbox),
4430 "Tab_Info",
4431 tab,
4432 (GDestroyNotify)tab_destructor);
4433
4434 g_signal_connect(G_OBJECT(tab->scrollbar), "value-changed",
4435 G_CALLBACK(scroll_value_changed_cb), tab);
4436
4437 g_signal_connect ((gpointer) tab->MEntry1, "value-changed",
4438 G_CALLBACK (on_MEntry1_value_changed),
4439 tab);
4440 g_signal_connect ((gpointer) tab->MEntry2, "value-changed",
4441 G_CALLBACK (on_MEntry2_value_changed),
4442 tab);
4443 g_signal_connect ((gpointer) tab->MEntry3, "value-changed",
4444 G_CALLBACK (on_MEntry3_value_changed),
4445 tab);
4446 g_signal_connect ((gpointer) tab->MEntry4, "value-changed",
4447 G_CALLBACK (on_MEntry4_value_changed),
4448 tab);
4449 g_signal_connect ((gpointer) tab->MEntry5, "value-changed",
4450 G_CALLBACK (on_MEntry5_value_changed),
4451 tab);
4452 g_signal_connect ((gpointer) tab->MEntry6, "value-changed",
4453 G_CALLBACK (on_MEntry6_value_changed),
4454 tab);
4455
4456 //g_signal_connect(G_OBJECT(tab->scrollbar), "changed",
4457 // G_CALLBACK(scroll_value_changed_cb), tab);
4458
4459
4460 //insert tab into notebook
4461 gtk_notebook_append_page(notebook,
4462 tab->vbox,
4463 tab->label);
4464 list = gtk_container_get_children(GTK_CONTAINER(notebook));
4465 gtk_notebook_set_current_page(notebook,g_list_length(list)-1);
4466 // always show : not if(g_list_length(list)>1)
4467 gtk_notebook_set_show_tabs(notebook, TRUE);
4468
4469 if(copy_tab) {
4470 lttvwindow_report_time_window(tab, copy_tab->time_window);
4471 lttvwindow_report_current_time(tab, copy_tab->current_time);
4472 } else {
4473 TimeWindow time_window;
4474
4475 time_window.start_time = ltt_time_zero;
4476 time_window.end_time = ltt_time_add(time_window.start_time,
4477 lttvwindow_default_time_width);
4478 time_window.time_width = lttvwindow_default_time_width;
4479 time_window.time_width_double = ltt_time_to_double(time_window.time_width);
4480
4481 lttvwindow_report_time_window(tab, time_window);
4482 lttvwindow_report_current_time(tab, ltt_time_zero);
4483 }
4484
4485 LttvTraceset *traceset = tab->traceset_info->traceset;
4486 SetTraceset(tab, traceset);
4487
4488 return tab;
4489 }
4490
4491 /*
4492 * execute_events_requests
4493 *
4494 * Idle function that executes the pending requests for a tab.
4495 *
4496 * @return return value : TRUE : keep the idle function, FALSE : remove it.
4497 */
4498 gboolean execute_events_requests(Tab *tab)
4499 {
4500 return ( lttvwindow_process_pending_requests(tab) );
4501 }
4502
This page took 0.121076 seconds and 5 git commands to generate.