menu.c\
gtkdirsel.c\
gtkmultivpaned.c\
- viewer.c \
+ lttvwindow.c \
init_module.c \
support.c \
interface.c \
common.h\
gtkdirsel.h\
gtkmultivpaned.h\
- viewer.h\
+ lttvwindow.h\
lttvfilter.h\
mainwindow.h\
menu.h\
#include <lttvwindow/mainwindow.h>
#include <lttvwindow/menu.h>
#include <lttvwindow/toolbar.h>
-#include <lttvwindow/viewer.h>
+#include <lttvwindow/lttvwindow.h>
#include <lttvwindow/gtkdirsel.h>
#include <lttvwindow/lttvfilter.h>
LttvTracesetSelector * construct_traceset_selector(LttvTraceset * traceset);
-void call_pending_read_hooks(MainWindow * mw_data);
+static gboolean lttvwindow_process_pending_requests(Tab *tab);
unsigned get_max_event_number(MainWindow * mw_data);
enum {
/* internal functions */
-void insert_viewer(GtkWidget* widget, lttvwindow_viewer_constructor constructor)
+static void insert_viewer(GtkWidget* widget, lttvwindow_viewer_constructor constructor)
{
GtkMultiVPaned * multi_vpaned;
- MainWindow * mw_data;
+ MainWindow * mw_data = get_window_data_struct(widget);
GtkWidget * viewer;
LttvTracesetSelector * s;
TimeInterval * time_interval;
+ Tab *tab = mw_data->current_tab;
- mw_data = get_window_data_struct(widget);
- if(!mw_data->current_tab) return;
- multi_vpaned = mw_data->current_tab->multi_vpaned;
+ if(!tab) return;
+ multi_vpaned = tab->multi_vpaned;
- s = construct_traceset_selector(mw_data->current_tab->traceset_info->traceset);
- viewer = (GtkWidget*)constructor(mw_data, s, "Traceset_Selector");
+ s = construct_traceset_selector(tab->traceset_info->traceset);
+ viewer = (GtkWidget*)constructor(tab, s, "Traceset_Selector");
if(viewer)
{
gtk_multi_vpaned_widget_add(multi_vpaned, viewer);
}
-/* call_pending_read_hooks parses the traceset first by calling
- * process_traceset, then display all viewers of
- * the current tab
- * It will then remove all entries from the time_requests array.
- * CHECK : we give more events than requested to the viewers. They
- * Have to filter them by themselves.
+/* lttvwindow_process_pending_requests
+ *
+ * This internal function gets called by g_idle, taking care of the pending
+ * requests. It is responsible for concatenation of time intervals and position
+ * requests. It does it with the following algorithm organizing process traceset
+ * calls. Here is the detailed description of the way it works :
+ *
+ * - Events Requests Servicing Algorithm
+ *
+ * Data structures necessary :
+ *
+ * List of requests added to context : list_in
+ * List of requests not added to context : list_out
+ *
+ * Initial state :
+ *
+ * list_in : empty
+ * list_out : many events requests
+ *
+ * FIXME : insert rest of algorithm here
+ *
*/
-gint compare_time_request(TimeRequest *a, TimeRequest *b)
-{
- return ltt_time_compare(a->time_window.start_time, b->time_window.start_time);
-}
-void call_pending_read_hooks(MainWindow * mw_data)
+gboolean lttvwindow_process_pending_requests(Tab *tab)
{
unsigned max_nb_events;
GdkWindow * win;
GdkCursor * new;
GtkWidget* widget;
- int i;
LttvTracesetContext *tsc;
+ LttvTracefileContext *tfc;
+ GSList *events_requests = tab->events_requests;
+ GSList *list_out = events_requests;
+ GSList *list_in = NULL;
+ LttTime end_time;
+ guint end_nb_events;
+ LttvTracesetContextPosition *end_position;
+
/* Current tab check : if no current tab is present, no hooks to call. */
- /* It makes the expose works.. */
- if(mw_data->current_tab == NULL)
- return;
+ /* (Xang Xiu) It makes the expose works.. MD:? */
+ if(tab == NULL)
+ return FALSE;
- if(mw_data->current_tab->time_requests->len == 0)
- return;
+ /* There is no events requests pending : we should never have been called! */
+ g_assert(g_slist_length(events_requests) != 0);
- LttvHooks *tmp_hooks = lttv_hooks_new();
-
- tsc =
- LTTV_TRACESET_CONTEXT(mw_data->current_tab->traceset_info->
- traceset_context);
+ tsc = LTTV_TRACESET_CONTEXT(tab->traceset_info->traceset_context);
//set the cursor to be X shape, indicating that the computer is busy in doing its job
new = gdk_cursor_new(GDK_X_CURSOR);
- widget = lookup_widget(mw_data->mwindow, "MToolbar1");
+ widget = lookup_widget(tab->mw_data->mwindow, "MToolbar1");
win = gtk_widget_get_parent_window(widget);
gdk_window_set_cursor(win, new);
gdk_cursor_unref(new);
gdk_window_stick(win);
gdk_window_unstick(win);
+ g_debug("SIZE events req len : %d", g_slist_length(events_request));
+
+ /* Events processing algorithm implementation */
+ /* A. Servicing loop */
+ while( (g_slist_length(list_in) != 0 || g_slist_length(list_out) != 0)
+ && !gtk_events_pending() ) {
+
+ /* 1. If list_in is empty (need a seek) */
+ if( g_slist_length(list_in) == 0 ) {
- g_array_sort(mw_data->current_tab->time_requests,
- (GCompareFunc)compare_time_request);
+ /* list in is empty, need a seek */
+ {
+ /* 1.1 Add requests to list_in */
+ GArray *ltime = g_array_new(FALSE, FALSE, sizeof(guint));
+ GArray *lpos = g_array_new(FALSE, FALSE, sizeof(guint));
+ guint i;
+
+ /* 1.1.1 Find all time requests with the lowest start time in list_out
+ * (ltime)
+ */
+ if(list_out->len > 0)
+ g_array_append_val(ltime, 0);
+ for(i=1;i<list_out->len;i++) {
+ /* Find all time requests with the lowest start time in list_out */
+ guint index_ltime = g_array_index(ltime, guint, 0);
+ EventsRequest *event_request_ltime = &g_array_index(list_out,
+ EventsRequest,
+ index_ltime);
+ EventsRequest *event_request_list_out = &g_array_index(list_out,
+ EventsRequest,
+ i);
+ int comp;
+ comp = ltt_time_compare(event_request_ltime->start_time,
+ event_request_list_out->start_time);
+ if(comp == 0)
+ g_array_append_val(ltime, i);
+ else if(comp > 0) {
+ /* Remove all elements from ltime, and add current */
+ g_array_remove_range(ltime, 0, ltime->len);
+ g_array_append_val(ltime, i);
+
+ }
+ }
+
+ /* 1.1.2 Find all position requests with the lowest position in list_out
+ * (lpos)
+ */
+ if(list_out->len > 0)
+ g_array_append(lpos, 0);
+ for(i=1;i<list_out->len;i++) {
+ /* Find all position requests with the lowest position in list_out */
+ guint index_lpos = g_array_index(lpos, guint, 0);
+ EventsRequest *event_request_lpos = &g_array_index(lpos,
+ EventsRequest,
+ index_lpos);
+ EventsRequest *event_request_list_out = &g_array_index(list_out,
+ EventsRequest,
+ i);
+ int comp;
+ comp = lttv_traceset_context_pos_pos_compare
+ (event_request_pos->start_position,
+ event_request_list_out->start_position);
+ if(comp == 0)
+ g_array_append_val(lpos, i);
+ else if(comp > 0) {
+ /* Remove all elements from lpos, and add current */
+ g_array_remove_range(lpos, 0, lpos->len);
+ g_array_append_val(lpos, i);
+ }
+ }
+
+ /* 1.1.3 If lpos.start time < ltime */
+ {
+ guint i;
+ EventsRequest *event_request_lpos = &g_array_index(lpos, 0);
+ EventsRequest *event_request_ltime = &g_array_index(ltime,0);
+ LttTime lpos_start_time =
+ lttv_traceset_context_position_get_time(event_request_lpos);
+
+ if(ltt_time_compare(lpos_start_time,
+ event_request_ltime->start_time)<0) {
+ /* Add lpos to list_in, remove them from list_out */
+
+ for(i=0;i<lpos->len;i++) {
+ /* Add to list_in */
+ guint index_lpos = g_array_index(lpos, guint, i);
+ EventsRequest *event_request_lpos =
+ &g_array_index(lpos,index_lpos);
+
+ g_array_append_val(list_in, *event_request_lpos);
+
+ }
+
+ for(i=0;i<lpos->len;i++) {
+ /* Remove from list_out */
+ guint index_lpos = g_array_index(lpos, guint, i);
+
+ g_array_remove_index_fast(list_out, index_lpos);
+ }
+
+ } else {
+ /* 1.1.4 (lpos.start time >= ltime) */
+ /* Add ltime to list_in, remove them from list_out */
+
+ for(i=0;i<ltime->len;i++) {
+ /* Add to list_in */
+ guint index_ltime = g_array_index(ltime, guint, i);
+ EventsRequest *event_request_ltime =
+ &g_array_index(ltime,index_ltime);
+
+ g_array_append_val(list_in, *event_request_ltime);
+ }
+
+ for(i=0;i<ltime->len;i++) {
+ /* Remove from list_out */
+ guint index_ltime = g_array_index(ltime, guint, i);
+
+ g_array_remove_index_fast(list_out, index_ltime);
+ }
+ }
+ }
+ g_array_free(lpos, TRUE);
+ g_array_free(ltime, TRUE);
+ }
+ /* 1.2 Seek */
+ {
+ EventsRequest *events_request = &g_array_index(list_in,
+ EventsRequest,
+ 0);
+
+ /* 1.2.1 If first request in list_in is a time request */
+ if(events_request->start_position == NULL) {
+ /* 1.2.1.1 Seek to that time */
+ lttv_process_traceset_seek_time(tsc, events_request->start_time);
+ } else {
+ /* Else, the first request in list_in is a position request */
+ /* 1.2.2.1 Seek to that position */
+ lttv_process_traceset_seek_position(tsc, events_request->start_position);
+ }
+ }
- //update time window of each viewer, let viewer insert hooks needed by process_traceset
- //lttvwindow_report_time_window(mw_data, time_window);
-
- //max_nb_events = get_max_event_number(mw_data);
+ /* 1.3 Call begin for all list_in members */
+ {
+ guint i;
+
+ for(i=0;i<list_in->len;i++) {
+ EventsRequest *events_request = &g_array_index(list_in,
+ EventsRequest,
+ i);
+ /* (1.3.1 begin hooks called) */
+ /* (1.3.2 middle hooks added) */
+ lttv_process_traceset_begin(tsc, events_request->before_traceset,
+ events_request->before_trace,
+ events_request->before_tracefile,
+ events_request->event,
+ events_request->event_by_id);
+ }
+ }
+ } else {
+ /* 2. Else, list_in is not empty, we continue a read */
+ guint i;
+ tfc = lttv_traceset_context_get_current_tfc(tsc);
+
+ /* 2.1 For each req of list_out */
+ for(i=0;i<list_out->len;i++) {
+ EventsRequest *events_request = &g_array_index(list_out,
+ EventsRequest,
+ i);
+ if(ltt_time_compare(events_request->start_time,
+ tfc->timestamp) == 0) {
+ /* if req.start time == current context time */
+ /* Call Begin */
+ lttv_process_traceset_begin(tsc, events_request->before_traceset,
+ events_request->before_trace,
+ events_request->before_tracefile,
+ events_request->event,
+ events_request->event_by_id);
+
+
+ /* Add to list_in */
+ g_array_append_val(list_in, *events_request);
+ } else if(events_request->start_position != NULL &&
+ lttv_traceset_context_ctx_pos_compare(tsc,
+ events_request->start_position) == 0) {
+ /* if req.start position == current position */
+ /* Call Begin */
+ lttv_process_traceset_begin(tsc, events_request->before_traceset,
+ events_request->before_trace,
+ events_request->before_tracefile,
+ events_request->event,
+ events_request->event_by_id);
+
- //call hooks to show each viewer and let them remove hooks
- //show_viewer(mw_data);
+ /* Add to list_in */
+ g_array_append_val(list_in, *events_request);
- // FIXME
- // call process trace for each time interval
- // Will have to be combined!
- g_critical("SIZE time req len : %d", mw_data->current_tab->time_requests->len);
-
- //g_assert(mw_data->current_tab->time_requests->len <= 1); //FIXME
- /* Go through each time request. As they are already sorted by start_time,
- * we check with the current event time if processing is needed. */
- for(i=0; i < mw_data->current_tab->time_requests->len; i++)
- {
- g_critical("RUN i %d", i);
- TimeRequest *time_request =
- &g_array_index(mw_data->current_tab->time_requests, TimeRequest, i);
- LttTime end_time = ltt_time_add( time_request->time_window.start_time,
- time_request->time_window.time_width);
+ }
+
+ }
- if(i == 0 || !(ltt_time_compare(time_request->time_window.start_time, ltt_event_time(tsc->e))<0) )
+
+ for(i=0;i<list_out->len;i++) {
+ EventsRequest *events_request = &g_array_index(list_out,
+ EventsRequest,
+ i);
+ if(ltt_time_compare(events_request->start_time,
+ tfc->timestamp) == 0) {
+ /* if req.start time == current context time */
+ /* Remove from list_out */
+ g_array_remove_index_fast(list_out, i);
+ } else if(events_request->start_position != NULL &&
+ lttv_traceset_context_ctx_pos_compare(tsc,
+ events_request->start_position) == 0) {
+ /* if req.start position == current position */
+ /* Remove from list_out */
+ g_array_remove_index_fast(list_out, i);
+
+ }
+ }
+ }
+
+
+
+ /* 3. Find end criterions */
{
- /* do it if first request or start_time >= last event's time */
- lttv_process_traceset_seek_time(tsc, time_request->time_window.start_time);
- lttv_process_traceset(tsc, end_time, time_request->num_events);
+ /* 3.1 End time */
+ guint i;
+
+ /* 3.1.1 Find lowest end time in list_in */
+ end_time = g_array_index(list_in, EventsRequest,0).end_time;
+
+ for(i=1;i<list_in->len;i++) {
+ EventsRequest *events_request = &g_array_index(list_in,
+ EventsRequest,
+ i);
+ if(ltt_time_compare(events_request->end_time,
+ end_time) < 0)
+ end_time = events_request->end_time;
+ }
+
+ /* 3.1.2 Find lowest start time in list_out */
+ for(i=0;i<list_out->len;i++) {
+ EventsRequest *events_request = &g_array_index(list_out,
+ EventsRequest,
+ i);
+ if(ltt_time_compare(events_request->start_time,
+ end_time) < 0)
+ end_time = events_request->start_time;
+ }
}
- else
+
{
- if(ltt_time_compare(time_request->time_window.start_time, ltt_event_time(tsc->e))<0
- && !(ltt_time_compare(end_time, ltt_event_time(tsc->e))<0))
- {
- /* Continue reading from current event */
- lttv_process_traceset(tsc, end_time, time_request->num_events);
+ /* 3.2 Number of events */
+
+ /* 3.2.1 Find lowest number of events in list_in */
+ guint i;
+ end_nb_events = g_array_index(list_in, EventsRequest, 0).num_events;
+
+ for(i=1;i<list_in->len;i++) {
+ EventsRequest *events_request = &g_array_index(list_in,
+ EventsRequest,
+ i);
+ if(events_request->num_events < end_nb_events)
+ end_nb_events = events_request->num_events;
}
- else
+ }
+
+ {
+ /* 3.3 End position */
+
+ /* 3.3.1 Find lowest end position in list_in */
+ guint i;
+
+ end_position = g_array_index(list_in, EventsRequest, 0).end_position;
+
+ for(i=1;i<list_in->len;i++) {
+ EventsRequest *events_request = &g_array_index(list_in,
+ EventsRequest,
+ i);
+
+ if(lttv_traceset_context_pos_pos_compare(events_request->end_position,
+ end_position) <0)
+ end_position = events_request->end_position;
+ }
+ }
+
+ {
+ /* 3.3.2 Find lowest start position in list_out */
+ guint i;
+
+ for(i=0;i<list_out->len;i++) {
+ EventsRequest *events_request = &g_array_index(list_out,
+ EventsRequest,
+ i);
+
+ if(lttv_traceset_context_pos_pos_compare(events_request->end_position,
+ end_position) <0)
+ end_position = events_request->end_position;
+ }
+ }
+
+
+ }
+
+ /* B. When interrupted */
+
+ /* 1. for each request in list_in */
+ {
+ GSList *iter = list_in;
+
+ while(iter != NULL) {
+
+ gboolean remove = FALSE;
+ gboolean free_data = FALSE;
+ EventsRequest events_request = (EventsRequest *)iter->data;
+
+ /* 1.1. Use current postition as start position */
+ g_free(events_request->start_position);
+ lttv_traceset_context_position_save(tsc, events_request->start_position);
+
+ /* 1.2. Remove start time */
+ events_request->start_time = { G_MAXUINT, G_MAXUINT };
+
+ /* 1.3. Call after_traceset */
+ /* 1.4. Remove event hooks */
+ lttv_process_traceset_end(tsc, events_request->after_traceset,
+ events_request->after_trace,
+ events_request->after_tracefile,
+ events_request->event,
+ events_request->event_by_id);
+
+ /* 1.5. Put it back in list_out */
+ remove = TRUE;
+ free_data = FALSE;
+ list_out = g_slist_append(list_out, events_request);
+
+
+ /* Go to next */
+ if(remove)
{
- if(ltt_time_compare(time_request->time_window.start_time, end_time) > 0)
- {
- /* This is a request for a minimum number of events, give
- * more events than necessary */
- lttv_process_traceset(tsc, end_time, time_request->num_events);
- }
+ GSList *remove_iter = iter;
+
+ iter = g_slist_next(iter);
+ if(free_data) g_free(remove_iter->data);
+ list_in = g_slist_remove_link(list_in, remove_iter);
+ } else { // not remove
+ iter = g_slist_next(iter);
}
}
- /* Call the end of process_traceset hook */
- lttv_hooks_add(tmp_hooks,
- time_request->after_hook,
- time_request->after_hook_data);
- lttv_hooks_call(tmp_hooks, time_request);
- lttv_hooks_remove(tmp_hooks, time_request->after_hook);
+
+ }
+
+ /* 2. Save current state into saved_state. */
+ {
+ /* 2.1 Free old saved state. */
+ //FIXME : free will need to be able to remove state for a traceset
+ //with changed traces!
+ //FIXME lttv_state_state_saved_free( , tab->interrupted_state);
+
+ /* 2.2 save current state. */
+ //FIXME
+ //lttv_state_save( ,tab->interrupted_state);
+
}
-
- /* Free the time requests */
- g_array_free(mw_data->current_tab->time_requests, TRUE);
- mw_data->current_tab->time_requests =
- g_array_new(FALSE, FALSE, sizeof(TimeRequest));
-
- mw_data->current_tab->time_request_pending = FALSE;
-
- lttv_hooks_destroy(tmp_hooks);
//set the cursor back to normal
gdk_window_set_cursor(win, NULL);
+
+
+
+ if( g_slist_length(list_in) == 0 && g_slist_length(list_out) == 0 ) {
+ /* Put tab's request pending flag back to normal */
+ tab->time_request_pending = FALSE;
+ return FALSE; /* Remove the idle function */
+ }
+
+ return TRUE; /* Leave the idle function */
+
}
+#ifdef TESTCODE
+ GSList *iter = list_in;
+
+ /* 1. for each request in list_in */
+ while(iter != NULL) {
+
+ gboolean remove = FALSE;
+ gboolean free_data = FALSE;
+
+
+
+ /* Go to next */
+ if(remove)
+ {
+ GSList *remove_iter = iter;
+
+ iter = g_slist_next(iter);
+ if(free_data) g_free(remove_iter->data);
+ list_in = g_slist_remove_link(list_in, remove_iter);
+ } else { // not remove
+ iter = g_slist_next(iter);
+ }
+ }
+#endif //TESTCODE
+
+
/* add_trace_into_traceset_selector, each instance of a viewer has an associated
* selector (filter), when a trace is added into traceset, the selector should
lttv_traceset_number(mw_data->current_tab->traceset_info->traceset) == 1
|| ltt_time_compare(mw_data->current_tab->current_time,
LTTV_TRACESET_CONTEXT(mw_data->current_tab->traceset_info->
- traceset_context)->Time_Span->startTime)<0)
+ traceset_context)->time_span.start_time)<0)
{
/* Set initial time if this is the first trace in the traceset */
mw_data->current_tab->current_time =
LTTV_TRACESET_CONTEXT(mw_data->current_tab->traceset_info->
- traceset_context)->Time_Span->startTime;
+ traceset_context)->time_span.start_time;
mw_data->current_tab->time_window.start_time =
mw_data->current_tab->current_time;
mw_data->current_tab->time_window.time_width.tv_sec =
TimeWindow new_time_window;
LttTime current_time, time_delta, time_s, time_e, time_tmp;
MainWindow * mw_data = get_window_data_struct(widget);
+ Tab *tab = mw_data->current_tab;
+ LttvTracesetContext *tsc =
+ LTTV_TRACESET_CONTEXT(tab->traceset_info->traceset_context);
if(size == 1) return;
- time_span = LTTV_TRACESET_CONTEXT(mw_data->current_tab->
- traceset_info->traceset_context)->Time_Span;
- new_time_window = mw_data->current_tab->time_window;
- current_time = mw_data->current_tab->current_time;
+ time_span = &tsc->time_span;
+ new_time_window = tab->time_window;
+ current_time = tab->current_time;
- time_delta = ltt_time_sub(time_span->endTime,time_span->startTime);
+ time_delta = ltt_time_sub(time_span->end_time,time_span->start_time);
if(size == 0){
- new_time_window.start_time = time_span->startTime;
+ new_time_window.start_time = time_span->start_time;
new_time_window.time_width = time_delta;
}else{
new_time_window.time_width = ltt_time_div(new_time_window.time_width, size);
if(ltt_time_compare(new_time_window.time_width,time_delta) > 0)
{ /* Case where zoom out is bigger than trace length */
- new_time_window.start_time = time_span->startTime;
+ new_time_window.start_time = time_span->start_time;
new_time_window.time_width = time_delta;
}
else
new_time_window.start_time =
ltt_time_sub(current_time, ltt_time_div(new_time_window.time_width, 2.0));
/* If on borders, don't fall off */
- if(ltt_time_compare(new_time_window.start_time, time_span->startTime) <0)
+ if(ltt_time_compare(new_time_window.start_time, time_span->start_time) <0)
{
- new_time_window.start_time = time_span->startTime;
+ new_time_window.start_time = time_span->start_time;
}
else
{
if(ltt_time_compare(
ltt_time_add(new_time_window.start_time, new_time_window.time_width),
- time_span->endTime) > 0)
+ time_span->end_time) > 0)
{
new_time_window.start_time =
- ltt_time_sub(time_span->endTime, new_time_window.time_width);
+ ltt_time_sub(time_span->end_time, new_time_window.time_width);
}
}
//call_pending_read_hooks(mw_data);
//lttvwindow_report_current_time(mw_data,&(mw_data->current_tab->current_time));
- set_time_window(mw_data, &new_time_window);
+ set_time_window(tab, &new_time_window);
// in expose now call_pending_read_hooks(mw_data);
- gtk_multi_vpaned_set_adjust(mw_data->current_tab->multi_vpaned, &new_time_window, FALSE);
+ gtk_multi_vpaned_set_adjust(tab->multi_vpaned, &new_time_window, FALSE);
}
void zoom_in(GtkWidget * widget, gpointer user_data)
"viewers/menu", LTTV_POINTER, &value));
lttv_menus_destroy((LttvMenus*)*(value.v_pointer));
- g_assert(lttv_iattribute_find_by_path(attributes_global,
+ g_assert(lttv_iattribute_find_by_path(attributes,
"viewers/toolbar", LTTV_POINTER, &value));
lttv_toolbars_destroy((LttvToolbars*)*(value.v_pointer));
LttvToolbarClosure *toolbar_item;
LttvAttributeValue value;
LttvIAttribute *global_attributes = LTTV_IATTRIBUTE(lttv_global_attributes());
- LttvIAttribute *attributes = LTTV_IATTRIBUTES(mw->attributes);
+ LttvIAttribute *attributes = mw->attributes;
GtkWidget * tool_menu_title_menu, *new_widget, *pixmap;
g_assert(lttv_iattribute_find_by_path(global_attributes,
"viewers/menu", LTTV_POINTER, &value));
if(*(value.v_pointer) == NULL)
- (LttvMenus*)*(value.v_pointer) = lttv_menus_new();
+ *(value.v_pointer) = lttv_menus_new();
global_menu = (LttvMenus*)*(value.v_pointer);
g_assert(lttv_iattribute_find_by_path(attributes,
"viewers/menu", LTTV_POINTER, &value));
if(*(value.v_pointer) == NULL)
- (LttvMenus*)*(value.v_pointer) = lttv_menus_new();
+ *(value.v_pointer) = lttv_menus_new();
instance_menu = (LttvMenus*)*(value.v_pointer);
g_assert(lttv_iattribute_find_by_path(global_attributes,
"viewers/toolbar", LTTV_POINTER, &value));
if(*(value.v_pointer) == NULL)
- (LttvToolbars*)*(value.v_pointer) = lttv_toolbars_new();
+ *(value.v_pointer) = lttv_toolbars_new();
global_toolbar = (LttvToolbars*)*(value.v_pointer);
g_assert(lttv_iattribute_find_by_path(attributes,
"viewers/toolbar", LTTV_POINTER, &value));
if(*(value.v_pointer) == NULL)
- (LttvToolbars*)*(value.v_pointer) = lttv_toolbars_new();
+ *(value.v_pointer) = lttv_toolbars_new();
instance_toolbar = (LttvToolbars*)*(value.v_pointer);
/* Add missing menu entries to window instance */
constructor = menu_item->con;
tool_menu_title_menu = lookup_widget(mw->mwindow,"ToolMenuTitle_menu");
new_widget =
- gtk_menu_item_new_with_mnemonic (menu_item->menuText);
+ gtk_menu_item_new_with_mnemonic (menu_item->menu_text);
gtk_container_add (GTK_CONTAINER (tool_menu_title_menu),
new_widget);
g_signal_connect ((gpointer) new_widget, "activate",
g_assert(lttv_iattribute_find_by_path(attributes,
"viewers/menu", LTTV_POINTER, &value));
- (LttvMenus*)*(value.v_pointer) = lttv_menus_new();
+ *(value.v_pointer) = lttv_menus_new();
- g_assert(lttv_iattribute_find_by_path(attributes_global,
+ g_assert(lttv_iattribute_find_by_path(attributes,
"viewers/toolbar", LTTV_POINTER, &value));
- (LttvToolbars*)*(value.v_pointer) = lttv_toolbars_new();
+ *(value.v_pointer) = lttv_toolbars_new();
add_all_menu_toolbar_constructors(new_m_window, NULL);
LttvTrace * trace;
if(tab_instance->attributes)
- g_object_unref(tab_instance->attributes);
+ g_object_unref(tab_instance->attributes);
+
+ if(tab_instance->interrupted_state)
+ g_object_unref(tab_instance->interrupted_state);
+
if(tab_instance->mw->tab == tab_instance){
tab_instance->mw->tab = tab_instance->next;
}
}
lttv_traceset_destroy(tab_instance->traceset_info->traceset);
- g_array_free(tab_instance->time_requests, TRUE);
+ /* Remove the idle events requests processing function of the tab */
+ g_idle_remove_by_data(tab_instance);
+
+ g_slist_free(tab_instance->events_requests);
g_free(tab_instance->traceset_info);
g_free(tab_instance);
}
// to be able to modify a traceset on the fly.
// get_traceset_time_span(mw_data,&tmp_tab->traceStartTime, &tmp_tab->traceEndTime);
tmp_tab->time_window.start_time =
- LTTV_TRACESET_CONTEXT(tmp_tab->traceset_info->traceset_context)->Time_Span->startTime;
+ LTTV_TRACESET_CONTEXT(tmp_tab->traceset_info->traceset_context)->time_span.start_time;
if(DEFAULT_TIME_WIDTH_S <
- LTTV_TRACESET_CONTEXT(tmp_tab->traceset_info->traceset_context)->Time_Span->endTime.tv_sec)
+ LTTV_TRACESET_CONTEXT(tmp_tab->traceset_info->traceset_context)->time_span.end_time.tv_sec)
tmp_time.tv_sec = DEFAULT_TIME_WIDTH_S;
else
tmp_time.tv_sec =
- LTTV_TRACESET_CONTEXT(tmp_tab->traceset_info->traceset_context)->Time_Span->endTime.tv_sec;
+ LTTV_TRACESET_CONTEXT(tmp_tab->traceset_info->traceset_context)->time_span.end_time.tv_sec;
tmp_time.tv_nsec = 0;
tmp_tab->time_window.time_width = tmp_time ;
tmp_tab->current_time.tv_sec =
- LTTV_TRACESET_CONTEXT(tmp_tab->traceset_info->traceset_context)->Time_Span->startTime.tv_sec;
+ LTTV_TRACESET_CONTEXT(tmp_tab->traceset_info->traceset_context)->time_span.start_time.tv_sec;
tmp_tab->current_time.tv_nsec =
- LTTV_TRACESET_CONTEXT(tmp_tab->traceset_info->traceset_context)->Time_Span->startTime.tv_nsec;
+ LTTV_TRACESET_CONTEXT(tmp_tab->traceset_info->traceset_context)->time_span.start_time.tv_nsec;
}
/* Become the current tab */
mw_data->current_tab = tmp_tab;
tmp_tab->attributes = LTTV_IATTRIBUTE(g_object_new(LTTV_ATTRIBUTE_TYPE, NULL));
+ tmp_tab->interrupted_state = g_object_new(LTTV_ATTRIBUTE_TYPE, NULL);
tmp_tab->multi_vpaned = (GtkMultiVPaned*)gtk_multi_vpaned_new();
- tmp_tab->multi_vpaned->mw = mw_data;
+ tmp_tab->multi_vpaned->tab = mw_data->current_tab;
gtk_widget_show((GtkWidget*)tmp_tab->multi_vpaned);
tmp_tab->next = NULL;
tmp_tab->mw = mw_data;
tmp_tab->label = gtk_label_new (label);
gtk_widget_show (tmp_tab->label);
- tmp_tab->time_requests = g_array_new(FALSE, FALSE, sizeof(TimeRequest));
- tmp_tab->time_request_pending = FALSE;
+ /* Start with empty events requests list */
+ tmp_tab->events_requests = NULL;
+ tmp_tab->events_request_pending = FALSE;
g_object_set_data_full(
G_OBJECT(tmp_tab->multi_vpaned),
}
-
-gboolean execute_time_requests(MainWindow * mw)
+/*
+ * execute_events_requests
+ *
+ * Idle function that executes the pending requests for a tab.
+ *
+ * @return return value : TRUE : keep the idle function, FALSE : remove it.
+ */
+gboolean execute_events_requests(Tab *tab)
{
- call_pending_read_hooks(mw);
-
- return FALSE; // automatically removed from the list of event sources
+ return ( lttvwindow_process_pending_requests(tab) );
}
#include <lttvwindow/gtkmultivpaned.h>
//#include "gtkintl.h"
#include <lttvwindow/mainwindow.h>
-#include <lttvwindow/viewer.h>
+#include <lttvwindow/lttvwindow.h>
static void gtk_multi_vpaned_class_init (GtkMultiVPanedClass *klass);
static void gtk_multi_vpaned_init (GtkMultiVPaned *multi_vpaned);
void gtk_multi_vpaned_set_adjust(GtkMultiVPaned * multi_vpaned, const TimeWindow *time_window, gboolean first_time)
{
- //TimeWindow time_window = multi_vpaned->mw->current_tab->time_window;
TimeInterval *time_span;
double len, start;
+ LttvTracesetContext *tsc =
+ LTTV_TRACESET_CONTEXT(multi_vpaned->tab->traceset_info->traceset_context);
if(first_time){
- time_span = <TV_TRACESET_CONTEXT(multi_vpaned->mw->current_tab->
- traceset_info->traceset_context)->time_span ;
+ time_span = &tsc->time_span ;
multi_vpaned->hadjust->lower = ltt_time_to_double(time_span->start_time) *
NANOSECONDS_PER_SECOND;
gtk_widget_show(multi_vpaned->hscrollbar);
multi_vpaned->hadjust = gtk_range_get_adjustment(GTK_RANGE(multi_vpaned->hscrollbar));
- gtk_multi_vpaned_set_adjust(multi_vpaned, &multi_vpaned->mw->current_tab->time_window, TRUE);
+ gtk_multi_vpaned_set_adjust(multi_vpaned, &multi_vpaned->tab->time_window, TRUE);
gtk_range_set_update_policy (GTK_RANGE(multi_vpaned->hscrollbar),
GTK_UPDATE_CONTINUOUS);
GtkMultiVPaned * multi_vpaned = (GtkMultiVPaned*)multi_vpaned_arg;
gdouble value = gtk_adjustment_get_value(adjust);
gdouble upper, lower, ratio;
+ LttvTracesetContext * tsc =
+ LTTV_TRACESET_CONTEXT(multi_vpaned->tab->traceset_info->traceset_context);
- time_window = multi_vpaned->mw->current_tab->time_window;
+ time_window = multi_vpaned->tab->time_window;
- time_span = <TV_TRACESET_CONTEXT(multi_vpaned->mw->current_tab->traceset_info->
- traceset_context)->time_span ;
+ time_span = &tsc->time_span ;
lower = multi_vpaned->hadjust->lower;
upper = multi_vpaned->hadjust->upper;
ratio = (value - lower) / (upper - lower);
if(ltt_time_compare(time,time_window.time_width) < 0){
time_window.time_width = time;
}
- set_time_window(multi_vpaned->mw, &time_window);
- // done in expose now call_pending_read_hooks(multi_vpaned->mw);
+ set_time_window(multi_vpaned->tab, &time_window);
}
--- /dev/null
+/* This file is part of the Linux Trace Toolkit viewer
+ * Copyright (C) 2003-2004 XangXiu Yang
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License Version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+/*! \file lttvwindow.c
+ * \brief API used by the graphical viewers to interact with their tab.
+ *
+ * Main window (gui module) is the place to contain and display viewers.
+ * Viewers (lttv plugins) interact with tab and main window through this API
+ * and events sent by gtk.
+ * This header file should be included in each graphic module.
+ * This library is used by graphical modules to interact with their tab and
+ * main window.
+ *
+ */
+
+#include <ltt/ltt.h>
+#include <lttv/lttv.h>
+#include <lttv/state.h>
+#include <lttv/stats.h>
+#include <lttv/tracecontext.h>
+#include <lttvwindow/common.h>
+#include <lttvwindow/mainwindow.h>
+#include <lttvwindow/lttvwindow.h>
+#include <lttvwindow/toolbar.h>
+#include <lttvwindow/menu.h>
+#include <lttvwindow/callbacks.h> // for execute_events_requests
+#include <lttvwindow/support.h>
+
+
+/**
+ * Internal function parts
+ */
+
+extern GSList * g_main_window_list;
+
+/**
+ * Function to set/update traceset for the viewers
+ * @param tab viewer's tab
+ * @param traceset traceset of the main window.
+ * return value :
+ * -1 : error
+ * 0 : traceset updated
+ * 1 : no traceset hooks to update; not an error.
+ */
+
+int SetTraceset(Tab * tab, gpointer traceset)
+{
+ LttvHooks * tmp;
+ LttvAttributeValue value;
+
+ if( lttv_iattribute_find_by_path(tab->attributes,
+ "hooks/updatetraceset", LTTV_POINTER, &value) != 0)
+ return -1;
+
+ tmp = (LttvHooks*)*(value.v_pointer);
+ if(tmp == NULL) return 1;
+
+
+ lttv_hooks_call(tmp,traceset);
+
+ return 0;
+}
+
+
+/**
+ * Function to set/update filter for the viewers
+ * @param tab viewer's tab
+ * @param filter filter of the main window.
+ * return value :
+ * -1 : error
+ * 0 : filters updated
+ * 1 : no filter hooks to update; not an error.
+ */
+
+int SetFilter(Tab * tab, gpointer filter)
+{
+ LttvHooks * tmp;
+ LttvAttributeValue value;
+
+ if(lttv_iattribute_find_by_path(tab->attributes,
+ "hooks/updatefilter", LTTV_POINTER, &value) != 0)
+ return -1;
+
+ tmp = (LttvHooks*)*(value.v_pointer);
+
+ if(tmp == NULL) return 1;
+ lttv_hooks_call(tmp,filter);
+
+ return 0;
+}
+
+/**
+ * Function to redraw each viewer belonging to the current tab
+ * @param tab viewer's tab
+ */
+
+void update_traceset(Tab *tab)
+{
+ LttvAttributeValue value;
+ LttvHooks * tmp;
+ g_assert(lttv_iattribute_find_by_path(tab->attributes,
+ "hooks/updatetraceset", LTTV_POINTER, &value));
+ tmp = (LttvHooks*)*(value.v_pointer);
+ if(tmp == NULL) return;
+ lttv_hooks_call(tmp, NULL);
+}
+
+void set_time_window_adjustment(Tab *tab, const TimeWindow* new_time_window)
+{
+ gtk_multi_vpaned_set_adjust(tab->multi_vpaned, new_time_window, FALSE);
+}
+
+
+void set_time_window(Tab *tab, const TimeWindow *time_window)
+{
+ LttvAttributeValue value;
+ LttvHooks * tmp;
+
+ TimeWindowNotifyData time_window_notify_data;
+ TimeWindow old_time_window = tab->time_window;
+ time_window_notify_data.old_time_window = &old_time_window;
+ tab->time_window = *time_window;
+ time_window_notify_data.new_time_window =
+ &(tab->time_window);
+
+ g_assert(lttv_iattribute_find_by_path(tab->attributes,
+ "hooks/updatetimewindow", LTTV_POINTER, &value));
+ tmp = (LttvHooks*)*(value.v_pointer);
+ if(tmp == NULL) return;
+ lttv_hooks_call(tmp, &time_window_notify_data);
+
+
+}
+
+void add_toolbar_constructor(MainWindow *mw, LttvToolbarClosure *toolbar_c)
+{
+ LttvIAttribute *attributes = mw->attributes;
+ LttvAttributeValue value;
+ LttvToolbars * instance_toolbar;
+ lttvwindow_viewer_constructor constructor;
+ GtkWidget * tool_menu_title_menu, *new_widget, *pixmap;
+ GdkPixbuf *pixbuf;
+
+ g_assert(lttv_iattribute_find_by_path(attributes,
+ "viewers/toolbar", LTTV_POINTER, &value));
+ if(*(value.v_pointer) == NULL)
+ *(value.v_pointer) = lttv_toolbars_new();
+ instance_toolbar = (LttvToolbars*)*(value.v_pointer);
+
+ constructor = toolbar_c->con;
+ tool_menu_title_menu = lookup_widget(mw->mwindow,"MToolbar1");
+ pixbuf = gdk_pixbuf_new_from_xpm_data((const char**)toolbar_c->pixmap);
+ pixmap = gtk_image_new_from_pixbuf(pixbuf);
+ new_widget =
+ gtk_toolbar_append_element (GTK_TOOLBAR (tool_menu_title_menu),
+ GTK_TOOLBAR_CHILD_BUTTON,
+ NULL,
+ "",
+ toolbar_c->tooltip, NULL,
+ pixmap, NULL, NULL);
+ gtk_label_set_use_underline(
+ GTK_LABEL (((GtkToolbarChild*) (
+ g_list_last (GTK_TOOLBAR
+ (tool_menu_title_menu)->children)->data))->label),
+ TRUE);
+ gtk_container_set_border_width (GTK_CONTAINER (new_widget), 1);
+ g_signal_connect ((gpointer) new_widget,
+ "clicked",
+ G_CALLBACK (insert_viewer_wrap),
+ constructor);
+ gtk_widget_show (new_widget);
+
+ lttv_toolbars_add(instance_toolbar, toolbar_c->con,
+ toolbar_c->tooltip,
+ toolbar_c->pixmap,
+ new_widget);
+
+}
+
+void add_menu_constructor(MainWindow *mw, LttvMenuClosure *menu_c)
+{
+ LttvIAttribute *attributes = mw->attributes;
+ LttvAttributeValue value;
+ LttvToolbars * instance_menu;
+ lttvwindow_viewer_constructor constructor;
+ GtkWidget * tool_menu_title_menu, *new_widget;
+
+ g_assert(lttv_iattribute_find_by_path(attributes,
+ "viewers/menu", LTTV_POINTER, &value));
+ if(*(value.v_pointer) == NULL)
+ *(value.v_pointer) = lttv_menus_new();
+ instance_menu = (LttvMenus*)*(value.v_pointer);
+
+
+ constructor = menu_c->con;
+ tool_menu_title_menu = lookup_widget(mw->mwindow,"ToolMenuTitle_menu");
+ new_widget =
+ gtk_menu_item_new_with_mnemonic (menu_c->menu_text);
+ gtk_container_add (GTK_CONTAINER (tool_menu_title_menu),
+ new_widget);
+ g_signal_connect ((gpointer) new_widget, "activate",
+ G_CALLBACK (insert_viewer_wrap),
+ constructor);
+ gtk_widget_show (new_widget);
+ lttv_menus_add(instance_menu, menu_c->con,
+ menu_c->menu_path,
+ menu_c->menu_text,
+ new_widget);
+}
+
+void remove_toolbar_constructor(MainWindow *mw, lttvwindow_viewer_constructor viewer_constructor)
+{
+ LttvIAttribute *attributes = mw->attributes;
+ LttvAttributeValue value;
+ LttvToolbars * instance_toolbar;
+ lttvwindow_viewer_constructor constructor;
+ GtkWidget * tool_menu_title_menu, *widget;
+
+ g_assert(lttv_iattribute_find_by_path(attributes,
+ "viewers/toolbar", LTTV_POINTER, &value));
+ if(*(value.v_pointer) == NULL)
+ *(value.v_pointer) = lttv_toolbars_new();
+ instance_toolbar = (LttvToolbars*)*(value.v_pointer);
+
+ tool_menu_title_menu = lookup_widget(mw->mwindow,"MToolbar1");
+ widget = lttv_menus_remove(instance_toolbar, viewer_constructor);
+ gtk_container_remove (GTK_CONTAINER (tool_menu_title_menu),
+ widget);
+}
+
+
+void remove_menu_constructor(MainWindow *mw, lttvwindow_viewer_constructor viewer_constructor)
+{
+ LttvIAttribute *attributes = mw->attributes;
+ LttvAttributeValue value;
+ LttvMenus * instance_menu;
+ lttvwindow_viewer_constructor constructor;
+ GtkWidget * tool_menu_title_menu, *widget;
+ LttvMenuClosure *menu_item_i;
+
+ g_assert(lttv_iattribute_find_by_path(attributes,
+ "viewers/menu", LTTV_POINTER, &value));
+ if(*(value.v_pointer) == NULL)
+ *(value.v_pointer) = lttv_menus_new();
+ instance_menu = (LttvMenus*)*(value.v_pointer);
+
+ widget = lttv_menus_remove(instance_menu, viewer_constructor);
+ tool_menu_title_menu = lookup_widget(mw->mwindow,"ToolMenuTitle_menu");
+ gtk_container_remove (GTK_CONTAINER (tool_menu_title_menu), widget);
+}
+
+
+/**
+ * API parts
+ */
+
+
+/**
+ * Function to register a view constructor so that main window can generate
+ * a menu item and a toolbar item for the viewer in order to generate a new
+ * instance easily. A menu entry and toolbar item will be added to each main
+ * window.
+ *
+ * It should be called by init function of the module.
+ *
+ * @param menu_path path of the menu item.
+ * @param menu_text text of the menu item.
+ * @param pixmap Image shown on the toolbar item.
+ * @param tooltip tooltip of the toolbar item.
+ * @param view_constructor constructor of the viewer.
+ */
+
+void lttvwindow_register_constructor
+ (char * menu_path,
+ char * menu_text,
+ char ** pixmap,
+ char * tooltip,
+ lttvwindow_viewer_constructor view_constructor)
+{
+ LttvIAttribute *attributes_global = LTTV_IATTRIBUTE(lttv_global_attributes());
+ LttvToolbars * toolbar;
+ LttvMenus * menu;
+ LttvToolbarClosure toolbar_c;
+ LttvMenuClosure menu_c;
+ LttvAttributeValue value;
+
+ if(pixmap != NULL) {
+ g_assert(lttv_iattribute_find_by_path(attributes_global,
+ "viewers/toolbar", LTTV_POINTER, &value));
+ toolbar = (LttvToolbars*)*(value.v_pointer);
+
+ if(toolbar == NULL) {
+ toolbar = lttv_toolbars_new();
+ *(value.v_pointer) = toolbar;
+ }
+ toolbar_c = lttv_toolbars_add(toolbar, view_constructor, tooltip, pixmap,
+ NULL);
+
+ g_slist_foreach(g_main_window_list,
+ (gpointer)add_toolbar_constructor,
+ &toolbar_c);
+ }
+
+ if(menu_path != NULL) {
+ g_assert(lttv_iattribute_find_by_path(attributes_global,
+ "viewers/menu", LTTV_POINTER, &value));
+ menu = (LttvMenus*)*(value.v_pointer);
+
+ if(menu == NULL) {
+ menu = lttv_menus_new();
+ *(value.v_pointer) = menu;
+ }
+ menu_c = lttv_menus_add(menu, view_constructor, menu_path, menu_text,NULL);
+
+ g_slist_foreach(g_main_window_list,
+ (gpointer)add_menu_constructor,
+ &menu_c);
+ }
+}
+
+
+/**
+ * Function to unregister the viewer's constructor, release the space
+ * occupied by menu_path, menu_text, pixmap, tooltip and constructor of the
+ * viewer.
+ *
+ * It will be called when a module is unloaded.
+ *
+ * @param view_constructor constructor of the viewer.
+ */
+
+
+void lttvwindow_unregister_constructor
+ (lttvwindow_viewer_constructor view_constructor)
+{
+ LttvIAttribute *attributes_global = LTTV_IATTRIBUTE(lttv_global_attributes());
+ LttvToolbars * toolbar;
+ LttvMenus * menu;
+ LttvAttributeValue value;
+
+ g_assert(lttv_iattribute_find_by_path(attributes_global,
+ "viewers/toolbar", LTTV_POINTER, &value));
+ toolbar = (LttvToolbars*)*(value.v_pointer);
+
+ if(toolbar != NULL) {
+ g_slist_foreach(g_main_window_list,
+ (gpointer)remove_toolbar_constructor,
+ view_constructor);
+ lttv_toolbars_remove(toolbar, view_constructor);
+ }
+
+ g_assert(lttv_iattribute_find_by_path(attributes_global,
+ "viewers/menu", LTTV_POINTER, &value));
+ menu = (LttvMenus*)*(value.v_pointer);
+
+ if(menu != NULL) {
+ g_slist_foreach(g_main_window_list,
+ (gpointer)remove_menu_constructor,
+ view_constructor);
+ lttv_menus_remove(menu, view_constructor);
+ }
+}
+
+
+/**
+ * Function to register a hook function for a viewer to set/update its
+ * time interval.
+ * @param tab viewer's tab
+ * @param hook hook function of the viewer.
+ * @param hook_data hook data associated with the hook function.
+ */
+void lttvwindow_register_time_window_notify(Tab *tab,
+ LttvHook hook, gpointer hook_data)
+{
+ LttvAttributeValue value;
+ LttvHooks * tmp;
+ g_assert(lttv_iattribute_find_by_path(tab->attributes,
+ "hooks/updatetimewindow", LTTV_POINTER, &value));
+ tmp = (LttvHooks*)*(value.v_pointer);
+ if(tmp == NULL){
+ tmp = lttv_hooks_new();
+ *(value.v_pointer) = tmp;
+ }
+ lttv_hooks_add(tmp, hook,hook_data, LTTV_PRIO_DEFAULT);
+}
+
+
+/**
+ * Function to unregister a viewer's hook function which is used to
+ * set/update the time interval of the viewer.
+ * @param tab viewer's tab
+ * @param hook hook function of the viewer.
+ * @param hook_data hook data associated with the hook function.
+ */
+
+void lttvwindow_unregister_time_window_notify(Tab *tab,
+ LttvHook hook, gpointer hook_data)
+{
+ LttvAttributeValue value;
+ LttvHooks * tmp;
+ g_assert(lttv_iattribute_find_by_path(tab->attributes,
+ "hooks/updatetimewindow", LTTV_POINTER, &value));
+ tmp = (LttvHooks*)*(value.v_pointer);
+ if(tmp == NULL) return;
+ lttv_hooks_remove_data(tmp, hook, hook_data);
+}
+
+/**
+ * Function to register a hook function for a viewer to set/update its
+ * traceset.
+ * @param tab viewer's tab
+ * @param hook hook function of the viewer.
+ * @param hook_data hook data associated with the hook function.
+ */
+
+void lttvwindow_register_traceset_notify(Tab *tab,
+ LttvHook hook, gpointer hook_data)
+{
+ LttvAttributeValue value;
+ LttvHooks * tmp;
+ g_assert(lttv_iattribute_find_by_path(tab->attributes,
+ "hooks/updatetraceset", LTTV_POINTER, &value));
+ tmp = (LttvHooks*)*(value.v_pointer);
+ if(tmp == NULL){
+ tmp = lttv_hooks_new();
+ *(value.v_pointer) = tmp;
+ }
+ lttv_hooks_add(tmp, hook, hook_data, LTTV_PRIO_DEFAULT);
+}
+
+
+/**
+ * Function to unregister a viewer's hook function which is used to
+ * set/update the traceset of the viewer.
+ * @param tab viewer's tab
+ * @param hook hook function of the viewer.
+ * @param hook_data hook data associated with the hook function.
+ */
+
+void lttvwindow_unregister_traceset_notify(Tab *tab,
+ LttvHook hook, gpointer hook_data)
+{
+ LttvAttributeValue value;
+ LttvHooks * tmp;
+ g_assert(lttv_iattribute_find_by_path(tab->attributes,
+ "hooks/updatetraceset", LTTV_POINTER, &value));
+ tmp = (LttvHooks*)*(value.v_pointer);
+ if(tmp == NULL) return;
+ lttv_hooks_remove_data(tmp, hook, hook_data);
+}
+
+/**
+ * Function to register a hook function for a viewer to set/update its
+ * filter.
+ * @param tab viewer's tab
+ * @param hook hook function of the viewer.
+ * @param hook_data hook data associated with the hook function.
+ */
+
+void lttvwindow_register_filter_notify(Tab *tab,
+ LttvHook hook, gpointer hook_data)
+{
+ LttvAttributeValue value;
+ LttvHooks * tmp;
+ g_assert(lttv_iattribute_find_by_path(tab->attributes,
+ "hooks/updatefilter", LTTV_POINTER, &value));
+ tmp = (LttvHooks*)*(value.v_pointer);
+ if(tmp == NULL){
+ tmp = lttv_hooks_new();
+ *(value.v_pointer) = tmp;
+ }
+ lttv_hooks_add(tmp, hook, hook_data, LTTV_PRIO_DEFAULT);
+}
+
+
+/**
+ * Function to unregister a viewer's hook function which is used to
+ * set/update the filter of the viewer.
+ * @param tab viewer's tab
+ * @param hook hook function of the viewer.
+ * @param hook_data hook data associated with the hook function.
+ */
+
+void lttvwindow_unregister_filter_notify(Tab *tab,
+ LttvHook hook,
+ gpointer hook_data)
+{
+ LttvAttributeValue value;
+ LttvHooks * tmp;
+ g_assert(lttv_iattribute_find_by_path(tab->attributes,
+ "hooks/updatefilter", LTTV_POINTER, &value));
+ tmp = (LttvHooks*)*(value.v_pointer);
+ if(tmp == NULL) return;
+ lttv_hooks_remove_data(tmp, hook, hook_data);
+}
+
+/**
+ * Function to register a hook function for a viewer to set/update its
+ * current time.
+ * @param tab viewer's tab
+ * @param hook hook function of the viewer.
+ * @param hook_data hook data associated with the hook function.
+ */
+
+void lttvwindow_register_current_time_notify(Tab *tab,
+ LttvHook hook, gpointer hook_data)
+{
+ LttvAttributeValue value;
+ LttvHooks * tmp;
+ g_assert(lttv_iattribute_find_by_path(tab->attributes,
+ "hooks/updatecurrenttime", LTTV_POINTER, &value));
+ tmp = (LttvHooks*)*(value.v_pointer);
+ if(tmp == NULL){
+ tmp = lttv_hooks_new();
+ *(value.v_pointer) = tmp;
+ }
+ lttv_hooks_add(tmp, hook, hook_data, LTTV_PRIO_DEFAULT);
+}
+
+
+/**
+ * Function to unregister a viewer's hook function which is used to
+ * set/update the current time of the viewer.
+ * @param tab viewer's tab
+ * @param hook hook function of the viewer.
+ * @param hook_data hook data associated with the hook function.
+ */
+
+void lttvwindow_unregister_current_time_notify(Tab *tab,
+ LttvHook hook, gpointer hook_data)
+{
+ LttvAttributeValue value;
+ LttvHooks * tmp;
+ g_assert(lttv_iattribute_find_by_path(tab->attributes,
+ "hooks/updatecurrenttime", LTTV_POINTER, &value));
+ tmp = (LttvHooks*)*(value.v_pointer);
+ if(tmp == NULL) return;
+ lttv_hooks_remove_data(tmp, hook, hook_data);
+}
+
+
+/**
+ * Function to register a hook function for a viewer to show
+ * the content of the viewer.
+ * @param tab viewer's tab
+ * @param hook hook function of the viewer.
+ * @param hook_data hook data associated with the hook function.
+ */
+
+void lttvwindow_register_show_notify(Tab *tab,
+ LttvHook hook, gpointer hook_data)
+{
+ LttvAttributeValue value;
+ LttvHooks * tmp;
+ g_assert(lttv_iattribute_find_by_path(tab->attributes,
+ "hooks/showviewer", LTTV_POINTER, &value));
+ tmp = (LttvHooks*)*(value.v_pointer);
+ if(tmp == NULL){
+ tmp = lttv_hooks_new();
+ *(value.v_pointer) = tmp;
+ }
+ lttv_hooks_add(tmp, hook, hook_data, LTTV_PRIO_DEFAULT);
+}
+
+
+/**
+ * Function to unregister a viewer's hook function which is used to
+ * show the content of the viewer..
+ * @param tab viewer's tab
+ * @param hook hook function of the viewer.
+ * @param hook_data hook data associated with the hook function.
+ */
+
+void lttvwindow_unregister_show_notify(Tab *tab,
+ LttvHook hook, gpointer hook_data)
+{
+ LttvAttributeValue value;
+ LttvHooks * tmp;
+ g_assert(lttv_iattribute_find_by_path(tab->attributes,
+ "hooks/showviewer", LTTV_POINTER, &value));
+ tmp = (LttvHooks*)*(value.v_pointer);
+ if(tmp == NULL) return;
+ lttv_hooks_remove_data(tmp, hook, hook_data);
+}
+
+/**
+ * Function to register a hook function for a viewer to set/update the
+ * dividor of the hpane.
+ * @param tab viewer's tab
+ * @param hook hook function of the viewer.
+ * @param hook_data hook data associated with the hook function.
+ */
+
+void lttvwindow_register_dividor(Tab *tab,
+ LttvHook hook, gpointer hook_data)
+{
+ LttvAttributeValue value;
+ LttvHooks * tmp;
+ g_assert(lttv_iattribute_find_by_path(tab->attributes,
+ "hooks/hpanedividor", LTTV_POINTER, &value));
+ tmp = (LttvHooks*)*(value.v_pointer);
+ if(tmp == NULL){
+ tmp = lttv_hooks_new();
+ *(value.v_pointer) = tmp;
+ }
+ lttv_hooks_add(tmp, hook, hook_data, LTTV_PRIO_DEFAULT);
+}
+
+
+/**
+ * Function to unregister a viewer's hook function which is used to
+ * set/update hpane's dividor of the viewer.
+ * It will be called by the destructor of the viewer.
+ * @param tab viewer's tab
+ * @param hook hook function of the viewer.
+ * @param hook_data hook data associated with the hook function.
+ */
+
+void lttvwindow_unregister_dividor(Tab *tab,
+ LttvHook hook, gpointer hook_data)
+{
+ LttvAttributeValue value;
+ LttvHooks * tmp;
+ g_assert(lttv_iattribute_find_by_path(tab->attributes,
+ "hooks/hpanedividor", LTTV_POINTER, &value));
+ tmp = (LttvHooks*)*(value.v_pointer);
+ if(tmp == NULL) return;
+ lttv_hooks_remove_data(tmp, hook, hook_data);
+}
+
+
+/**
+ * Update the status bar whenever something changed in the viewer.
+ * @param tab viewer's tab
+ * @param info the message which will be shown in the status bar.
+ */
+
+void lttvwindow_report_status(Tab *tab, const char *info)
+{
+ //FIXME
+ g_warning("update_status not implemented in viewer.c");
+ // Use tab->mw for status
+}
+
+/**
+ * Function to set the time interval of the current tab.
+ * It will be called by a viewer's signal handle associated with
+ * the move_slider signal
+ * @param tab viewer's tab
+ * @param time_interval a pointer where time interval is stored.
+ */
+
+void lttvwindow_report_time_window(Tab *tab,
+ const TimeWindow *time_window)
+{
+ set_time_window(tab, time_window);
+ set_time_window_adjustment(tab, time_window);
+}
+
+
+/**
+ * Function to set the current time/event of the current tab.
+ * It will be called by a viewer's signal handle associated with
+ * the button-release-event signal
+ * @param tab viewer's tab
+ * @param time a pointer where time is stored.
+ */
+
+void lttvwindow_report_current_time(Tab *tab,
+ const LttTime *time)
+{
+ LttvAttributeValue value;
+ LttvHooks * tmp;
+ tab->current_time = *time;
+ g_assert(lttv_iattribute_find_by_path(tab->attributes,
+ "hooks/updatecurrenttime", LTTV_POINTER, &value));
+ tmp = (LttvHooks*)*(value.v_pointer);
+
+ if(tmp == NULL)return;
+ lttv_hooks_call(tmp, &tab->current_time);
+}
+
+/**
+ * Function to set the position of the hpane's dividor (viewer).
+ * It will be called by a viewer's signal handle associated with
+ * the motion_notify_event event/signal
+ * @param tab viewer's tab
+ * @param position position of the hpane's dividor.
+ */
+
+void lttvwindow_report_dividor(Tab *tab, gint position)
+{
+ LttvAttributeValue value;
+ LttvHooks * tmp;
+ g_assert(lttv_iattribute_find_by_path(tab->attributes,
+ "hooks/hpanedividor", LTTV_POINTER, &value));
+ tmp = (LttvHooks*)*(value.v_pointer);
+ if(tmp == NULL) return;
+ lttv_hooks_call(tmp, &position);
+}
+
+/**
+ * Function to set the focused pane (viewer).
+ * It will be called by a viewer's signal handle associated with
+ * the grab_focus signal
+ * @param tab viewer's tab
+ * @param top_widget the top widget containing all the other widgets of the
+ * viewer.
+ */
+
+void lttvwindow_report_focus(Tab *tab, GtkWidget *top_widget)
+{
+ gtk_multi_vpaned_set_focus((GtkWidget*)tab->multi_vpaned,
+ GTK_PANED(gtk_widget_get_parent(top_widget)));
+}
+
+
+/**
+ * Function to request data in a specific time interval to the main window. The
+ * event request servicing is differed until the glib idle functions are
+ * called.
+ *
+ * The viewer has to provide hooks that should be associated with the event
+ * request.
+ *
+ * Either start time or start position must be defined in a EventRequest
+ * structure for it to be valid.
+ *
+ * end_time, end_position and num_events can all be defined. The first one
+ * to occur will be used as end criterion.
+ *
+ * @param tab viewer's tab
+ * @param events_requested the structure of request from.
+ */
+
+void lttvwindow_events_request(Tab *tab,
+ const EventsRequest *events_request)
+{
+ EventsRequest *alloc = g_new(sizeof(EventsRequest,1));
+ *alloc = *events_request;
+
+ tab->events_requests = g_slist_append(tab->events_requests, alloc);
+
+ if(!tab->events_request_pending)
+ {
+ /* Redraw has +20 priority. We want a prio higher than that, so +19 */
+ g_idle_add_full((G_PRIORITY_HIGH_IDLE + 19),
+ (GSourceFunc)execute_events_requests,
+ tab,
+ NULL);
+ tab->events_request_pending = TRUE;
+ }
+}
+
+
+/**
+ * Function to remove data requests related to a viewer.
+ *
+ * The existing requests's viewer gpointer is compared to the pointer
+ * given in argument to establish which data request should be removed.
+ *
+ * @param tab the tab the viewer belongs to.
+ * @param viewer a pointer to the viewer data structure
+ */
+
+gint find_viewer (const EventsRequest *a, gconstpointer b)
+{
+ return (a->viewer != b);
+}
+
+
+void lttvwindow_events_request_remove_all(Tab *tab,
+ gconstpointer viewer)
+{
+ GSList *element;
+
+ while((element =
+ g_slist_find_custom(tab->events_requests, viewer,
+ (GCompareFunc)find_viewer))
+ != NULL) {
+ EventRequest *events_request = (EventsRequest *)element->data;
+ if(events_request->servicing == TRUE) {
+ lttv_hooks_call(events_request->after_request, NULL);
+ }
+ g_free(events_request);
+ tab->events_requests = g_slist_remove_link(tab->events_requests, element);
+
+ }
+}
+
+
+
+/**
+ * Function to get the current time interval shown on the current tab.
+ * It will be called by a viewer's hook function to update the
+ * shown time interval of the viewer and also be called by the constructor
+ * of the viewer.
+ * @param tab viewer's tab
+ * @param time_interval a pointer where time interval will be stored.
+ */
+
+const TimeWindow *lttvwindow_get_time_window(Tab *tab)
+{
+ return &(tab->time_window);
+
+}
+
+
+/**
+ * Function to get the current time/event of the current tab.
+ * It will be called by a viewer's hook function to update the
+ * current time/event of the viewer.
+ * @param tab viewer's tab
+ * @param time a pointer where time will be stored.
+ */
+
+const LttTime *lttvwindow_get_current_time(Tab *tab)
+{
+ return &(tab->current_time);
+}
+
+
+/**
+ * Function to get the filter of the current tab.
+ * It will be called by the constructor of the viewer and also be
+ * called by a hook funtion of the viewer to update its filter.
+ * @param tab viewer's tab
+ * @param filter, a pointer to a filter.
+ */
+const lttv_filter *lttvwindow_get_filter(Tab *tab)
+{
+ //FIXME
+ g_warning("lttvwindow_get_filter not implemented in viewer.c");
+}
+
+
+/**
+ * Function to get the stats of the traceset
+ * @param tab viewer's tab
+ */
+
+LttvTracesetStats* lttvwindow_get_traceset_stats(Tab *tab)
+{
+ return tab->traceset_info->traceset_context;
+}
+
+
+LttvTracesetContext* lttvwindow_get_traceset_context(Tab *tab)
+{
+ return (LttvTracesetContext*)tab->traceset_info->traceset_context;
+}
--- /dev/null
+/* This file is part of the Linux Trace Toolkit Graphic User Interface
+ * Copyright (C) 2003-2004 Xiangxiu Yang, Mathieu Desnoyers
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License Version 2 as
+ * published by the Free Software Foundation;
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+/*
+This file is what every viewer plugin writer should refer to.
+
+
+Module Related API
+
+A viewer plugin is, before anything, a plugin. As a dynamically loadable
+module, it thus has an init and a destroy function called whenever it is
+loaded/initialized and unloaded/destroyed. A graphical module depends on
+lttvwindow for construction of its viewer instances. In order to achieve this,
+it must register its constructor function to the main window along with
+button description or text menu entry description. A module keeps a list of
+every viewer that currently sits in memory so it can destroy them before the
+module gets unloaded/destroyed.
+
+The contructor registration to the main windows adds button and menu entry
+to each main window, thus allowing instanciation of viewers.
+
+
+Main Window
+
+The main window is a container that offers menus, buttons and a notebook. Some
+of those menus and buttons are part of the core of the main window, others
+are dynamically added and removed when modules are loaded/unloaded.
+
+The notebook contains as much tabs as wanted. Each tab is linked with a
+set of traces (traceset). Each trace contains many tracefiles (one per cpu).
+A trace corresponds to a kernel being traced. A traceset corresponds to
+many traces read together. The time span of a traceset goes from the
+earliest start of all the traces to the latest end of all the traces.
+
+Inside each tab are added the viewers. When they interact with the main
+window through the lttvwindow API, they affect the other viewers located
+in the same tab as they are.
+
+The insertion of many viewers in a tab permits a quick look at all the
+information wanted in a glance. The main window does merge the read requests
+from all the viewers in the same tab in a way that every viewer will get exactly
+the events it asked for, while the event reading loop and state update are
+shared. It improves performance of events delivery to the viewers.
+
+
+
+Viewer Instance Related API
+
+The lifetime of a viewer is as follows. The viewer constructor function is
+called each time an instance view is created (one subwindow of this viewer
+type is created by the user either by clicking on the menu item or the button
+corresponding to the viewer). Thereafter, the viewer gets hooks called for
+different purposes by the window containing it. These hooks are detailed
+below. It also has to deal with GTK Events. Finally, it can be destructed by
+having its top level widget unreferenced by the main window or by any
+GTK Event causing a "destroy-event" signal on the its top widget. Another
+possible way for it do be destroyed is if the module gets unloaded. The module
+unload function will have to emit a "destroy" signal on each top level widget
+of all instances of its viewers.
+
+
+Notices from Main Window
+
+time_window : This is the time interval visible on the viewer's tab. Every
+ viewer that cares about being synchronised by respect to the
+ time with other viewers should register to this notification.
+ They should redraw all or part of their display when this occurs.
+
+traceset : This notification is called whenever a trace is added/removed
+ from the traceset. As it affects all the data displayed by the
+ viewer, it sould redraw itself totally.
+
+filter : FIXME : describe..
+
+current_time: Being able to zoom nearer a specific time or highlight a specific
+ time on every viewer in synchronicity implies that the viewer
+ has to shown a visual sign over the drawing or select an event
+ when it receives this notice. It should also inform the main
+ window with the appropriate report API function when a user
+ selects a specific time as being the current time.
+
+dividor : This notice links the positions of the horizontal dividors
+ between the graphic display zone of every viewer and their Y axis,
+ typically showing processes, cpus, ...
+
+
+FIXME : Add background computation explanation here
+background_init: prepare for background computation (comes after show_end).
+process_trace for background: done in small chunks in gtk_idle, hooks called.
+background_end: remove the hooks and perhaps update the window.
+
+
+Reporting Changes to the Main Window
+
+In most cases, the enclosing window knows about updates such as described in the
+Notification section higher. There are a few cases, however, where updates are
+caused by actions known by a view instance. For example, clicking in a view may
+update the current time; all viewers within the same window must be told about
+the new current time to change the currently highlighted time point. A viewer
+reports such events by calling lttvwindow_report_current_time on its lttvwindow.
+The lttvwindow will consequently call current_time_notify for each of its
+contained viewers.
+
+
+Available report methods are :
+
+lttvwindow_report_status : reports the text of the status bar.
+lttvwindow_report_time_window : reports the new time window.
+lttvwindow_report_current_time : reports the new current time.
+lttvwindow_report_dividor : reports the new horizontal dividor's position.
+lttvwindow_report_focus : One on the widgets in the viewer has the keyboard's
+ focus from GTK.
+
+
+
+Requesting Events to Main Window
+
+Events can be requested by passing a EventsRequest structure to the main window.
+They will be delivered later when the next g_idle functions will be called.
+Event delivery is done by calling the event hook for this event ID, or the
+main event hooks. A pointer to the EventsRequest structure is passed as
+hook_data to the event hooks of the viewers.
+
+EventsRequest consists in
+- a pointer to the viewer specific data structure
+- a start timestamp or position
+- a stop_flag, ending the read process when set to TRUE
+- a end timestamp and/or position and/or number of events to read
+- hook lists to call for traceset/trace/tracefile begin and end, and for each
+ event (event hooks and event_by_id hooks).
+
+The main window will deliver events for every EventRequests it has pending
+through an algorithm that guarantee that all events requested, and only them,
+will be delivered to the viewer between the call of the tracefile_begin hooks
+and the call of the tracefile_end hooks.
+
+If a viewer wants to stop the event request at a certain point inside the event
+hooks, it has to set the stop_flag to TRUE and return TRUE from the hook
+function. Then return value will stop the process traceset. Then, the main
+window will look for the stop_flag and remove the EventRequests from its lists,
+calling the process_traceset_end for this request (it removes hooks from the
+context and calls the after hooks).
+
+It no stop_flag is rose, the end timestamp, end position or number of events to
+read has to be reached to determine the end of the request. Otherwise,
+the end of traceset does determine it.
+
+
+GTK Events
+
+Events and Signals
+
+GTK is quite different from the other graphical toolkits around there. The main
+difference resides in that there are many X Windows inside one GtkWindow,
+instead of just one. That means that X events are delivered by the glib main
+loop directly to the widget corresponding to the GdkWindow affected by the X
+event.
+
+Event delivery to a widget emits a signal on that widget. Then, if a handler
+is connected to this widget's signal, it will be executed. There are default
+handlers for signals, connected at class instantiation time. There is also
+the possibility to connect other handlers to these signals, which is what
+should be done in most cases when a viewer needs to interact with X in any
+way.
+
+
+
+Signal emission and propagation is described there :
+
+http://www.gtk.org/tutorial/sec-signalemissionandpropagation.html
+
+For further information on the GTK main loop (now a wrapper over glib main loop)
+see :
+
+http://developer.gnome.org/doc/API/2.0/gtk/gtk-General.html
+http://developer.gnome.org/doc/API/2.0/glib/glib-The-Main-Event-Loop.html
+
+
+For documentation on event handling in GTK/GDK, see :
+
+http://developer.gnome.org/doc/API/2.0/gdk/gdk-Events.html
+http://developer.gnome.org/doc/API/2.0/gdk/gdk-Event-Structures.html
+
+
+Signals can be connected to handlers, emitted, propagated, blocked,
+stopped. See :
+
+http://developer.gnome.org/doc/API/2.0/gobject/gobject-Signals.html
+
+
+
+
+The "expose_event"
+
+Provides the exposed region in the GdkEventExpose structure.
+
+There are two ways of dealing with exposures. The first one is to directly draw
+on the screen and the second one is to draw in a pixmap buffer, and then to
+update the screen when necessary.
+
+In the first case, the expose event will be responsible for registering hooks to
+process_traceset and require time intervals to the main window. So, in this
+scenario, if a part of the screen is damaged, the trace has to be read to
+redraw the screen.
+
+In the second case, with a pixmap buffer, the expose handler is only responsible
+of showing the pixmap buffer on the screen. If the pixmap buffer has never
+been filled with a drawing, the expose handler may ask for it to be filled.
+
+The interest of using events request to the main window instead of reading the
+events directly from the trace comes from the fact that the main window
+does merge requests from the different viewers in the same tab so that the
+read loop and the state update is shared. As viewers will, in the common
+scenario, request the same events, only one pass through the trace that will
+call the right hooks for the right intervals will be done.
+
+When the traceset read is over for a events request, the traceset_end hook is
+called. It has the responsibility of finishing the drawing if some parts
+still need to be drawn and to show it on the screen (if the viewer uses a pixmap
+buffer).
+
+It can add dotted lines and such visual effects to enhance the user's
+experience.
+
+
+FIXME : explain other important events
+
+*/
+
+
+#ifndef VIEWER_H
+#define VIEWER_H
+
+/*! \file lttvwindow.h
+ * \brief API used by the graphical viewers to interact with their top window.
+ *
+ * Main window (lttvwindow module) is the place to contain and display viewers.
+ * Viewers (lttv plugins) interact with main window through this API.
+ * This header file should be included in each graphic module.
+ *
+ */
+
+#include <gtk/gtk.h>
+#include <ltt/ltt.h>
+#include <ltt/time.h>
+#include <lttv/hook.h>
+#include <lttv/tracecontext.h>
+#include <lttv/stats.h>
+#include <lttvwindow/common.h>
+//FIXME (not ready yet) #include <lttv/filter.h>
+
+
+/* Module Related API */
+
+
+/* constructor a the viewer */
+//FIXME explain LttvTracesetSelector and key
+typedef GtkWidget * (*lttvwindow_viewer_constructor)
+ (Tab *tab, LttvTracesetSelector * s, char *key);
+
+
+/**
+ * Function to register a view constructor so that main window can generate
+ * a menu item and a toolbar item for the viewer in order to generate a new
+ * instance easily. A menu entry and toolbar item will be added to each main
+ * window.
+ *
+ * It should be called by init function of the module.
+ *
+ * @param menu_path path of the menu item. NULL : no menu entry.
+ * @param menu_text text of the menu item.
+ * @param pixmap Image shown on the toolbar item. NULL : no button.
+ * @param tooltip tooltip of the toolbar item.
+ * @param view_constructor constructor of the viewer.
+ */
+
+void lttvwindow_register_constructor
+ (char * menu_path,
+ char * menu_text,
+ char ** pixmap,
+ char * tooltip,
+ lttvwindow_viewer_constructor view_constructor);
+
+
+/**
+ * Function to unregister the viewer's constructor, release the space
+ * occupied by menu_path, menu_text, pixmap, tooltip and constructor of the
+ * viewer.
+ *
+ * It will be called when a module is unloaded.
+ *
+ * @param view_constructor constructor of the viewer.
+ */
+
+void lttvwindow_unregister_constructor
+ (lttvwindow_viewer_constructor view_constructor);
+
+
+
+
+/* Viewer Instance Related API */
+
+/**
+ * Structure used as hook_data for the time_window_notify hook.
+ */
+typedef struct _TimeWindowNotifyData {
+ TimeWindow *new_time_window;
+ TimeWindow *old_time_window;
+} TimeWindowNotifyData;
+
+
+/**
+ * Function to register a hook function that will be called by the main window
+ * when the time interval needs to be updated.
+ *
+ * This register function is typically called by the constructor of the viewer.
+ *
+ * @param tab the tab the viewer belongs to.
+ * @param hook hook that sould be called by the main window when the time
+ * interval changes. This hook function takes a
+ * TimeWindowNotifyData* as call_data.
+ * @param hook_data hook data associated with the hook function. It will
+ * be typically a pointer to the viewer's data structure.
+ */
+
+void lttvwindow_register_time_window_notify(Tab *tab,
+ LttvHook hook,
+ gpointer hook_data);
+
+
+/**
+ * Function to unregister the time_window notification hook.
+ *
+ * This unregister function is typically called by the destructor of the viewer.
+ *
+ * @param tab the tab the viewer belongs to.
+ * @param hook hook that sould be called by the main window when the time
+ * interval changes. This hook function takes a
+ * TimeWindowNotifyData* as call_data.
+ * @param hook_data hook data associated with the hook function. It will
+ * be typically a pointer to the viewer's data structure.
+ */
+
+void lttvwindow_unregister_time_window_notify(Tab *tab,
+ LttvHook hook,
+ gpointer hook_data);
+
+
+/**
+ * Function to register a hook function that will be called by the main window
+ * when the traceset is changed. That means that the viewer must redraw
+ * itself completely or check if it's affected by the particular change to the
+ * traceset.
+ *
+ * This register function is typically called by the constructor of the viewer.
+ *
+ * @param tab the tab the viewer belongs to.
+ * @param hook hook that should be called whenever a change to the traceset
+ * occurs. The call_data of this hook is a NULL pointer.
+ * @param hook_data hook data associated with the hook function. It will
+ * be typically a pointer to the viewer's data structure.
+ */
+
+void lttvwindow_register_traceset_notify(Tab *tab,
+ LttvHook hook,
+ gpointer hook_data);
+
+
+/**
+ * Function to unregister the traceset_notify hook.
+ *
+ * @param tab the tab the viewer belongs to.
+ * @param hook hook that should be called whenever a change to the traceset
+ * occurs. The call_data of this hook is a NULL pointer.
+ * @param hook_data hook data associated with the hook function. It will
+ * be typically a pointer to the viewer's data structure.
+ */
+
+void lttvwindow_unregister_traceset_notify(Tab *tab,
+ LttvHook hook,
+ gpointer hook_data);
+
+
+/**
+ * Function to register a hook function for a viewer to set/update its
+ * filter.
+ *
+ * FIXME : Add information about what a filter is as seen from a viewer and how
+ * to use it.
+ *
+ * This register function is typically called by the constructor of the viewer.
+ *
+ * @param tab the tab the viewer belongs to.
+ * @param hook hook function called by the main window when a filter change
+ * occurs.
+ * @param hook_data hook data associated with the hook function. It will
+ * be typically a pointer to the viewer's data structure.
+ */
+
+void lttvwindow_register_filter_notify(Tab *tab,
+ LttvHook hook,
+ gpointer hook_data);
+
+
+/**
+ * Function to unregister a viewer's hook function which is used to
+ * set/update the filter of the viewer.
+ *
+ * This unregistration is called by the destructor of the viewer.
+ *
+ * @param tab the tab the viewer belongs to.
+ * @param hook hook function called by the main window when a filter change
+ * occurs.
+ * @param hook_data hook data associated with the hook function. It will
+ * be typically a pointer to the viewer's data structure.
+ */
+
+void lttvwindow_unregister_filter_notify(Tab *tab,
+ LttvHook hook,
+ gpointer hook_data);
+
+
+/**
+ * Function to register a hook function for a viewer to set/update its
+ * current time.
+ *
+ * @param tab the tab the viewer belongs to.
+ * @param hook hook function of the viewer that updates the current time. The
+ * call_data is a LttTime* representing the new current time.
+ * @param hook_data hook data associated with the hook function. It will
+ * be typically a pointer to the viewer's data structure.
+ */
+
+void lttvwindow_register_current_time_notify(Tab *tab,
+ LttvHook hook,
+ gpointer hook_data);
+
+
+/**
+ * Function to unregister a viewer's hook function which is used to
+ * set/update the current time of the viewer.
+ * @param tab the tab the viewer belongs to.
+ * @param hook hook function of the viewer that updates the current time. The
+ * call_data is a LttTime* representing the new current time.
+ * @param hook_data hook data associated with the hook function. It will
+ * be typically a pointer to the viewer's data structure.
+ */
+
+void lttvwindow_unregister_current_time_notify(Tab *tab,
+ LttvHook hook,
+ gpointer hook_data);
+
+
+/**
+ * Function to register a hook function for a viewer to set/update the
+ * dividor of the hpane. It provides a way to make the horizontal
+ * dividors of all the viewers linked together.
+ *
+ * @param tab the tab the viewer belongs to.
+ * @param hook hook function of the viewer that will be called whenever a
+ * dividor changes in another viewer. The call_data of this hook
+ * is a gint*. The value of the integer is the new position of the
+ * hpane dividor.
+ * @param hook_data hook data associated with the hook function. It will
+ * be typically a pointer to the viewer's data structure.
+ */
+
+void lttvwindow_register_dividor(Tab *tab,
+ LttvHook hook,
+ gpointer hook_data);
+
+
+/**
+ * Function to unregister a viewer's hook function which is used to
+ * set/update hpane's dividor of the viewer.
+ *
+ * @param tab the tab the viewer belongs to.
+ * @param hook hook function of the viewer that will be called whenever a
+ * dividor changes in another viewer. The call_data of this hook
+ * is a gint*. The value of the integer is the new position of the
+ * hpane dividor.
+ * @param hook_data hook data associated with the hook function. It will
+ * be typically a pointer to the viewer's data structure.
+ */
+
+void lttvwindow_unregister_dividor(Tab *tab,
+ LttvHook hook,
+ gpointer hook_data);
+
+
+
+/**
+ * This method reports the information to show on the status bar in the
+ * main window.
+ *
+ * @param tab the tab the viewer belongs to.
+ * @param info the message which will be shown in the status bar.
+ */
+
+void lttvwindow_report_status(Tab *tab, const char *info);
+
+
+/**
+ * Function to set the time interval of the current tab.a
+ *
+ * @param tab the tab the viewer belongs to.
+ * @param time_interval pointer to the time interval value.
+ */
+
+void lttvwindow_report_time_window(Tab *tab,
+ const TimeWindow *time_window);
+
+/**
+ * Function to set the current time/event of the current tab.
+ * It will be called by a viewer's signal handle associated with
+ * the button-release-event signal
+ * @param tab the tab the viewer belongs to.
+ * @param time a pointer where time is stored.
+ */
+
+void lttvwindow_report_current_time(Tab *tab,
+ const LttTime *time);
+
+
+/**
+ * Function to set the position of the hpane's dividor (viewer).
+ * It will typically be called by a viewer's signal handle associated
+ * with the motion_notify_event event/signal.
+ *
+ * @param tab the tab the viewer belongs to.
+ * @param position position of the hpane's dividor.
+ */
+
+void lttvwindow_report_dividor(Tab *tab, gint position);
+
+/**
+ * Function to set the focused viewer of the tab.
+ * It will be called by a viewer's signal handle associated with
+ * the grab_focus signal of all widgets in the viewer.
+ *
+ * @param tab the tab the viewer belongs to.
+ * @param top_widget the top widget containing all the other widgets of the
+ * viewer.
+ */
+void lttvwindow_report_focus(Tab *tab,
+ GtkWidget *top_widget);
+
+
+/* Structure sent to the events request hook */
+ /* Value considered as empty */
+typedef struct _EventsRequest {
+ gpointer viewer_data; /* Unset : NULL */
+ gboolean servicing; /* service in progress: TRUE */
+ LttTime start_time;/* Unset : { G_MAXUINT, G_MAXUINT }*/
+ LttvTracesetContextPosition *start_position; /* Unset : NULL */
+ gboolean stop_flag; /* Continue:TRUE Stop:FALSE */
+ LttTime end_time;/* Unset : { G_MAXUINT, G_MAXUINT } */
+ guint num_events; /* Unset : G_MAXUINT */
+ LttvTracesetContextPosition *end_position; /* Unset : NULL */
+ LttvHooks *before_chunk_traceset; /* Unset : NULL */
+ LttvHooks *before_chunk_trace; /* Unset : NULL */
+ LttvHooks *before_chunk_tracefile;/* Unset : NULL */
+ LttvHooks *event; /* Unset : NULL */
+ LttvHooksById *event_by_id; /* Unset : NULL */
+ LttvHooks *after_chunk_tracefile; /* Unset : NULL */
+ LttvHooks *after_chunk_trace; /* Unset : NULL */
+ LttvHooks *after_chunk_traceset; /* Unset : NULL */
+ LttvHooks *before_request; /* Unset : NULL */
+ LttvHooks *after_request /* Unset : NULL */
+} EventsRequest;
+
+
+/**
+ * Function to request data in a specific time interval to the main window. The
+ * event request servicing is differed until the glib idle functions are
+ * called.
+ *
+ * The viewer has to provide hooks that should be associated with the event
+ * request.
+ *
+ * Either start time or start position must be defined in a EventRequest
+ * structure for it to be valid.
+ *
+ * end_time, end_position and num_events can all be defined. The first one
+ * to occur will be used as end criterion.
+ *
+ * @param tab the tab the viewer belongs to.
+ * @param events_requested Details about the event request.
+ */
+
+void lttvwindow_events_request(Tab *tab,
+ const EventsRequest *events_request);
+
+/**
+ * Function to remove data requests related to a viewer.
+ *
+ * The existing requests's viewer gpointer is compared to the pointer
+ * given in argument to establish which data request should be removed.
+ *
+ * @param tab the tab the viewer belongs to.
+ * @param viewer a pointer to the viewer data structure
+ */
+
+void lttvwindow_events_request_remove_all(Tab *tab,
+ gconstpointer viewer);
+
+
+typedef struct _BackgroundRequest {
+ gchar *hook_path; /* Hook path in global attributes, where all standard hooks
+ are : i.e. /TraceState/Statistics/ModuleName */
+ gchar *trace_path; /* path_to_trace */
+} BackgroundRequest;
+
+typedef struct _BackgroundNotify {
+ gchar *trace_path; /* path_to_trace */
+ LttTime notify_time;
+ LttvTracesetContextPosition *notify_position;
+ LttvHooks *notify; /* Hook to call when the notify is
+ passed, or at the end of trace */
+} BackgroundNotify;
+
+/**
+ * Function to request data from a specific trace
+ *
+ * @param bg_request Request specification
+ */
+
+void lttvwindow_background_request_queue(const BackgroundRequest *bg_request);
+
+/**
+ * Register a callback to be called when requested data is passed in the next
+ * queued background processing.
+ *
+ * @param bg_request Request specification
+ */
+
+void lttvwindow_background_notify_queue(const BackgroundNotify *bg_notify);
+
+
+/**
+ * Register a callback to be called when requested data is passed in the current
+ * background processing.
+ *
+ * @param bg_request Request specification
+ */
+
+void lttvwindow_background_notify_current(const BackgroundNotify *bg_notify);
+
+
+/**
+ * Function to get the current time window of the current tab.
+ *
+ * @param tab the tab the viewer belongs to.
+ * @return a pointer to the current tab's time interval.
+ */
+
+const TimeWindow *lttvwindow_get_time_window(Tab *tab);
+
+
+/**
+ * Function to get the current time of the current tab.
+ *
+ * @param tab the tab the viewer belongs to.
+ * @return a pointer to the current tab's current time.
+ */
+
+const LttTime *lttvwindow_get_current_time(Tab *tab);
+
+
+/**
+ * Function to get the filter of the current tab.
+ * @param main_win, the main window the viewer belongs to.
+ * @param filter, a pointer to a filter.
+ */
+
+//FIXME
+typedef void lttv_filter;
+//FIXME
+const lttv_filter *lttvwindow_get_filter(Tab *tab);
+
+
+/**
+ * Function to get the stats of the traceset
+ * It must be non const so the viewer can modify it.
+ * FIXME : a set/get pair of functions would be more appropriate here.
+ * @param tab the tab the viewer belongs to.
+ * @return A pointer to Traceset statistics.
+ */
+
+LttvTracesetStats* lttvwindow_get_traceset_stats(Tab *tab);
+
+/**
+ * Function to get the context of the traceset
+ * It must be non const so the viewer can add and remove hooks from it.
+ * @param tab the tab the viewer belongs to.
+ * @return Context of the current tab.
+ */
+
+
+LttvTracesetContext* lttvwindow_get_traceset_context(Tab *tab);
+
+
+#endif //VIEWER_H
#include <gtk/gtk.h>
#include <lttvwindow/common.h>
-#include <lttvwindow/viewer.h>
+#include <lttvwindow/lttvwindow.h>
typedef GArray LttvMenus;
typedef struct _LttvMenuClosure {
lttvwindow_viewer_constructor con;
- char * menuPath;
- char * menuText;
+ char * menu_path;
+ char * menu_text;
GtkWidget *widget;
} LttvMenuClosure;
#define TOOLBAR_H
#include <lttvwindow/common.h>
-#include <lttvwindow/viewer.h>
+#include <lttvwindow/lttvwindow.h>
#include <gtk/gtk.h>
typedef GArray LttvToolbars;