1 /* This file is part of the Linux Trace Toolkit viewer
2 * Copyright (C) 2003-2004 Mathieu Desnoyers
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License Version 2 as
6 * published by the Free Software Foundation;
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
20 /*****************************************************************************
21 * Hooks to be called by the main window *
22 *****************************************************************************/
25 #define g_info(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, format)
26 #define g_debug(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_DEBUG, format)
28 //#define PANGO_ENABLE_BACKEND
35 //#include <pango/pango.h>
37 #include <ltt/event.h>
41 #include <lttv/hook.h>
42 #include <lttv/common.h>
43 #include <lttv/state.h>
44 #include <lttv/gtkTraceSet.h>
47 #include "eventhooks.h"
49 #include "processlist.h"
51 #include "cfv-private.h"
54 #define MAX_PATH_LEN 256
58 * Event Viewer's constructor hook
60 * This constructor is given as a parameter to the menuitem and toolbar button
61 * registration. It creates the list.
62 * @param mw A pointer to the parent window.
63 * @return The widget created.
66 h_guicontrolflow(MainWindow
*mw
, LttvTracesetSelector
* s
, char * key
)
68 g_info("h_guicontrolflow, %p, %p, %s", mw
, s
, key
);
69 ControlFlowData
*control_flow_data
= guicontrolflow() ;
71 control_flow_data
->mw
= mw
;
72 TimeWindow
*time_window
= guicontrolflow_get_time_window(control_flow_data
);
73 time_window
->start_time
.tv_sec
= 0;
74 time_window
->start_time
.tv_nsec
= 0;
75 time_window
->time_width
.tv_sec
= 0;
76 time_window
->time_width
.tv_nsec
= 0;
78 LttTime
*current_time
= guicontrolflow_get_current_time(control_flow_data
);
79 current_time
->tv_sec
= 0;
80 current_time
->tv_nsec
= 0;
82 //g_critical("time width1 : %u",time_window->time_width);
89 //g_critical("time width2 : %u",time_window->time_width);
90 // Unreg done in the GuiControlFlow_Destructor
91 reg_update_time_window(update_time_window_hook
, control_flow_data
,
93 reg_update_current_time(update_current_time_hook
, control_flow_data
,
95 return guicontrolflow_get_widget(control_flow_data
) ;
99 int event_selected_hook(void *hook_data
, void *call_data
)
101 ControlFlowData
*control_flow_data
= (ControlFlowData
*) hook_data
;
102 guint
*event_number
= (guint
*) call_data
;
104 g_critical("DEBUG : event selected by main window : %u", *event_number
);
106 // control_flow_data->currently_Selected_Event = *event_number;
107 // control_flow_data->Selected_Event = TRUE ;
109 // tree_v_set_cursor(control_flow_data);
113 /* Hook called before drawing. Gets the initial context at the beginning of the
114 * drawing interval and copy it to the context in event_request.
116 int draw_before_hook(void *hook_data
, void *call_data
)
118 EventRequest
*event_request
= (EventRequest
*)hook_data
;
119 //EventsContext Events_Context = (EventsContext*)call_data;
121 //event_request->Events_Context = Events_Context;
127 * The draw event hook is called by the reading API to have a
128 * particular event drawn on the screen.
129 * @param hook_data ControlFlowData structure of the viewer.
130 * @param call_data Event context.
132 * This function basically draw lines and icons. Two types of lines are drawn :
133 * one small (3 pixels?) representing the state of the process and the second
134 * type is thicker (10 pixels?) representing on which CPU a process is running
135 * (and this only in running state).
137 * Extremums of the lines :
138 * x_min : time of the last event context for this process kept in memory.
139 * x_max : time of the current event.
140 * y : middle of the process in the process list. The process is found in the
141 * list, therefore is it's position in pixels.
143 * The choice of lines'color is defined by the context of the last event for this
146 int draw_event_hook(void *hook_data
, void *call_data
)
148 EventRequest
*event_request
= (EventRequest
*)hook_data
;
149 ControlFlowData
*control_flow_data
= event_request
->control_flow_data
;
151 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
153 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
159 if(strcmp(ltt_eventtype_name(ltt_event_eventtype(e
)),"schedchange") == 0)
161 g_critical("schedchange!");
163 /* Add process to process list (if not present) and get drawing "y" from
164 * process position */
165 guint pid_out
, pid_in
;
166 LttvProcessState
*process_out
, *process_in
;
168 guint y_in
= 0, y_out
= 0, height
= 0, pl_height
= 0;
170 ProcessList
*process_list
=
171 guicontrolflow_get_process_list(event_request
->control_flow_data
);
174 LttField
*f
= ltt_event_field(e
);
176 element
= ltt_field_member(f
,0);
177 pid_out
= ltt_event_get_long_unsigned(e
,element
);
178 element
= ltt_field_member(f
,1);
179 pid_in
= ltt_event_get_long_unsigned(e
,element
);
180 g_critical("out : %u in : %u", pid_out
, pid_in
);
183 /* Find process pid_out in the list... */
184 process_out
= lttv_state_find_process(tfs
, pid_out
);
185 g_critical("out : %s",g_quark_to_string(process_out
->state
->s
));
187 birth
= process_out
->creation_time
;
188 gchar
*name
= strdup(g_quark_to_string(process_out
->name
));
189 HashedProcessData
*hashed_process_data_out
= NULL
;
191 if(processlist_get_process_pixels(process_list
,
196 &hashed_process_data_out
) == 1)
198 /* Process not present */
199 processlist_add(process_list
,
204 &hashed_process_data_out
);
205 processlist_get_process_pixels(process_list
,
210 &hashed_process_data_out
);
211 drawing_insert_square( event_request
->control_flow_data
->drawing
, y_out
, height
);
216 /* Find process pid_in in the list... */
217 process_in
= lttv_state_find_process(tfs
, pid_in
);
218 g_critical("in : %s",g_quark_to_string(process_in
->state
->s
));
220 birth
= process_in
->creation_time
;
221 name
= strdup(g_quark_to_string(process_in
->name
));
222 HashedProcessData
*hashed_process_data_in
= NULL
;
224 if(processlist_get_process_pixels(process_list
,
229 &hashed_process_data_in
) == 1)
231 /* Process not present */
232 processlist_add(process_list
,
237 &hashed_process_data_in
);
238 processlist_get_process_pixels(process_list
,
243 &hashed_process_data_in
);
245 drawing_insert_square( event_request
->control_flow_data
->drawing
, y_in
, height
);
250 /* Find pixels corresponding to time of the event. If the time does
251 * not fit in the window, show a warning, not supposed to happend. */
253 guint width
= control_flow_data
->drawing
->drawing_area
->allocation
.width
;
255 LttTime time
= ltt_event_time(e
);
257 LttTime window_end
= ltt_time_add(control_flow_data
->time_window
.time_width
,
258 control_flow_data
->time_window
.start_time
);
261 convert_time_to_pixels(
262 control_flow_data
->time_window
.start_time
,
270 /* draw what represents the event for outgoing process. */
272 DrawContext
*draw_context_out
= hashed_process_data_out
->draw_context
;
273 draw_context_out
->current
->modify_over
->x
= x
;
274 draw_context_out
->current
->modify_over
->y
= y_out
;
275 draw_context_out
->drawable
= control_flow_data
->drawing
->pixmap
;
276 draw_context_out
->pango_layout
= control_flow_data
->drawing
->pango_layout
;
277 GtkWidget
*widget
= control_flow_data
->drawing
->drawing_area
;
278 //draw_context_out->gc = widget->style->fg_gc[GTK_WIDGET_STATE (widget)];
279 draw_context_out
->gc
= gdk_gc_new(control_flow_data
->drawing
->pixmap
);
280 gdk_gc_copy(draw_context_out
->gc
, widget
->style
->black_gc
);
281 //draw_context_out->gc = widget->style->black_gc;
283 //draw_arc((void*)&prop_arc, (void*)draw_context_out);
284 //test_draw_item(control_flow_data->drawing, control_flow_data->drawing->pixmap);
286 GdkColor colorfg_out
= { 0, 0xffff, 0x0000, 0x0000 };
287 GdkColor colorbg_out
= { 0, 0xffff, 0xffff, 0xffff };
288 PropertiesText prop_text_out
;
289 prop_text_out
.foreground
= &colorfg_out
;
290 prop_text_out
.background
= &colorbg_out
;
291 prop_text_out
.size
= 10;
292 prop_text_out
.position
= OVER
;
294 /* Print status of the process : U, WF, WC, E, W, R */
295 if(process_out
->state
->s
== LTTV_STATE_UNNAMED
)
296 prop_text_out
.text
= "U";
297 else if(process_out
->state
->s
== LTTV_STATE_WAIT_FORK
)
298 prop_text_out
.text
= "WF";
299 else if(process_out
->state
->s
== LTTV_STATE_WAIT_CPU
)
300 prop_text_out
.text
= "WC";
301 else if(process_out
->state
->s
== LTTV_STATE_EXIT
)
302 prop_text_out
.text
= "E";
303 else if(process_out
->state
->s
== LTTV_STATE_WAIT
)
304 prop_text_out
.text
= "W";
305 else if(process_out
->state
->s
== LTTV_STATE_RUN
)
306 prop_text_out
.text
= "R";
308 prop_text_out
.text
= "U";
310 draw_text((void*)&prop_text_out
, (void*)draw_context_out
);
311 gdk_gc_unref(draw_context_out
->gc
);
313 /* Draw the line of the out process */
314 if(draw_context_out
->previous
->middle
->x
== -1)
316 draw_context_out
->previous
->middle
->x
= event_request
->x_begin
;
317 g_critical("out middle x_beg : %u",event_request
->x_begin
);
320 draw_context_out
->current
->middle
->x
= x
;
321 draw_context_out
->current
->middle
->y
= y_out
+ height
/2;
322 draw_context_out
->previous
->middle
->y
= y_out
+ height
/2;
323 draw_context_out
->drawable
= control_flow_data
->drawing
->pixmap
;
324 draw_context_out
->pango_layout
= control_flow_data
->drawing
->pango_layout
;
325 //draw_context_out->gc = widget->style->black_gc;
326 draw_context_out
->gc
= gdk_gc_new(control_flow_data
->drawing
->pixmap
);
327 gdk_gc_copy(draw_context_out
->gc
, widget
->style
->black_gc
);
329 PropertiesLine prop_line_out
;
330 prop_line_out
.color
= g_new(GdkColor
,1);
331 prop_line_out
.line_width
= 4;
332 prop_line_out
.style
= GDK_LINE_SOLID
;
333 prop_line_out
.position
= MIDDLE
;
335 /* color of line : status of the process */
336 if(process_out
->state
->s
== LTTV_STATE_UNNAMED
)
338 prop_line_out
.color
->red
= 0x0000;
339 prop_line_out
.color
->green
= 0x0000;
340 prop_line_out
.color
->blue
= 0x0000;
342 else if(process_out
->state
->s
== LTTV_STATE_WAIT_FORK
)
344 prop_line_out
.color
->red
= 0x0fff;
345 prop_line_out
.color
->green
= 0x0000;
346 prop_line_out
.color
->blue
= 0x0fff;
348 else if(process_out
->state
->s
== LTTV_STATE_WAIT_CPU
)
350 prop_line_out
.color
->red
= 0x0fff;
351 prop_line_out
.color
->green
= 0x0fff;
352 prop_line_out
.color
->blue
= 0x0000;
354 else if(process_out
->state
->s
== LTTV_STATE_EXIT
)
356 prop_line_out
.color
->red
= 0xffff;
357 prop_line_out
.color
->green
= 0x0000;
358 prop_line_out
.color
->blue
= 0xffff;
360 else if(process_out
->state
->s
== LTTV_STATE_WAIT
)
362 prop_line_out
.color
->red
= 0xffff;
363 prop_line_out
.color
->green
= 0x0000;
364 prop_line_out
.color
->blue
= 0x0000;
366 else if(process_out
->state
->s
== LTTV_STATE_RUN
)
368 prop_line_out
.color
->red
= 0x0000;
369 prop_line_out
.color
->green
= 0xffff;
370 prop_line_out
.color
->blue
= 0x0000;
374 prop_line_out
.color
->red
= 0x0000;
375 prop_line_out
.color
->green
= 0x0000;
376 prop_line_out
.color
->blue
= 0x0000;
379 draw_line((void*)&prop_line_out
, (void*)draw_context_out
);
380 g_free(prop_line_out
.color
);
381 gdk_gc_unref(draw_context_out
->gc
);
382 /* Note : finishing line will have to be added when trace read over. */
384 /* Finally, update the drawing context of the pid_in. */
386 DrawContext
*draw_context_in
= hashed_process_data_in
->draw_context
;
387 draw_context_in
->current
->modify_over
->x
= x
;
388 draw_context_in
->current
->modify_over
->y
= y_in
;
389 draw_context_in
->drawable
= control_flow_data
->drawing
->pixmap
;
390 draw_context_in
->pango_layout
= control_flow_data
->drawing
->pango_layout
;
391 widget
= control_flow_data
->drawing
->drawing_area
;
392 //draw_context_in->gc = widget->style->fg_gc[GTK_WIDGET_STATE (widget)];
393 //draw_context_in->gc = widget->style->black_gc;
394 draw_context_in
->gc
= gdk_gc_new(control_flow_data
->drawing
->pixmap
);
395 gdk_gc_copy(draw_context_in
->gc
, widget
->style
->black_gc
);
397 //draw_arc((void*)&prop_arc, (void*)draw_context_in);
398 //test_draw_item(control_flow_data->drawing, control_flow_data->drawing->pixmap);
400 GdkColor colorfg_in
= { 0, 0x0000, 0xffff, 0x0000 };
401 GdkColor colorbg_in
= { 0, 0xffff, 0xffff, 0xffff };
402 PropertiesText prop_text_in
;
403 prop_text_in
.foreground
= &colorfg_in
;
404 prop_text_in
.background
= &colorbg_in
;
405 prop_text_in
.size
= 10;
406 prop_text_in
.position
= OVER
;
408 /* Print status of the process : U, WF, WC, E, W, R */
409 if(process_in
->state
->s
== LTTV_STATE_UNNAMED
)
410 prop_text_in
.text
= "U";
411 else if(process_in
->state
->s
== LTTV_STATE_WAIT_FORK
)
412 prop_text_in
.text
= "WF";
413 else if(process_in
->state
->s
== LTTV_STATE_WAIT_CPU
)
414 prop_text_in
.text
= "WC";
415 else if(process_in
->state
->s
== LTTV_STATE_EXIT
)
416 prop_text_in
.text
= "E";
417 else if(process_in
->state
->s
== LTTV_STATE_WAIT
)
418 prop_text_in
.text
= "W";
419 else if(process_in
->state
->s
== LTTV_STATE_RUN
)
420 prop_text_in
.text
= "R";
422 prop_text_in
.text
= "U";
424 draw_text((void*)&prop_text_in
, (void*)draw_context_in
);
425 gdk_gc_unref(draw_context_in
->gc
);
427 /* Draw the line of the in process */
428 if(draw_context_in
->previous
->middle
->x
== -1)
430 draw_context_in
->previous
->middle
->x
= event_request
->x_begin
;
431 g_critical("in middle x_beg : %u",event_request
->x_begin
);
434 draw_context_in
->current
->middle
->x
= x
;
435 draw_context_in
->previous
->middle
->y
= y_in
+ height
/2;
436 draw_context_in
->current
->middle
->y
= y_in
+ height
/2;
437 draw_context_in
->drawable
= control_flow_data
->drawing
->pixmap
;
438 draw_context_in
->pango_layout
= control_flow_data
->drawing
->pango_layout
;
439 //draw_context_in->gc = widget->style->black_gc;
440 draw_context_in
->gc
= gdk_gc_new(control_flow_data
->drawing
->pixmap
);
441 gdk_gc_copy(draw_context_in
->gc
, widget
->style
->black_gc
);
443 PropertiesLine prop_line_in
;
444 prop_line_in
.color
= g_new(GdkColor
,1);
445 prop_line_in
.line_width
= 4;
446 prop_line_in
.style
= GDK_LINE_SOLID
;
447 prop_line_in
.position
= MIDDLE
;
449 /* color of line : status of the process */
450 if(process_in
->state
->s
== LTTV_STATE_UNNAMED
)
452 prop_line_in
.color
->red
= 0x0000;
453 prop_line_in
.color
->green
= 0x0000;
454 prop_line_in
.color
->blue
= 0x0000;
456 else if(process_in
->state
->s
== LTTV_STATE_WAIT_FORK
)
458 prop_line_in
.color
->red
= 0x0fff;
459 prop_line_in
.color
->green
= 0x0000;
460 prop_line_in
.color
->blue
= 0x0fff;
462 else if(process_in
->state
->s
== LTTV_STATE_WAIT_CPU
)
464 prop_line_in
.color
->red
= 0x0fff;
465 prop_line_in
.color
->green
= 0x0fff;
466 prop_line_in
.color
->blue
= 0x0000;
468 else if(process_in
->state
->s
== LTTV_STATE_EXIT
)
470 prop_line_in
.color
->red
= 0xffff;
471 prop_line_in
.color
->green
= 0x0000;
472 prop_line_in
.color
->blue
= 0xffff;
474 else if(process_in
->state
->s
== LTTV_STATE_WAIT
)
476 prop_line_in
.color
->red
= 0xffff;
477 prop_line_in
.color
->green
= 0x0000;
478 prop_line_in
.color
->blue
= 0x0000;
480 else if(process_in
->state
->s
== LTTV_STATE_RUN
)
482 prop_line_in
.color
->red
= 0x0000;
483 prop_line_in
.color
->green
= 0xffff;
484 prop_line_in
.color
->blue
= 0x0000;
488 prop_line_in
.color
->red
= 0x0000;
489 prop_line_in
.color
->green
= 0x0000;
490 prop_line_in
.color
->blue
= 0x0000;
493 draw_line((void*)&prop_line_in
, (void*)draw_context_in
);
494 g_free(prop_line_in
.color
);
495 gdk_gc_unref(draw_context_in
->gc
);
502 GString
*string
= g_string_new("");;
503 gboolean field_names
= TRUE
, state
= TRUE
;
505 lttv_event_to_string(e
, tfc
->tf
, string
, TRUE
, field_names
, tfs
);
506 g_string_append_printf(string
,"\n");
509 g_string_append_printf(string
, " %s",
510 g_quark_to_string(tfs
->process
->state
->s
));
513 g_info("%s",string
->str
);
515 g_string_free(string
, TRUE
);
517 /* End of text dump */
523 int draw_after_hook(void *hook_data
, void *call_data
)
525 EventRequest
*event_request
= (EventRequest
*)hook_data
;
526 ControlFlowData
*control_flow_data
= event_request
->control_flow_data
;
528 LttvTracefileContext
*tfc
= (LttvTracefileContext
*)call_data
;
530 LttvTracefileState
*tfs
= (LttvTracefileState
*)call_data
;
536 if(strcmp(ltt_eventtype_name(ltt_event_eventtype(e
)),"schedchange") == 0)
538 g_critical("schedchange!");
540 /* Add process to process list (if not present) and get drawing "y" from
541 * process position */
542 guint pid_out
, pid_in
;
543 LttvProcessState
*process_out
, *process_in
;
545 guint y_in
= 0, y_out
= 0, height
= 0, pl_height
= 0;
547 ProcessList
*process_list
=
548 guicontrolflow_get_process_list(event_request
->control_flow_data
);
551 LttField
*f
= ltt_event_field(e
);
553 element
= ltt_field_member(f
,0);
554 pid_out
= ltt_event_get_long_unsigned(e
,element
);
555 element
= ltt_field_member(f
,1);
556 pid_in
= ltt_event_get_long_unsigned(e
,element
);
557 g_critical("out : %u in : %u", pid_out
, pid_in
);
560 /* Find process pid_out in the list... */
561 process_out
= lttv_state_find_process(tfs
, pid_out
);
562 g_critical("out : %s",g_quark_to_string(process_out
->state
->s
));
564 birth
= process_out
->creation_time
;
565 gchar
*name
= strdup(g_quark_to_string(process_out
->name
));
566 HashedProcessData
*hashed_process_data_out
= NULL
;
568 if(processlist_get_process_pixels(process_list
,
573 &hashed_process_data_out
) == 1)
575 /* Process not present */
576 processlist_add(process_list
,
581 &hashed_process_data_out
);
582 processlist_get_process_pixels(process_list
,
587 &hashed_process_data_out
);
588 drawing_insert_square( event_request
->control_flow_data
->drawing
, y_out
, height
);
593 /* Find process pid_in in the list... */
594 process_in
= lttv_state_find_process(tfs
, pid_in
);
595 g_critical("in : %s",g_quark_to_string(process_in
->state
->s
));
597 birth
= process_in
->creation_time
;
598 name
= strdup(g_quark_to_string(process_in
->name
));
599 HashedProcessData
*hashed_process_data_in
= NULL
;
601 if(processlist_get_process_pixels(process_list
,
606 &hashed_process_data_in
) == 1)
608 /* Process not present */
609 processlist_add(process_list
,
614 &hashed_process_data_in
);
615 processlist_get_process_pixels(process_list
,
620 &hashed_process_data_in
);
622 drawing_insert_square( event_request
->control_flow_data
->drawing
, y_in
, height
);
627 /* Find pixels corresponding to time of the event. If the time does
628 * not fit in the window, show a warning, not supposed to happend. */
630 //guint width = control_flow_data->drawing->drawing_area->allocation.width;
632 //LttTime time = ltt_event_time(e);
634 //LttTime window_end = ltt_time_add(control_flow_data->time_window.time_width,
635 // control_flow_data->time_window.start_time);
638 //convert_time_to_pixels(
639 // control_flow_data->time_window.start_time,
645 //assert(x <= width);
647 /* draw what represents the event for outgoing process. */
649 DrawContext
*draw_context_out
= hashed_process_data_out
->draw_context
;
650 //draw_context_out->current->modify_over->x = x;
651 draw_context_out
->current
->modify_over
->y
= y_out
;
652 draw_context_out
->drawable
= control_flow_data
->drawing
->pixmap
;
653 draw_context_out
->pango_layout
= control_flow_data
->drawing
->pango_layout
;
654 GtkWidget
*widget
= control_flow_data
->drawing
->drawing_area
;
655 //draw_context_out->gc = widget->style->fg_gc[GTK_WIDGET_STATE (widget)];
656 draw_context_out
->gc
= widget
->style
->black_gc
;
658 //draw_arc((void*)&prop_arc, (void*)draw_context_out);
659 //test_draw_item(control_flow_data->drawing, control_flow_data->drawing->pixmap);
661 GdkColor colorfg_out
= { 0, 0xffff, 0x0000, 0x0000 };
662 GdkColor colorbg_out
= { 0, 0xffff, 0xffff, 0xffff };
663 PropertiesText prop_text_out
;
664 prop_text_out
.foreground
= &colorfg_out
;
665 prop_text_out
.background
= &colorbg_out
;
666 prop_text_out
.size
= 10;
667 prop_text_out
.position
= OVER
;
669 /* Print status of the process : U, WF, WC, E, W, R */
670 if(process_out
->state
->s
== LTTV_STATE_UNNAMED
)
671 prop_text_out
.text
= "U";
672 else if(process_out
->state
->s
== LTTV_STATE_WAIT_FORK
)
673 prop_text_out
.text
= "WF";
674 else if(process_out
->state
->s
== LTTV_STATE_WAIT_CPU
)
675 prop_text_out
.text
= "WC";
676 else if(process_out
->state
->s
== LTTV_STATE_EXIT
)
677 prop_text_out
.text
= "E";
678 else if(process_out
->state
->s
== LTTV_STATE_WAIT
)
679 prop_text_out
.text
= "W";
680 else if(process_out
->state
->s
== LTTV_STATE_RUN
)
681 prop_text_out
.text
= "R";
683 prop_text_out
.text
= "U";
685 draw_text((void*)&prop_text_out
, (void*)draw_context_out
);
687 draw_context_out
->current
->middle
->y
= y_out
+height
/2;
688 draw_context_out
->current
->status
= process_out
->state
->s
;
690 /* for pid_out : remove previous, Prev = current, new current (default) */
691 g_free(draw_context_out
->previous
->modify_under
);
692 g_free(draw_context_out
->previous
->modify_middle
);
693 g_free(draw_context_out
->previous
->modify_over
);
694 g_free(draw_context_out
->previous
->under
);
695 g_free(draw_context_out
->previous
->middle
);
696 g_free(draw_context_out
->previous
->over
);
697 g_free(draw_context_out
->previous
);
699 draw_context_out
->previous
= draw_context_out
->current
;
701 draw_context_out
->current
= g_new(DrawInfo
,1);
702 draw_context_out
->current
->over
= g_new(ItemInfo
,1);
703 draw_context_out
->current
->over
->x
= -1;
704 draw_context_out
->current
->over
->y
= -1;
705 draw_context_out
->current
->middle
= g_new(ItemInfo
,1);
706 draw_context_out
->current
->middle
->x
= -1;
707 draw_context_out
->current
->middle
->y
= -1;
708 draw_context_out
->current
->under
= g_new(ItemInfo
,1);
709 draw_context_out
->current
->under
->x
= -1;
710 draw_context_out
->current
->under
->y
= -1;
711 draw_context_out
->current
->modify_over
= g_new(ItemInfo
,1);
712 draw_context_out
->current
->modify_over
->x
= -1;
713 draw_context_out
->current
->modify_over
->y
= -1;
714 draw_context_out
->current
->modify_middle
= g_new(ItemInfo
,1);
715 draw_context_out
->current
->modify_middle
->x
= -1;
716 draw_context_out
->current
->modify_middle
->y
= -1;
717 draw_context_out
->current
->modify_under
= g_new(ItemInfo
,1);
718 draw_context_out
->current
->modify_under
->x
= -1;
719 draw_context_out
->current
->modify_under
->y
= -1;
720 draw_context_out
->current
->status
= LTTV_STATE_UNNAMED
;
722 /* Finally, update the drawing context of the pid_in. */
724 DrawContext
*draw_context_in
= hashed_process_data_in
->draw_context
;
725 //draw_context_in->current->modify_over->x = x;
726 draw_context_in
->current
->modify_over
->y
= y_in
;
727 draw_context_in
->drawable
= control_flow_data
->drawing
->pixmap
;
728 draw_context_in
->pango_layout
= control_flow_data
->drawing
->pango_layout
;
729 widget
= control_flow_data
->drawing
->drawing_area
;
730 //draw_context_in->gc = widget->style->fg_gc[GTK_WIDGET_STATE (widget)];
731 draw_context_in
->gc
= widget
->style
->black_gc
;
733 //draw_arc((void*)&prop_arc, (void*)draw_context_in);
734 //test_draw_item(control_flow_data->drawing, control_flow_data->drawing->pixmap);
736 GdkColor colorfg_in
= { 0, 0x0000, 0xffff, 0x0000 };
737 GdkColor colorbg_in
= { 0, 0xffff, 0xffff, 0xffff };
738 PropertiesText prop_text_in
;
739 prop_text_in
.foreground
= &colorfg_in
;
740 prop_text_in
.background
= &colorbg_in
;
741 prop_text_in
.size
= 10;
742 prop_text_in
.position
= OVER
;
744 /* Print status of the process : U, WF, WC, E, W, R */
745 if(process_in
->state
->s
== LTTV_STATE_UNNAMED
)
746 prop_text_in
.text
= "U";
747 else if(process_in
->state
->s
== LTTV_STATE_WAIT_FORK
)
748 prop_text_in
.text
= "WF";
749 else if(process_in
->state
->s
== LTTV_STATE_WAIT_CPU
)
750 prop_text_in
.text
= "WC";
751 else if(process_in
->state
->s
== LTTV_STATE_EXIT
)
752 prop_text_in
.text
= "E";
753 else if(process_in
->state
->s
== LTTV_STATE_WAIT
)
754 prop_text_in
.text
= "W";
755 else if(process_in
->state
->s
== LTTV_STATE_RUN
)
756 prop_text_in
.text
= "R";
758 prop_text_in
.text
= "U";
760 draw_text((void*)&prop_text_in
, (void*)draw_context_in
);
762 draw_context_in
->current
->middle
->y
= y_in
+height
/2;
763 draw_context_in
->current
->status
= process_in
->state
->s
;
765 /* for pid_in : remove previous, Prev = current, new current (default) */
766 g_free(draw_context_in
->previous
->modify_under
);
767 g_free(draw_context_in
->previous
->modify_middle
);
768 g_free(draw_context_in
->previous
->modify_over
);
769 g_free(draw_context_in
->previous
->under
);
770 g_free(draw_context_in
->previous
->middle
);
771 g_free(draw_context_in
->previous
->over
);
772 g_free(draw_context_in
->previous
);
774 draw_context_in
->previous
= draw_context_in
->current
;
776 draw_context_in
->current
= g_new(DrawInfo
,1);
777 draw_context_in
->current
->over
= g_new(ItemInfo
,1);
778 draw_context_in
->current
->over
->x
= -1;
779 draw_context_in
->current
->over
->y
= -1;
780 draw_context_in
->current
->middle
= g_new(ItemInfo
,1);
781 draw_context_in
->current
->middle
->x
= -1;
782 draw_context_in
->current
->middle
->y
= -1;
783 draw_context_in
->current
->under
= g_new(ItemInfo
,1);
784 draw_context_in
->current
->under
->x
= -1;
785 draw_context_in
->current
->under
->y
= -1;
786 draw_context_in
->current
->modify_over
= g_new(ItemInfo
,1);
787 draw_context_in
->current
->modify_over
->x
= -1;
788 draw_context_in
->current
->modify_over
->y
= -1;
789 draw_context_in
->current
->modify_middle
= g_new(ItemInfo
,1);
790 draw_context_in
->current
->modify_middle
->x
= -1;
791 draw_context_in
->current
->modify_middle
->y
= -1;
792 draw_context_in
->current
->modify_under
= g_new(ItemInfo
,1);
793 draw_context_in
->current
->modify_under
->x
= -1;
794 draw_context_in
->current
->modify_under
->y
= -1;
795 draw_context_in
->current
->status
= LTTV_STATE_UNNAMED
;
805 gint
update_time_window_hook(void *hook_data
, void *call_data
)
807 ControlFlowData
*control_flow_data
= (ControlFlowData
*) hook_data
;
808 TimeWindow
*old_time_window
=
809 guicontrolflow_get_time_window(control_flow_data
);
810 TimeWindow
*new_time_window
= ((TimeWindow
*)call_data
);
812 /* Two cases : zoom in/out or scrolling */
814 /* In order to make sure we can reuse the old drawing, the scale must
815 * be the same and the new time interval being partly located in the
816 * currently shown time interval. (reuse is only for scrolling)
819 g_info("Old time window HOOK : %u, %u to %u, %u",
820 old_time_window
->start_time
.tv_sec
,
821 old_time_window
->start_time
.tv_nsec
,
822 old_time_window
->time_width
.tv_sec
,
823 old_time_window
->time_width
.tv_nsec
);
825 g_info("New time window HOOK : %u, %u to %u, %u",
826 new_time_window
->start_time
.tv_sec
,
827 new_time_window
->start_time
.tv_nsec
,
828 new_time_window
->time_width
.tv_sec
,
829 new_time_window
->time_width
.tv_nsec
);
831 if( new_time_window
->time_width
.tv_sec
== old_time_window
->time_width
.tv_sec
832 && new_time_window
->time_width
.tv_nsec
== old_time_window
->time_width
.tv_nsec
)
834 /* Same scale (scrolling) */
836 LttTime
*ns
= &new_time_window
->start_time
;
837 LttTime
*os
= &old_time_window
->start_time
;
838 LttTime old_end
= ltt_time_add(old_time_window
->start_time
,
839 old_time_window
->time_width
);
840 LttTime new_end
= ltt_time_add(new_time_window
->start_time
,
841 new_time_window
->time_width
);
843 //if(ns<os+w && os+w<ns+w)
844 //if(ns<old_end && os<ns)
845 if(ltt_time_compare(*ns
, old_end
) == -1
846 && ltt_time_compare(*os
, *ns
) == -1)
848 g_info("scrolling near right");
849 /* Scroll right, keep right part of the screen */
851 guint width
= control_flow_data
->drawing
->drawing_area
->allocation
.width
;
852 convert_time_to_pixels(
859 /* Copy old data to new location */
860 gdk_draw_drawable (control_flow_data
->drawing
->pixmap
,
861 control_flow_data
->drawing
->drawing_area
->style
->white_gc
,
862 control_flow_data
->drawing
->pixmap
,
867 convert_time_to_pixels(
874 *old_time_window
= *new_time_window
;
875 /* Clear the data request background, but not SAFETY */
876 gdk_draw_rectangle (control_flow_data
->drawing
->pixmap
,
877 control_flow_data
->drawing
->drawing_area
->style
->white_gc
,
880 control_flow_data
->drawing
->width
- x
, // do not overlap
881 control_flow_data
->drawing
->height
+SAFETY
);
882 /* Get new data for the rest. */
883 drawing_data_request(control_flow_data
->drawing
,
884 &control_flow_data
->drawing
->pixmap
,
886 control_flow_data
->drawing
->width
- x
,
887 control_flow_data
->drawing
->height
);
889 drawing_refresh(control_flow_data
->drawing
,
891 control_flow_data
->drawing
->width
,
892 control_flow_data
->drawing
->height
);
897 //if(ns<os && os<ns+w)
898 //if(ns<os && os<new_end)
899 if(ltt_time_compare(*ns
,*os
) == -1
900 && ltt_time_compare(*os
,new_end
) == -1)
902 g_info("scrolling near left");
903 /* Scroll left, keep left part of the screen */
905 guint width
= control_flow_data
->drawing
->drawing_area
->allocation
.width
;
906 convert_time_to_pixels(
913 /* Copy old data to new location */
914 gdk_draw_drawable (control_flow_data
->drawing
->pixmap
,
915 control_flow_data
->drawing
->drawing_area
->style
->white_gc
,
916 control_flow_data
->drawing
->pixmap
,
921 *old_time_window
= *new_time_window
;
923 /* Clean the data request background */
924 gdk_draw_rectangle (control_flow_data
->drawing
->pixmap
,
925 control_flow_data
->drawing
->drawing_area
->style
->white_gc
,
929 control_flow_data
->drawing
->height
+SAFETY
);
930 /* Get new data for the rest. */
931 drawing_data_request(control_flow_data
->drawing
,
932 &control_flow_data
->drawing
->pixmap
,
935 control_flow_data
->drawing
->height
);
937 drawing_refresh(control_flow_data
->drawing
,
939 control_flow_data
->drawing
->width
,
940 control_flow_data
->drawing
->height
);
943 g_info("scrolling far");
944 /* Cannot reuse any part of the screen : far jump */
945 *old_time_window
= *new_time_window
;
948 gdk_draw_rectangle (control_flow_data
->drawing
->pixmap
,
949 control_flow_data
->drawing
->drawing_area
->style
->white_gc
,
952 control_flow_data
->drawing
->width
+SAFETY
, // do not overlap
953 control_flow_data
->drawing
->height
+SAFETY
);
955 drawing_data_request(control_flow_data
->drawing
,
956 &control_flow_data
->drawing
->pixmap
,
958 control_flow_data
->drawing
->width
,
959 control_flow_data
->drawing
->height
);
961 drawing_refresh(control_flow_data
->drawing
,
963 control_flow_data
->drawing
->width
,
964 control_flow_data
->drawing
->height
);
968 /* Different scale (zoom) */
971 *old_time_window
= *new_time_window
;
973 gdk_draw_rectangle (control_flow_data
->drawing
->pixmap
,
974 control_flow_data
->drawing
->drawing_area
->style
->white_gc
,
977 control_flow_data
->drawing
->width
+SAFETY
, // do not overlap
978 control_flow_data
->drawing
->height
+SAFETY
);
981 drawing_data_request(control_flow_data
->drawing
,
982 &control_flow_data
->drawing
->pixmap
,
984 control_flow_data
->drawing
->width
,
985 control_flow_data
->drawing
->height
);
987 drawing_refresh(control_flow_data
->drawing
,
989 control_flow_data
->drawing
->width
,
990 control_flow_data
->drawing
->height
);
996 gint
update_current_time_hook(void *hook_data
, void *call_data
)
998 ControlFlowData
*control_flow_data
= (ControlFlowData
*)hook_data
;
1000 LttTime
* current_time
=
1001 guicontrolflow_get_current_time(control_flow_data
);
1002 *current_time
= *((LttTime
*)call_data
);
1004 TimeWindow time_window
;
1006 LttTime time_begin
= control_flow_data
->time_window
.start_time
;
1007 LttTime width
= control_flow_data
->time_window
.time_width
;
1008 LttTime half_width
= ltt_time_div(width
,2.0);
1009 LttTime time_end
= ltt_time_add(time_begin
, width
);
1011 LttvTracesetContext
* tsc
=
1012 get_traceset_context(control_flow_data
->mw
);
1014 LttTime trace_start
= tsc
->Time_Span
->startTime
;
1015 LttTime trace_end
= tsc
->Time_Span
->endTime
;
1017 g_info("New current time HOOK : %u, %u", current_time
->tv_sec
,
1018 current_time
->tv_nsec
);
1022 /* If current time is inside time interval, just move the highlight
1025 /* Else, we have to change the time interval. We have to tell it
1026 * to the main window. */
1027 /* The time interval change will take care of placing the current
1028 * time at the center of the visible area, or nearest possible if we are
1029 * at one end of the trace. */
1032 if(ltt_time_compare(*current_time
, time_begin
) == -1)
1034 if(ltt_time_compare(*current_time
,
1035 ltt_time_add(trace_start
,half_width
)) == -1)
1036 time_begin
= trace_start
;
1038 time_begin
= ltt_time_sub(*current_time
,half_width
);
1040 time_window
.start_time
= time_begin
;
1041 time_window
.time_width
= width
;
1043 set_time_window(control_flow_data
->mw
, &time_window
);
1045 else if(ltt_time_compare(*current_time
, time_end
) == 1)
1047 if(ltt_time_compare(*current_time
, ltt_time_sub(trace_end
, half_width
)) == 1)
1048 time_begin
= ltt_time_sub(trace_end
,width
);
1050 time_begin
= ltt_time_sub(*current_time
,half_width
);
1052 time_window
.start_time
= time_begin
;
1053 time_window
.time_width
= width
;
1055 set_time_window(control_flow_data
->mw
, &time_window
);
1058 gtk_widget_queue_draw(control_flow_data
->drawing
->drawing_area
);
1063 typedef struct _ClosureData
{
1064 EventRequest
*event_request
;
1069 void draw_closure(gpointer key
, gpointer value
, gpointer user_data
)
1071 ProcessInfo
*process_info
= (ProcessInfo
*)key
;
1072 HashedProcessData
*hashed_process_data
= (HashedProcessData
*)value
;
1073 ClosureData
*closure_data
= (ClosureData
*)user_data
;
1075 ControlFlowData
*control_flow_data
=
1076 closure_data
->event_request
->control_flow_data
;
1078 GtkWidget
*widget
= control_flow_data
->drawing
->drawing_area
;
1080 /* Get y position of process */
1083 processlist_get_pixels_from_data( control_flow_data
->process_list
,
1085 hashed_process_data
,
1088 /* Get last state of process */
1089 LttvTraceContext
*tc
=
1090 (LttvTraceContext
*)closure_data
->ts
;
1092 LttvTraceState
*ts
= closure_data
->ts
;
1093 LttvProcessState
*process
;
1095 process
= lttv_state_find_process((LttvTracefileState
*)ts
, process_info
->pid
);
1097 /* Draw the closing line */
1098 DrawContext
*draw_context
= hashed_process_data
->draw_context
;
1099 if(draw_context
->previous
->middle
->x
== -1)
1101 draw_context
->previous
->middle
->x
= closure_data
->event_request
->x_begin
;
1102 g_critical("out middle x_beg : %u",closure_data
->event_request
->x_begin
);
1105 draw_context
->current
->middle
->x
= closure_data
->event_request
->x_end
;
1106 draw_context
->current
->middle
->y
= y
+ height
/2;
1107 draw_context
->previous
->middle
->y
= y
+ height
/2;
1108 draw_context
->drawable
= control_flow_data
->drawing
->pixmap
;
1109 draw_context
->pango_layout
= control_flow_data
->drawing
->pango_layout
;
1110 //draw_context->gc = widget->style->black_gc;
1111 draw_context
->gc
= gdk_gc_new(control_flow_data
->drawing
->pixmap
);
1112 gdk_gc_copy(draw_context
->gc
, widget
->style
->black_gc
);
1114 PropertiesLine prop_line
;
1115 prop_line
.color
= g_new(GdkColor
,1);
1116 prop_line
.line_width
= 6;
1117 prop_line
.style
= GDK_LINE_SOLID
;
1118 prop_line
.position
= MIDDLE
;
1120 /* color of line : status of the process */
1121 if(process
->state
->s
== LTTV_STATE_UNNAMED
)
1123 prop_line
.color
->red
= 0x0000;
1124 prop_line
.color
->green
= 0x0000;
1125 prop_line
.color
->blue
= 0x0000;
1127 else if(process
->state
->s
== LTTV_STATE_WAIT_FORK
)
1129 prop_line
.color
->red
= 0x0fff;
1130 prop_line
.color
->green
= 0x0000;
1131 prop_line
.color
->blue
= 0x0fff;
1133 else if(process
->state
->s
== LTTV_STATE_WAIT_CPU
)
1135 prop_line
.color
->red
= 0x0fff;
1136 prop_line
.color
->green
= 0x0fff;
1137 prop_line
.color
->blue
= 0x0000;
1139 else if(process
->state
->s
== LTTV_STATE_EXIT
)
1141 prop_line
.color
->red
= 0xffff;
1142 prop_line
.color
->green
= 0x0000;
1143 prop_line
.color
->blue
= 0xffff;
1145 else if(process
->state
->s
== LTTV_STATE_WAIT
)
1147 prop_line
.color
->red
= 0xffff;
1148 prop_line
.color
->green
= 0x0000;
1149 prop_line
.color
->blue
= 0x0000;
1151 else if(process
->state
->s
== LTTV_STATE_RUN
)
1153 prop_line
.color
->red
= 0x0000;
1154 prop_line
.color
->green
= 0xffff;
1155 prop_line
.color
->blue
= 0x0000;
1159 prop_line
.color
->red
= 0x0000;
1160 prop_line
.color
->green
= 0x0000;
1161 prop_line
.color
->blue
= 0x0000;
1164 draw_line((void*)&prop_line
, (void*)draw_context
);
1165 g_free(prop_line
.color
);
1166 gdk_gc_unref(draw_context
->gc
);
1168 /* Reset draw_context of the process for next request */
1170 hashed_process_data
->draw_context
->drawable
= NULL
;
1171 hashed_process_data
->draw_context
->gc
= NULL
;
1172 hashed_process_data
->draw_context
->pango_layout
= NULL
;
1173 hashed_process_data
->draw_context
->current
->over
->x
= -1;
1174 hashed_process_data
->draw_context
->current
->over
->y
= -1;
1175 hashed_process_data
->draw_context
->current
->middle
->x
= -1;
1176 hashed_process_data
->draw_context
->current
->middle
->y
= -1;
1177 hashed_process_data
->draw_context
->current
->under
->x
= -1;
1178 hashed_process_data
->draw_context
->current
->under
->y
= -1;
1179 hashed_process_data
->draw_context
->current
->modify_over
->x
= -1;
1180 hashed_process_data
->draw_context
->current
->modify_over
->y
= -1;
1181 hashed_process_data
->draw_context
->current
->modify_middle
->x
= -1;
1182 hashed_process_data
->draw_context
->current
->modify_middle
->y
= -1;
1183 hashed_process_data
->draw_context
->current
->modify_under
->x
= -1;
1184 hashed_process_data
->draw_context
->current
->modify_under
->y
= -1;
1185 hashed_process_data
->draw_context
->current
->status
= LTTV_STATE_UNNAMED
;
1186 hashed_process_data
->draw_context
->previous
->over
->x
= -1;
1187 hashed_process_data
->draw_context
->previous
->over
->y
= -1;
1188 hashed_process_data
->draw_context
->previous
->middle
->x
= -1;
1189 hashed_process_data
->draw_context
->previous
->middle
->y
= -1;
1190 hashed_process_data
->draw_context
->previous
->under
->x
= -1;
1191 hashed_process_data
->draw_context
->previous
->under
->y
= -1;
1192 hashed_process_data
->draw_context
->previous
->modify_over
->x
= -1;
1193 hashed_process_data
->draw_context
->previous
->modify_over
->y
= -1;
1194 hashed_process_data
->draw_context
->previous
->modify_middle
->x
= -1;
1195 hashed_process_data
->draw_context
->previous
->modify_middle
->y
= -1;
1196 hashed_process_data
->draw_context
->previous
->modify_under
->x
= -1;
1197 hashed_process_data
->draw_context
->previous
->modify_under
->y
= -1;
1198 hashed_process_data
->draw_context
->previous
->status
= LTTV_STATE_UNNAMED
;
1206 * new default prev and current
1208 int after_data_request(void *hook_data
, void *call_data
)
1210 EventRequest
*event_request
= (EventRequest
*)hook_data
;
1211 ControlFlowData
*control_flow_data
= event_request
->control_flow_data
;
1213 ProcessList
*process_list
=
1214 guicontrolflow_get_process_list(event_request
->control_flow_data
);
1216 ClosureData closure_data
;
1217 closure_data
.event_request
= (EventRequest
*)hook_data
;
1218 closure_data
.ts
= (LttvTraceState
*)call_data
;
1220 g_hash_table_foreach(process_list
->process_hash
, draw_closure
,
1221 (void*)&closure_data
);