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