Commit | Line | Data |
---|---|---|
1684ba2e | 1 | /* This file is part of the Linux Trace Toolkit viewer |
2 | * Copyright (C) 2006 Parisa heidari (inspired from CFV by 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 | ||
20 | /***************************************************************************** | |
21 | * Hooks to be called by the main window * | |
22 | *****************************************************************************/ | |
23 | ||
24 | ||
25 | /* Event hooks are the drawing hooks called during traceset read. They draw the | |
26 | * icons, text, lines and background color corresponding to the events read. | |
27 | * | |
28 | * Two hooks are used for drawing : before_schedchange and after_schedchange hooks. The | |
29 | * before_schedchange is called before the state update that occurs with an event and | |
30 | * the after_schedchange hook is called after this state update. | |
31 | * | |
32 | * The before_schedchange hooks fulfill the task of drawing the visible objects that | |
33 | * corresponds to the data accumulated by the after_schedchange hook. | |
34 | * | |
35 | * The after_schedchange hook accumulates the data that need to be shown on the screen | |
36 | * (items) into a queue. Then, the next before_schedchange hook will draw what that | |
37 | * queue contains. That's the Right Way (TM) of drawing items on the screen, | |
38 | * because we need to draw the background first (and then add icons, text, ... | |
39 | * over it), but we only know the length of a background region once the state | |
40 | * corresponding to it is over, which happens to be at the next before_schedchange | |
41 | * hook. | |
42 | * | |
43 | * We also have a hook called at the end of a chunk to draw the information left | |
44 | * undrawn in each process queue. We use the current time as end of | |
45 | * line/background. | |
46 | */ | |
47 | ||
48 | #ifdef HAVE_CONFIG_H | |
49 | #include <config.h> | |
50 | #endif | |
51 | ||
52 | //#define PANGO_ENABLE_BACKEND | |
53 | #include <gtk/gtk.h> | |
54 | #include <gdk/gdk.h> | |
55 | #include <glib.h> | |
56 | #include <assert.h> | |
57 | #include <string.h> | |
58 | #include <stdio.h> | |
59 | ||
60 | //#include <pango/pango.h> | |
61 | ||
1684ba2e | 62 | #include <lttv/lttv.h> |
63 | #include <lttv/hook.h> | |
64 | #include <lttv/state.h> | |
65 | #include <lttvwindow/lttvwindow.h> | |
66 | #include <lttvwindow/lttvwindowtraces.h> | |
67 | #include <lttvwindow/support.h> | |
68 | ||
69 | ||
70 | #include "histoeventhooks.h" | |
71 | #include "histocfv.h" | |
72 | #include "histobuttonwidget.h" | |
73 | #include "histodrawing.h" | |
74 | ||
75 | ||
76 | #define MAX_PATH_LEN 256 | |
77 | #define g_info(format...) g_log (G_LOG_DOMAIN, G_LOG_LEVEL_INFO, format) | |
78 | //FIXME | |
d2a03e9d | 79 | // fixed #define TRACE_NUMBER 0 |
1684ba2e | 80 | #define EXTRA_ALLOC 1024 // pixels |
81 | ||
8d8c5ea7 AM |
82 | /* |
83 | * Most functions here are inspired from the controlflow module. | |
84 | * Look in gui/controlflow/eventhooks.c if you need to add more functionality | |
1684ba2e | 85 | */ |
1684ba2e | 86 | |
87 | /** | |
88 | * Histogram Viewer's constructor hook | |
89 | * | |
90 | * This constructor is given as a parameter to the menuitem and toolbar button | |
91 | * registration. It creates the list. | |
92 | * @param tab A pointer to the parent tab. | |
93 | * @return The widget created. | |
94 | */ | |
95 | GtkWidget * | |
e433e6d6 | 96 | h_guihistocontrolflow(LttvPlugin *plugin) |
1684ba2e | 97 | { |
e433e6d6 | 98 | LttvPluginTab *ptab = LTTV_PLUGIN_TAB(plugin); |
99 | g_info("h_guihistocontrolflow, %p", ptab); | |
100 | HistoControlFlowData *histocontrol_flow_data = guihistocontrolflow(ptab) ; | |
1684ba2e | 101 | |
e433e6d6 | 102 | Tab *tab = ptab->tab; |
1684ba2e | 103 | histocontrol_flow_data->tab = tab; |
104 | ||
105 | // Unreg done in the GuiHistoControlFlow_Destructor | |
106 | lttvwindow_register_traceset_notify(tab, | |
107 | histo_traceset_notify, | |
108 | histocontrol_flow_data); | |
109 | ||
110 | lttvwindow_register_time_window_notify(tab, | |
111 | histo_update_time_window_hook, | |
112 | histocontrol_flow_data); | |
113 | lttvwindow_register_current_time_notify(tab, | |
114 | histo_update_current_time_hook, | |
115 | histocontrol_flow_data); | |
116 | lttvwindow_register_redraw_notify(tab, | |
117 | histo_redraw_notify, | |
118 | histocontrol_flow_data); | |
119 | lttvwindow_register_continue_notify(tab, | |
120 | histo_continue_notify, | |
121 | histocontrol_flow_data); | |
122 | //added for histogram, enable filter: | |
123 | lttvwindow_register_filter_notify(tab, | |
124 | histo_filter_changed,histocontrol_flow_data ); | |
125 | histocontrol_flow_data->histo_main_win_filter = lttvwindow_get_filter(tab); | |
126 | ||
127 | // histo_request_background_data(histocontrol_flow_data); | |
128 | ||
129 | return guihistocontrolflow_get_widget(histocontrol_flow_data) ; | |
130 | ||
131 | } | |
132 | ||
133 | ||
134 | ||
135 | /// added for histogram. | |
136 | void histo_request_event( HistoControlFlowData *histocontrol_flow_data, guint x, guint width) | |
137 | { | |
138 | if(width < 0) return ; | |
139 | ||
140 | guint i, nb_trace; | |
141 | Tab *tab = histocontrol_flow_data->tab; | |
142 | TimeWindow time_window = lttvwindow_get_time_window( tab ); | |
143 | LttTime time_start, time_end; | |
144 | ||
1684ba2e | 145 | //find the tracehooks |
64242d13 | 146 | LttvTraceset *traceset = lttvwindow_get_traceset(tab); |
1684ba2e | 147 | |
1684ba2e | 148 | nb_trace = lttv_traceset_number(traceset); |
149 | guint drawing_width= histocontrol_flow_data->drawing->width; | |
150 | //start time for chunk. | |
151 | histo_convert_pixels_to_time(drawing_width, /*0*/x, time_window, | |
152 | &time_start); | |
153 | //end time for chunk. | |
154 | histo_convert_pixels_to_time(drawing_width, | |
155 | /*width*/x+width,time_window, | |
156 | &time_end); | |
157 | time_end = ltt_time_add(time_end, ltt_time_one); // because main window | |
158 | // doesn't deliver end time. | |
159 | ||
160 | lttvwindow_events_request_remove_all(tab, | |
161 | histocontrol_flow_data); | |
162 | ||
163 | ||
164 | // LttvHooksById *histo_event_by_id = lttv_hooks_by_id_new();//if necessary for filter! | |
165 | // FIXME : eventually request for more traces | |
d2a03e9d | 166 | // fixed for(i = 0; i<MIN(TRACE_NUMBER+1, nb_trace);i++) { |
64242d13 | 167 | //TODO ybrosseau 2012-07-10: Just do one request |
d2a03e9d | 168 | for(i=0;i<nb_trace;i++) { |
1684ba2e | 169 | //should be in the loop or before? |
170 | EventsRequest *histo_events_request = g_new(EventsRequest, 1); | |
171 | ||
172 | LttvHooks *histo_before_trace_hooks = lttv_hooks_new(); | |
173 | lttv_hooks_add(histo_before_trace_hooks, histo_before_trace, | |
174 | histo_events_request, LTTV_PRIO_DEFAULT); | |
175 | ||
176 | LttvHooks *histo_count_event_hooks = lttv_hooks_new(); | |
177 | lttv_hooks_add(histo_count_event_hooks, histo_count_event, | |
178 | histo_events_request, LTTV_PRIO_DEFAULT); | |
179 | ||
180 | LttvHooks *histo_after_trace_hooks = lttv_hooks_new(); | |
181 | lttv_hooks_add(histo_after_trace_hooks, histo_after_trace, | |
182 | histo_events_request, LTTV_PRIO_DEFAULT); | |
183 | ||
184 | //for chunk: | |
185 | LttvHooks *histo_before_chunk_traceset = lttv_hooks_new(); | |
186 | LttvHooks *histo_after_chunk_traceset = lttv_hooks_new(); | |
187 | ||
188 | lttv_hooks_add(histo_before_chunk_traceset, | |
189 | histo_before_chunk, | |
190 | histo_events_request, | |
191 | LTTV_PRIO_DEFAULT); | |
192 | ||
193 | lttv_hooks_add(histo_after_chunk_traceset, | |
194 | histo_after_chunk, | |
195 | histo_events_request, | |
196 | LTTV_PRIO_DEFAULT); | |
1684ba2e | 197 | // Fill the events request |
198 | histo_events_request->owner = histocontrol_flow_data; | |
199 | histo_events_request->viewer_data = histocontrol_flow_data; | |
200 | histo_events_request->servicing = FALSE; | |
201 | histo_events_request->start_time = time_start;//time_window.start_time; | |
202 | ||
203 | histo_events_request->start_position = NULL; | |
204 | histo_events_request->stop_flag = FALSE; | |
205 | histo_events_request->end_time = time_end;//time_window.end_time; | |
206 | ||
207 | histo_events_request->num_events = G_MAXUINT; | |
208 | histo_events_request->end_position = NULL; | |
209 | histo_events_request->trace = i; | |
210 | histo_events_request->hooks = NULL; | |
211 | histo_events_request->before_chunk_traceset = histo_before_chunk_traceset;//NULL; | |
212 | histo_events_request->before_chunk_trace = NULL; | |
213 | histo_events_request->before_chunk_tracefile= NULL; | |
214 | histo_events_request->event = histo_count_event_hooks; | |
1684ba2e | 215 | histo_events_request->after_chunk_tracefile = NULL; |
216 | histo_events_request->after_chunk_trace = NULL; | |
217 | histo_events_request->after_chunk_traceset = histo_after_chunk_traceset;//NULL; | |
218 | histo_events_request->before_request = histo_before_trace_hooks; | |
219 | histo_events_request->after_request = histo_after_trace_hooks; | |
220 | ||
221 | lttvwindow_events_request(histocontrol_flow_data->tab, histo_events_request); | |
222 | } | |
223 | return; | |
224 | } | |
225 | ||
226 | //hook,added for histogram | |
227 | int histo_count_event(void *hook_data, void *call_data){ | |
228 | ||
229 | guint x;//time to pixel | |
1684ba2e | 230 | LttTime event_time; |
64242d13 | 231 | LttvEvent *e; |
1684ba2e | 232 | guint *element; |
233 | ||
234 | EventsRequest *events_request = (EventsRequest*)hook_data; | |
235 | HistoControlFlowData *histocontrol_flow_data = events_request->viewer_data; | |
236 | ||
237 | histoDrawing_t *drawing = histocontrol_flow_data->drawing; | |
238 | int width = drawing->width; | |
239 | ||
240 | g_info("Histogram: count_event() \n"); | |
241 | ||
64242d13 YB |
242 | e = (LttvEvent *)call_data; |
243 | #ifdef BABEL_CLEANUP | |
1684ba2e | 244 | LttvFilter *histo_filter = histocontrol_flow_data->histo_main_win_filter; |
245 | if(histo_filter != NULL && histo_filter->head != NULL) | |
246 | if(!lttv_filter_tree_parse(histo_filter->head,e,tfc->tf, | |
b6ef18af | 247 | tfc->t_context->t,tfc,NULL,NULL)) |
1684ba2e | 248 | return FALSE; |
64242d13 | 249 | #endif |
1684ba2e | 250 | TimeWindow time_window = lttvwindow_get_time_window(histocontrol_flow_data->tab); |
64242d13 | 251 | event_time = lttv_event_get_timestamp(e); |
1684ba2e | 252 | |
253 | histo_convert_time_to_pixels( | |
254 | time_window, | |
255 | event_time, | |
256 | width, | |
257 | &x); | |
258 | element = &g_array_index(histocontrol_flow_data->number_of_process, guint, x); | |
259 | (*element)++; | |
260 | ||
261 | return 0; | |
262 | } | |
263 | ///befor hook:Added for histogram | |
264 | int histo_before_trace(void *hook_data, void *call_data){ | |
265 | ||
266 | EventsRequest *events_request = (EventsRequest*)hook_data; | |
267 | HistoControlFlowData *histocontrol_flow_data = events_request->viewer_data; | |
268 | ||
269 | histoDrawing_t *drawing = histocontrol_flow_data->drawing; | |
270 | ||
271 | //in order to reset all of the array elements. | |
272 | guint i,end; | |
273 | end = MIN(histocontrol_flow_data->number_of_process->len,drawing->damage_end); | |
274 | for(i=drawing->damage_begin/*0*/; | |
275 | i < end/*histocontrol_flow_data->number_of_process->len*/;i++) | |
276 | { | |
277 | g_array_index(histocontrol_flow_data->number_of_process, guint, i) = 0; | |
278 | } | |
279 | histo_drawing_clear(drawing,drawing->damage_begin/*0*/, | |
280 | drawing->damage_end - drawing->damage_begin/*drawing->width*/); | |
281 | //g_array_free(histocontrol_flow_data->number_of_process,TRUE); | |
282 | //histocontrol_flow_data->number_of_process =g_array_new (FALSE, | |
283 | // TRUE, | |
284 | // sizeof(guint));//4 byte for guint | |
285 | //g_array_set_size (histocontrol_flow_data->number_of_process, | |
286 | // drawing->drawing_area->allocation.width); | |
287 | // gtk_widget_set_size_request(drawing->drawing_area,-1,-1); | |
288 | gtk_widget_queue_draw(drawing->drawing_area); | |
289 | return 0; | |
290 | } | |
291 | //after hook,added for histogram | |
292 | int histo_after_trace(void *hook_data, void *call_data){ | |
293 | ||
294 | EventsRequest *events_request = (EventsRequest*)hook_data; | |
295 | HistoControlFlowData *histocontrol_flow_data = events_request->viewer_data; | |
296 | histoDrawing_t *drawing = histocontrol_flow_data->drawing; | |
297 | guint x, x_end, width; | |
298 | LttTime end_time = events_request->end_time; | |
299 | TimeWindow time_window = | |
300 | lttvwindow_get_time_window(histocontrol_flow_data->tab); | |
301 | ||
302 | g_debug("histo after trace"); | |
303 | ||
304 | histo_convert_time_to_pixels( | |
305 | time_window, | |
306 | end_time, | |
307 | drawing->width, | |
308 | &x_end); | |
309 | x = drawing->damage_begin; | |
310 | width = x_end - x; | |
311 | drawing->damage_begin = x+width; | |
312 | histogram_show (histocontrol_flow_data,x,x_end); | |
313 | ||
314 | return 0; | |
315 | } | |
e865422c | 316 | /* TODO ybrosseau 2012-03-15: Cleanup line_src */ |
1684ba2e | 317 | void histogram_show(HistoControlFlowData *histocontrol_flow_data,guint draw_begin, |
318 | guint draw_end) | |
319 | { | |
320 | histoDrawing_t *drawing = histocontrol_flow_data->drawing; | |
321 | GtkWidget *drawingarea= histo_drawing_get_drawing_area(drawing); | |
322 | guint width = drawing->width; | |
323 | guint height= drawing->height;//drawingarea->allocation.height; | |
324 | ||
325 | /* gdk_gc_set_line_attributes(drawing->gc, | |
326 | 2, | |
327 | GDK_LINE_SOLID, | |
328 | GDK_CAP_BUTT, | |
329 | GDK_JOIN_MITER);*/ | |
330 | //clean the area! | |
331 | histo_drawing_clear(drawing,draw_begin,draw_end); | |
8d8c5ea7 | 332 | LttTime t1, t2; |
1684ba2e | 333 | TimeWindow time_window = |
334 | lttvwindow_get_time_window(histocontrol_flow_data->tab); | |
335 | ||
8d8c5ea7 | 336 | guint val, h_val; |
1684ba2e | 337 | |
e865422c | 338 | guint i/*, line_src*/; |
1684ba2e | 339 | guint end_chunk=MIN(draw_end,(histocontrol_flow_data->number_of_process)->len); |
340 | ||
341 | for (i=draw_begin/*0*/;i<end_chunk/* (histocontrol_flow_data->number_of_process)->len*/;i++){ | |
342 | val=g_array_index(histocontrol_flow_data->number_of_process,guint,i); | |
343 | h_val= height-((height*val)/histocontrol_flow_data->max_height); | |
344 | ||
345 | histo_convert_pixels_to_time(width, i, | |
346 | time_window, | |
347 | &t1); | |
348 | histo_convert_pixels_to_time(width, i+1, | |
349 | time_window, | |
350 | &t2); | |
e865422c | 351 | /* line_src=i; */ |
1684ba2e | 352 | |
353 | //check if zoom in is used and more than 1 pixel correspond to each 1nsec | |
354 | //used for drawing point (not line) on the screen. | |
355 | /* while (ltt_time_compare(t1,t2)==0) | |
356 | { | |
357 | histo_convert_pixels_to_time(width, i++, | |
358 | time_window, | |
359 | &t1); | |
360 | histo_convert_pixels_to_time(width, i+1, | |
361 | time_window, | |
362 | &t2); | |
363 | ||
364 | ||
365 | }//while (t1==t2) | |
366 | */ //replaced later for lines. | |
367 | ||
368 | if(val > drawing->histo_control_flow_data->max_height){ | |
369 | //overlimit, yellow color | |
370 | gdk_gc_set_foreground(drawing->gc,&histo_drawing_colors[COL_WHITE] );//COL_RUN_TRAP | |
371 | gdk_draw_line (drawing->pixmap, | |
372 | drawing->gc, | |
373 | i/*line_src*/,1, | |
374 | i,/*1*/height); | |
375 | } | |
376 | else{ | |
377 | gdk_gc_set_foreground(drawing->gc,&histo_drawing_colors[COL_RUN_USER_MODE] ); | |
378 | gdk_draw_line (drawing->pixmap, | |
379 | drawing->gc, | |
380 | i/*line_src*/,h_val, | |
381 | i,/*h_val*/height); | |
382 | } | |
383 | ||
384 | while ((ltt_time_compare(t1,t2)==0)&&(i<end_chunk))//-1 , i to be incremented later | |
385 | {//// | |
386 | i++; | |
387 | ||
388 | if(val > drawing->histo_control_flow_data->max_height){ | |
389 | //overlimit, yellow color | |
390 | gdk_gc_set_foreground(drawing->gc, | |
391 | &histo_drawing_colors[COL_RUN_TRAP] ); | |
392 | gdk_draw_line (drawing->pixmap, | |
393 | drawing->gc, | |
394 | i,1, | |
395 | i,height); | |
396 | } | |
397 | else{ | |
398 | gdk_gc_set_foreground(drawing->gc,&histo_drawing_colors[COL_RUN_USER_MODE] ); | |
399 | gdk_draw_line (drawing->pixmap, | |
400 | drawing->gc, | |
401 | i,h_val, | |
402 | i,height); | |
403 | } | |
404 | histo_convert_pixels_to_time(width, i, | |
405 | time_window, | |
406 | &t1); | |
407 | if(i<end_chunk-1){ | |
408 | histo_convert_pixels_to_time(width, i+1, | |
409 | time_window, | |
410 | &t2); | |
411 | } | |
412 | }//while (t1==t2)//// | |
413 | ||
414 | } | |
415 | ||
416 | histo_drawing_update_vertical_ruler(drawing); | |
417 | gtk_widget_queue_draw_area ( drawing->drawing_area, | |
418 | draw_begin, 0, | |
419 | draw_end-draw_begin, drawing->height); | |
420 | gdk_window_process_updates(drawingarea->window,TRUE); | |
421 | } | |
422 | ||
423 | int histo_event_selected_hook(void *hook_data, void *call_data) | |
424 | { | |
1684ba2e | 425 | guint *event_number = (guint*) call_data; |
426 | ||
427 | g_debug("DEBUG : event selected by main window : %u", *event_number); | |
428 | ||
429 | return 0; | |
430 | } | |
431 | ||
432 | ||
433 | ||
434 | /* histo_before_schedchange_hook | |
435 | * | |
436 | * This function basically draw lines and icons. Two types of lines are drawn : | |
437 | * one small (3 pixels?) representing the state of the process and the second | |
438 | * type is thicker (10 pixels?) representing on which CPU a process is running | |
439 | * (and this only in running state). | |
440 | * | |
441 | * Extremums of the lines : | |
442 | * x_min : time of the last event context for this process kept in memory. | |
443 | * x_max : time of the current event. | |
444 | * y : middle of the process in the process list. The process is found in the | |
445 | * list, therefore is it's position in pixels. | |
446 | * | |
447 | * The choice of lines'color is defined by the context of the last event for this | |
448 | * process. | |
449 | */ | |
450 | ||
451 | /* | |
452 | int histo_before_schedchange_hook(void *hook_data, void *call_data) | |
453 | { | |
454 | return 0; | |
455 | } | |
456 | */ | |
457 | ||
458 | gint histo_update_time_window_hook(void *hook_data, void *call_data) | |
459 | { | |
460 | HistoControlFlowData *histocontrol_flow_data = (HistoControlFlowData*) hook_data; | |
461 | histoDrawing_t *drawing = histocontrol_flow_data->drawing; | |
462 | ||
463 | const TimeWindowNotifyData *histo_time_window_nofify_data = | |
464 | ((const TimeWindowNotifyData *)call_data); | |
465 | ||
466 | TimeWindow *histo_old_time_window = | |
467 | histo_time_window_nofify_data->old_time_window; | |
468 | TimeWindow *histo_new_time_window = | |
469 | histo_time_window_nofify_data->new_time_window; | |
470 | ||
471 | // Update the ruler | |
472 | histo_drawing_update_ruler(drawing, | |
473 | histo_new_time_window); | |
474 | ||
475 | /* Two cases : zoom in/out or scrolling */ | |
476 | ||
477 | /* In order to make sure we can reuse the old drawing, the scale must | |
478 | * be the same and the new time interval being partly located in the | |
479 | * currently shown time interval. (reuse is only for scrolling) | |
480 | */ | |
481 | ||
482 | g_info("Old time window HOOK : %lu, %lu to %lu, %lu", | |
483 | histo_old_time_window->start_time.tv_sec, | |
484 | histo_old_time_window->start_time.tv_nsec, | |
485 | histo_old_time_window->time_width.tv_sec, | |
486 | histo_old_time_window->time_width.tv_nsec); | |
487 | ||
488 | g_info("New time window HOOK : %lu, %lu to %lu, %lu", | |
489 | histo_new_time_window->start_time.tv_sec, | |
490 | histo_new_time_window->start_time.tv_nsec, | |
491 | histo_new_time_window->time_width.tv_sec, | |
492 | histo_new_time_window->time_width.tv_nsec); | |
493 | ||
494 | //For Histo,redraw always except if zoom fit is pushed 2 times consequently | |
495 | if( histo_new_time_window->start_time.tv_sec == histo_old_time_window->start_time.tv_sec | |
496 | && histo_new_time_window->start_time.tv_nsec == histo_old_time_window->start_time.tv_nsec | |
497 | && histo_new_time_window->time_width.tv_sec == histo_old_time_window->time_width.tv_sec | |
498 | && histo_new_time_window->time_width.tv_nsec == histo_old_time_window->time_width.tv_nsec) | |
499 | { | |
500 | return 0; | |
501 | } | |
502 | histo_rectangle_pixmap (drawing->drawing_area->style->black_gc, | |
503 | TRUE, | |
504 | 0, 0, | |
505 | drawing->width,//+SAFETY, // do not overlap | |
506 | -1,drawing); | |
507 | ||
508 | drawing->damage_begin = 0; | |
509 | drawing->damage_end = drawing->width; | |
510 | ||
511 | gtk_widget_queue_draw(drawing->drawing_area); | |
512 | histo_request_event(histocontrol_flow_data,drawing->damage_begin, | |
513 | drawing->damage_end- drawing->damage_begin); | |
514 | ||
515 | gdk_window_process_updates(drawing->drawing_area->window,TRUE); | |
516 | ||
517 | //show number of event at current time | |
518 | ||
519 | histo_drawing_update_vertical_ruler(drawing); | |
1684ba2e | 520 | return 0; |
521 | } | |
522 | ||
523 | gint histo_traceset_notify(void *hook_data, void *call_data) | |
524 | { | |
525 | HistoControlFlowData *histocontrol_flow_data = (HistoControlFlowData*) hook_data; | |
526 | histoDrawing_t *drawing = histocontrol_flow_data->drawing; | |
527 | ||
528 | if(unlikely(drawing->gc == NULL)) { | |
529 | return FALSE; | |
530 | } | |
531 | if(drawing->dotted_gc == NULL) { | |
532 | return FALSE; | |
533 | } | |
534 | ||
535 | histo_drawing_clear(drawing,0,drawing->width); | |
536 | ||
537 | guint i; | |
538 | for(i=0;i < histocontrol_flow_data->number_of_process->len;i++) | |
539 | { | |
540 | g_array_index(histocontrol_flow_data->number_of_process, guint, i) = 0; | |
541 | } | |
542 | gtk_widget_set_size_request( | |
543 | drawing->drawing_area, | |
544 | -1, -1); | |
545 | histo_redraw_notify(histocontrol_flow_data, NULL); | |
546 | ||
547 | ///histo_request_background_data(histocontrol_flow_data); | |
548 | ||
549 | return FALSE; | |
550 | } | |
551 | ||
552 | gint histo_redraw_notify(void *hook_data, void *call_data) | |
553 | { | |
554 | HistoControlFlowData *histocontrol_flow_data = (HistoControlFlowData*) hook_data; | |
555 | histoDrawing_t *drawing = histocontrol_flow_data->drawing; | |
556 | GtkWidget *widget = drawing->drawing_area; | |
557 | ||
558 | drawing->damage_begin = 0; | |
559 | drawing->damage_end = drawing->width; | |
560 | ||
561 | // fun feature, to be separated someday... | |
562 | ||
563 | histo_drawing_clear(drawing,0,drawing->width); | |
564 | ||
565 | gtk_widget_set_size_request( | |
566 | drawing->drawing_area, | |
567 | -1, -1); | |
568 | // Clear the images | |
569 | ||
570 | histo_rectangle_pixmap (widget->style->black_gc, | |
571 | TRUE, | |
572 | 0, 0, | |
573 | drawing->alloc_width, | |
574 | -1,drawing); | |
575 | gtk_widget_queue_draw(widget); | |
576 | ||
577 | ||
578 | if(drawing->damage_begin < drawing->damage_end) | |
579 | { | |
580 | //replaced for histogram | |
581 | histo_request_event(histocontrol_flow_data,0,drawing->width); | |
582 | } | |
583 | ||
584 | ||
585 | //gtk_widget_queue_draw_area(drawing->drawing_area, | |
586 | // 0,0, | |
587 | // drawing->width, | |
588 | // drawing->height); | |
589 | return FALSE; | |
590 | ||
591 | } | |
592 | ||
593 | ||
594 | gint histo_continue_notify(void *hook_data, void *call_data) | |
595 | { | |
596 | HistoControlFlowData *histocontrol_flow_data = (HistoControlFlowData*) hook_data; | |
597 | histoDrawing_t *drawing = histocontrol_flow_data->drawing; | |
598 | ||
599 | //g_assert(widget->allocation.width == drawing->damage_end); | |
600 | ||
601 | if(drawing->damage_begin < drawing->damage_end) | |
602 | { | |
603 | histo_request_event(histocontrol_flow_data,drawing->damage_begin, | |
604 | drawing->damage_end-drawing->damage_begin); | |
605 | } | |
606 | ||
607 | return FALSE; | |
608 | } | |
609 | ||
610 | ||
611 | gint histo_update_current_time_hook(void *hook_data, void *call_data) | |
612 | { | |
613 | HistoControlFlowData *histocontrol_flow_data = (HistoControlFlowData*)hook_data; | |
614 | histoDrawing_t *drawing = histocontrol_flow_data->drawing; | |
615 | ||
616 | LttTime current_time = *((LttTime*)call_data); | |
617 | ||
618 | TimeWindow time_window = | |
619 | lttvwindow_get_time_window(histocontrol_flow_data->tab); | |
620 | ||
621 | LttTime time_begin = time_window.start_time; | |
622 | LttTime width = time_window.time_width; | |
623 | LttTime half_width; | |
624 | { | |
625 | guint64 time_ll = ltt_time_to_uint64(width); | |
626 | time_ll = time_ll >> 1; /* divide by two */ | |
627 | half_width = ltt_time_from_uint64(time_ll); | |
628 | } | |
629 | LttTime time_end = ltt_time_add(time_begin, width); | |
630 | ||
64242d13 YB |
631 | LttvTraceset *traceset = |
632 | lttvwindow_get_traceset(histocontrol_flow_data->tab); | |
8924e3e4 | 633 | TimeInterval time_span = lttv_traceset_get_time_span_real(traceset); |
64242d13 YB |
634 | |
635 | LttTime trace_start = time_span.start_time; | |
636 | LttTime trace_end = time_span.end_time; | |
1684ba2e | 637 | |
638 | g_info("Histogram: New current time HOOK : %lu, %lu", current_time.tv_sec, | |
639 | current_time.tv_nsec); | |
640 | ||
641 | ||
642 | ||
643 | /* If current time is inside time interval, just move the highlight | |
644 | * bar */ | |
645 | ||
646 | /* Else, we have to change the time interval. We have to tell it | |
647 | * to the main window. */ | |
648 | /* The time interval change will take care of placing the current | |
649 | * time at the center of the visible area, or nearest possible if we are | |
650 | * at one end of the trace. */ | |
651 | ||
652 | ||
653 | if(ltt_time_compare(current_time, time_begin) < 0) | |
654 | { | |
655 | TimeWindow histo_new_time_window; | |
656 | ||
657 | if(ltt_time_compare(current_time, | |
658 | ltt_time_add(trace_start,half_width)) < 0) | |
659 | time_begin = trace_start; | |
660 | else | |
661 | time_begin = ltt_time_sub(current_time,half_width); | |
662 | ||
663 | histo_new_time_window.start_time = time_begin; | |
664 | histo_new_time_window.time_width = width; | |
665 | histo_new_time_window.time_width_double = ltt_time_to_double(width); | |
666 | histo_new_time_window.end_time = ltt_time_add(time_begin, width); | |
667 | ||
668 | lttvwindow_report_time_window(histocontrol_flow_data->tab, histo_new_time_window); | |
669 | } | |
670 | else if(ltt_time_compare(current_time, time_end) > 0) | |
671 | { | |
672 | TimeWindow histo_new_time_window; | |
673 | ||
674 | if(ltt_time_compare(current_time, ltt_time_sub(trace_end, half_width)) > 0) | |
675 | time_begin = ltt_time_sub(trace_end,width); | |
676 | else | |
677 | time_begin = ltt_time_sub(current_time,half_width); | |
678 | ||
679 | histo_new_time_window.start_time = time_begin; | |
680 | histo_new_time_window.time_width = width; | |
681 | histo_new_time_window.time_width_double = ltt_time_to_double(width); | |
682 | histo_new_time_window.end_time = ltt_time_add(time_begin, width); | |
683 | ||
684 | lttvwindow_report_time_window(histocontrol_flow_data->tab, histo_new_time_window); | |
685 | ||
686 | } | |
687 | gtk_widget_queue_draw(drawing->drawing_area); | |
688 | ||
689 | /* Update directly when scrolling */ | |
690 | gdk_window_process_updates(drawing->drawing_area->window, | |
691 | TRUE); | |
692 | ||
693 | histo_drawing_update_vertical_ruler(drawing); | |
694 | ||
695 | return 0; | |
696 | } | |
697 | ||
698 | gboolean histo_filter_changed(void * hook_data, void * call_data) | |
699 | { | |
700 | HistoControlFlowData *histocontrol_flow_data = (HistoControlFlowData*)hook_data; | |
701 | histoDrawing_t *drawing =histocontrol_flow_data->drawing; | |
702 | ||
1684ba2e | 703 | histocontrol_flow_data->histo_main_win_filter = |
704 | (LttvFilter*)call_data; | |
705 | //get_events(event_viewer_data->vadjust_c->value, event_viewer_data); | |
706 | gtk_widget_set_size_request( | |
707 | drawing->drawing_area, | |
708 | -1, -1); | |
709 | drawing->damage_begin = 0; | |
710 | drawing->damage_end = drawing->width; | |
711 | ||
712 | /* //done in, before request! | |
713 | histo_drawing_clear(drawing,0,drawing->width); | |
714 | guint i; | |
715 | for(i=0;i < histocontrol_flow_data->number_of_process->len;i++) | |
716 | { | |
717 | g_array_index(histocontrol_flow_data->number_of_process, guint, i) = 0; | |
718 | }*/ | |
719 | ||
720 | histo_request_event(histocontrol_flow_data,0,drawing->width); | |
721 | ||
722 | return FALSE; | |
723 | } | |
724 | ||
725 | typedef struct _histo_ClosureData { | |
726 | EventsRequest *events_request; | |
64242d13 | 727 | LttvTraceset *traceset; |
1684ba2e | 728 | LttTime end_time; |
729 | guint x_end; | |
730 | } histo_ClosureData; | |
731 | ||
732 | ||
733 | ||
734 | int histo_before_chunk(void *hook_data, void *call_data) | |
735 | { | |
736 | EventsRequest *histo_events_request = (EventsRequest*)hook_data; | |
64242d13 | 737 | LttvTraceset *histo_traceset = (LttvTraceset*)call_data; |
1684ba2e | 738 | #if 0 |
739 | /* Desactivate sort */ | |
740 | gtk_tree_sortable_set_sort_column_id( | |
741 | GTK_TREE_SORTABLE(cfd->process_list->list_store), | |
742 | TRACE_COLUMN, | |
743 | GTK_SORT_ASCENDING); | |
744 | #endif //0 | |
64242d13 | 745 | histo_drawing_chunk_begin(histo_events_request, histo_traceset); |
1684ba2e | 746 | |
747 | return 0; | |
748 | } | |
749 | ||
750 | /*int histo_before_request(void *hook_data, void *call_data) | |
751 | { | |
752 | EventsRequest *events_request = (EventsRequest*)hook_data; | |
753 | LttvTracesetState *tss = (LttvTracesetState*)call_data; | |
754 | ||
755 | histo_drawing_data_request_begin(events_request, tss); | |
756 | ||
757 | return 0; | |
758 | } | |
759 | */ | |
760 | ||
761 | ||
762 | /* | |
763 | * after request is necessary in addition of after chunk in order to draw | |
764 | * lines until the end of the screen. after chunk just draws lines until | |
765 | * the last event. | |
766 | * | |
767 | * for each process | |
768 | * draw closing line | |
769 | * expose | |
770 | */ | |
771 | /*int histo_after_request(void *hook_data, void *call_data) | |
772 | { | |
773 | return 0; | |
774 | } | |
775 | */ | |
776 | /* | |
777 | * for each process | |
778 | * draw closing line | |
779 | * expose | |
780 | */ | |
781 | ||
782 | int histo_after_chunk(void *hook_data, void *call_data) | |
783 | { | |
784 | EventsRequest *events_request = (EventsRequest*)hook_data; | |
785 | HistoControlFlowData *histocontrol_flow_data = events_request->viewer_data; | |
64242d13 YB |
786 | LttvTraceset *traceset = (LttvTraceset*)call_data; |
787 | ||
1684ba2e | 788 | LttTime end_time; |
789 | ||
790 | histoDrawing_t *drawing = histocontrol_flow_data->drawing; | |
791 | ||
43ed82b5 | 792 | if(!histocontrol_flow_data->chunk_has_begun) |
793 | return 0; | |
794 | ||
d2a03e9d | 795 | histocontrol_flow_data->chunk_has_begun = TRUE; |
796 | ||
64242d13 | 797 | #ifdef BABEL_CLEANUP |
1684ba2e | 798 | if(tfc != NULL) |
799 | end_time = LTT_TIME_MIN(tfc->timestamp, events_request->end_time); | |
800 | else /* end of traceset, or position now out of request : end */ | |
64242d13 | 801 | #endif |
1684ba2e | 802 | end_time = events_request->end_time; |
803 | ||
804 | guint x, x_end, width; | |
805 | ||
806 | TimeWindow time_window = | |
807 | lttvwindow_get_time_window(histocontrol_flow_data->tab); | |
808 | ||
809 | g_debug("histo after chunk"); | |
810 | ||
811 | histo_convert_time_to_pixels( | |
812 | time_window, | |
813 | end_time, | |
814 | drawing->width, | |
815 | &x_end); | |
816 | x = drawing->damage_begin; | |
817 | width = x_end - x; | |
818 | drawing->damage_begin = x+width; | |
819 | ||
820 | histogram_show (histocontrol_flow_data,x,x_end); | |
821 | ||
822 | return 0; | |
823 | } | |
824 |