| /* |
| *------------------------------------------------------------------ |
| * Copyright (c) 2006-2016 Cisco and/or its affiliates. |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at: |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include <stdio.h> |
| #include <gtk/gtk.h> |
| #define GTK_ENABLE_BROKEN // DGMS |
| #include <gtk/gtktext.h> |
| #include <stdlib.h> |
| #include "g2.h" |
| #include <string.h> |
| |
| /* |
| * locals |
| */ |
| static GtkWidget *s_mainmenubar; |
| static GtkWidget *s_filemenu; |
| static GtkWidget *s_readdefs; |
| static GtkWidget *s_readevents; |
| static GtkWidget *s_readeventsclock; |
| static GtkWidget *s_readcpel; |
| static GtkWidget *s_readclib; |
| static GtkWidget *s_print; |
| static GtkWidget *s_quit; |
| |
| static GtkWidget *s_mainfilemenu; |
| static GtkWidget *s_help_general; |
| static GtkWidget *s_help_about; |
| static GtkWidget *s_mainhelpmenu; |
| static GtkWidget *s_helpmenu; |
| |
| static GtkWidget *s_filesel; |
| static GtkWidget *s_eventsel; |
| |
| typedef struct md_ { |
| GtkWidget *entry; |
| GtkWidget *label; |
| GtkWidget *dialog; |
| boolean (*callback)(char *); |
| char *retry_text; |
| } md_t; |
| |
| char *general_help = "\n" |
| "G2 is a performance event visualization tool.\n" |
| "\n" |
| "To view CPEL-format event data:\n" |
| "g2 --cpel <filename>\n" |
| "or use the File Menu->Read CPEL file option.\n" |
| "\n" |
| "To view vppinfra-format (.../open-repo/vppinfra/vppinfra/elog.h) event data:\n" |
| "g2 --clib <filename>\n" |
| "or use the File Menu->Read clib file option.\n" |
| "\n" |
| "To toggle event detail boxes, left-mouse-click on an event.\n" |
| "\n" |
| "To zoom to an area, depress the left mouse button. Move the\n" |
| "mouse. Release the mouse.\n" |
| "\n" |
| "To use the time ruler, depress the right mouse button. Move the\n" |
| "mouse. Release when done.\n" |
| "\n" |
| "To push a track to the bottom, <ctrl><left-mouse>\n" |
| "\n" |
| "To pull a track to the top, <shift><left-mouse>\n" |
| "\n" |
| "To selectively color/uncolor a track, <ctrl><shift><left-mouse>\n" |
| "\n" |
| "To make the mouse scrollwheel faster, press <shift>\n" |
| "\n" |
| "Hotkeys, supposedly Quake-like:\n" |
| " w - zoom-in\n" |
| " s - zoom-out\n" |
| " a - pan-left\n" |
| " d - pan-right\n" |
| " r - pan-up\n" |
| " f - pan-down\n" |
| " t - less traces\n" |
| " g - more traces\n" |
| "\n" |
| " e - toggle summary-mode\n" |
| " c - toggle color-mode\n" |
| "\n" |
| " x - take snapshot\n" |
| " z - go to next snapshot\n" |
| " p - put snapshots to snapshots.g2 \n" |
| " l - load snapshots from snapshots.g2\n" |
| "\n" |
| "<ctrl>q - quit\n" |
| "Send comments / bug reports to the \"fd.io\" mailing list.\n"; |
| |
| /**************************************************************************** |
| * debug_dialog_callback |
| ****************************************************************************/ |
| |
| boolean debug_dialog_callback (char *s) |
| { |
| g_print("Dialog result: %s", s); |
| return (TRUE); |
| } |
| |
| /**************************************************************************** |
| * get_dialog_value |
| ****************************************************************************/ |
| |
| static void get_dialog_value (GtkWidget *dialog, gpointer user_data) |
| { |
| md_t *md = (md_t *)user_data; |
| char * cb_arg; |
| |
| cb_arg = (char *) gtk_entry_get_text(GTK_ENTRY(md->entry)); |
| |
| if ((*md->callback)(cb_arg)) { |
| gtk_grab_remove(md->dialog); |
| gtk_widget_destroy(md->dialog); |
| } else { |
| gtk_label_set_text (GTK_LABEL(md->label), md->retry_text); |
| } |
| } |
| |
| /**************************************************************************** |
| * modal_dialog |
| ****************************************************************************/ |
| |
| void modal_dialog (char *label_text, char *retry_text, char *default_value, |
| boolean (*cb)(char *)) |
| { |
| GtkWidget *dialog, *label, *ok_button, *entry; |
| static md_t dlg; |
| md_t *md = &dlg; |
| |
| dialog = gtk_dialog_new(); |
| label = gtk_label_new(label_text); |
| |
| entry = gtk_entry_new(); |
| if (default_value) |
| gtk_entry_set_text(GTK_ENTRY(entry), default_value); |
| |
| ok_button = gtk_button_new_with_label("OK"); |
| |
| md->entry = entry; |
| md->label = label; |
| md->retry_text = retry_text; |
| md->dialog = dialog; |
| if (cb) |
| md->callback = cb; |
| else |
| md->callback = debug_dialog_callback; |
| |
| gtk_signal_connect (GTK_OBJECT (ok_button), "clicked", |
| GTK_SIGNAL_FUNC(get_dialog_value), (gpointer) md); |
| |
| gtk_signal_connect (GTK_OBJECT (entry), "activate", |
| GTK_SIGNAL_FUNC(get_dialog_value), (gpointer) md); |
| |
| gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->action_area), |
| entry); |
| |
| gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->action_area), |
| ok_button); |
| gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), label); |
| gtk_widget_show_all(dialog); |
| gtk_widget_grab_focus(entry); |
| gtk_grab_add(dialog); |
| } |
| |
| /**************************************************************************** |
| * get_eventdef_name |
| ****************************************************************************/ |
| |
| static void get_eventdef_name (GtkFileSelection *sel, gpointer user_data) |
| { |
| char *filename = (char *) gtk_file_selection_get_filename ( |
| GTK_FILE_SELECTION(s_filesel)); |
| read_event_definitions(filename); |
| set_window_title(filename); |
| } |
| |
| /**************************************************************************** |
| * read_eventdef_callback |
| ****************************************************************************/ |
| |
| static void read_eventdef_callback(GtkToggleButton *item, gpointer data) |
| { |
| |
| s_filesel = gtk_file_selection_new("Read Event Definitions From..."); |
| |
| gtk_file_selection_set_filename(GTK_FILE_SELECTION(s_filesel), |
| "../h/elog.h"); |
| |
| gtk_signal_connect (GTK_OBJECT ( |
| GTK_FILE_SELECTION(s_filesel)->ok_button), |
| "clicked", |
| GTK_SIGNAL_FUNC(get_eventdef_name), NULL); |
| |
| gtk_signal_connect_object (GTK_OBJECT ( |
| GTK_FILE_SELECTION(s_filesel)->ok_button), |
| "clicked", |
| GTK_SIGNAL_FUNC (gtk_widget_destroy), |
| (gpointer) s_filesel); |
| |
| gtk_signal_connect_object (GTK_OBJECT ( |
| GTK_FILE_SELECTION(s_filesel)->cancel_button), |
| "clicked", |
| GTK_SIGNAL_FUNC (gtk_widget_destroy), |
| (gpointer) s_filesel); |
| gtk_file_selection_hide_fileop_buttons(GTK_FILE_SELECTION(s_filesel)); |
| gtk_widget_show (s_filesel); |
| } |
| |
| /**************************************************************************** |
| * get_events_name |
| ****************************************************************************/ |
| |
| static void get_events_name (GtkFileSelection *sel, gpointer user_data) |
| { |
| char *filename = (char *) gtk_file_selection_get_filename ( |
| GTK_FILE_SELECTION(s_eventsel)); |
| read_events(filename); |
| view1_display_when_idle(); |
| } |
| |
| |
| /**************************************************************************** |
| * get_ticks_per_ns |
| ****************************************************************************/ |
| |
| static boolean get_ticks_per_ns (char *value) |
| { |
| double rv; |
| |
| rv = atof (value); |
| |
| if (rv == 0.0 || rv > 100000) |
| return(FALSE); |
| |
| ticks_per_ns = rv; |
| ticks_per_ns_set = TRUE; |
| |
| gtk_widget_show(s_eventsel); |
| return(TRUE); |
| } |
| |
| /**************************************************************************** |
| * read_events_callback |
| ****************************************************************************/ |
| |
| static void read_events_callback(GtkToggleButton *item, gpointer data) |
| { |
| char tmpbuf [32]; |
| |
| s_eventsel = gtk_file_selection_new("Read Events From..."); |
| |
| gtk_signal_connect (GTK_OBJECT ( |
| GTK_FILE_SELECTION(s_eventsel)->ok_button), |
| "clicked", |
| GTK_SIGNAL_FUNC(get_events_name), NULL); |
| |
| gtk_signal_connect_object (GTK_OBJECT ( |
| GTK_FILE_SELECTION(s_eventsel)->ok_button), |
| "clicked", |
| GTK_SIGNAL_FUNC (gtk_widget_destroy), |
| (gpointer) s_eventsel); |
| |
| gtk_signal_connect_object (GTK_OBJECT ( |
| GTK_FILE_SELECTION(s_eventsel)->cancel_button), |
| "clicked", |
| GTK_SIGNAL_FUNC (gtk_widget_destroy), |
| (gpointer) s_eventsel); |
| gtk_file_selection_hide_fileop_buttons(GTK_FILE_SELECTION(s_eventsel)); |
| |
| if (ticks_per_ns_set) |
| gtk_widget_show (s_eventsel); |
| else { |
| sprintf(tmpbuf, "%.3f", ticks_per_ns); |
| modal_dialog ("Please enter clock ticks per nanosecond", |
| "Invalid: Please enter clock ticks per nanosecond", |
| tmpbuf, get_ticks_per_ns); |
| } |
| } |
| |
| /**************************************************************************** |
| * read_eventclock_callback |
| ****************************************************************************/ |
| |
| static void read_eventsclock_callback(GtkToggleButton *item, gpointer data) |
| { |
| ticks_per_ns_set = FALSE; |
| read_events_callback(item, data); |
| } |
| |
| /**************************************************************************** |
| * infobox_size_request |
| ****************************************************************************/ |
| |
| void infobox_size_request (GtkWidget *widget, GtkRequisition *req, |
| gpointer user_data) |
| { |
| char *text = (char *)user_data; |
| char *cp; |
| int widest_line_in_chars; |
| int w; |
| int nlines; |
| |
| /* |
| * You'd think that the string extent function would work here. |
| * You'd be wrong. |
| */ |
| nlines = w = widest_line_in_chars = 0; |
| for (cp = text; *cp; cp++) { |
| if (*cp == '\n') { |
| if (w > widest_line_in_chars) { |
| widest_line_in_chars = w; |
| } |
| w = 0; |
| nlines++; |
| } |
| w++; |
| } |
| |
| nlines++; |
| |
| req->width = (widest_line_in_chars * 8) + 20; |
| req->height = (nlines * 13) + 10; |
| } |
| |
| /**************************************************************************** |
| * infobox |
| ****************************************************************************/ |
| |
| void infobox(char *label_text, char *text) |
| { |
| GtkWidget *dialog, *label, *ok_button, *entry; |
| GtkWidget *box; |
| |
| dialog = gtk_dialog_new(); |
| label = gtk_label_new(label_text); |
| |
| entry = gtk_text_new(NULL, NULL); |
| |
| gtk_signal_connect (GTK_OBJECT (entry), "size-request", |
| GTK_SIGNAL_FUNC(infobox_size_request), |
| (gpointer) text); |
| |
| gtk_text_insert(GTK_TEXT(entry), g_font, &fg_black, &bg_white, |
| text, -1); |
| |
| gtk_text_set_editable(GTK_TEXT(entry), FALSE); |
| |
| ok_button = gtk_button_new_with_label("OK"); |
| |
| gtk_signal_connect_object (GTK_OBJECT (ok_button), "clicked", |
| GTK_SIGNAL_FUNC(gtk_widget_destroy), |
| (gpointer) GTK_OBJECT(dialog)); |
| |
| box = gtk_vbox_new(FALSE, 5); |
| |
| |
| gtk_box_pack_start(GTK_BOX(box), entry, TRUE, TRUE, 0); |
| gtk_box_pack_start(GTK_BOX(box), ok_button, FALSE, FALSE, 0); |
| |
| gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->action_area), |
| box); |
| |
| gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), label); |
| gtk_widget_show_all(dialog); |
| } |
| |
| /**************************************************************************** |
| * help_general_callback |
| ****************************************************************************/ |
| |
| static void help_general_callback(GtkToggleButton *item, gpointer data) |
| { |
| infobox("General Help", general_help); |
| } |
| |
| /**************************************************************************** |
| * help_about_callback |
| ****************************************************************************/ |
| |
| static void help_about_callback(GtkToggleButton *item, gpointer data) |
| { |
| char tmpbuf [1024]; |
| sprintf (tmpbuf, "G2 -- Graphical Event Viewer\n\n"); |
| view1_about(tmpbuf); |
| pointsel_about(tmpbuf); |
| events_about(tmpbuf); |
| sprintf (tmpbuf+strlen(tmpbuf), "\n%s\n", version_string); |
| sprintf (tmpbuf+strlen(tmpbuf), "%s\n", minor_v_string); |
| infobox("About", tmpbuf); |
| } |
| |
| |
| /**************************************************************************** |
| * get_cpel_name |
| ****************************************************************************/ |
| |
| static void get_cpel_name (GtkFileSelection *sel, gpointer user_data) |
| { |
| char *filename = (char *)gtk_file_selection_get_filename ( |
| GTK_FILE_SELECTION(s_filesel)); |
| read_cpel_file(filename); |
| set_window_title(filename); |
| } |
| |
| /**************************************************************************** |
| * get_clib_name |
| ****************************************************************************/ |
| |
| static void get_clib_name (GtkFileSelection *sel, gpointer user_data) |
| { |
| char *filename = (char *) gtk_file_selection_get_filename ( |
| GTK_FILE_SELECTION(s_filesel)); |
| read_clib_file(filename); |
| set_window_title(filename); |
| } |
| |
| /**************************************************************************** |
| * read_cpel_callback |
| ****************************************************************************/ |
| |
| static void read_cpel_callback(GtkToggleButton *item, gpointer data) |
| { |
| |
| s_filesel = gtk_file_selection_new("Read CPEL data from..."); |
| |
| gtk_file_selection_set_filename(GTK_FILE_SELECTION(s_filesel), |
| "cpel.out"); |
| |
| gtk_signal_connect (GTK_OBJECT ( |
| GTK_FILE_SELECTION(s_filesel)->ok_button), |
| "clicked", |
| GTK_SIGNAL_FUNC(get_cpel_name), NULL); |
| |
| gtk_signal_connect_object (GTK_OBJECT ( |
| GTK_FILE_SELECTION(s_filesel)->ok_button), |
| "clicked", |
| GTK_SIGNAL_FUNC (gtk_widget_destroy), |
| (gpointer) s_filesel); |
| |
| gtk_signal_connect_object (GTK_OBJECT ( |
| GTK_FILE_SELECTION(s_filesel)->cancel_button), |
| "clicked", |
| GTK_SIGNAL_FUNC (gtk_widget_destroy), |
| (gpointer) s_filesel); |
| gtk_file_selection_hide_fileop_buttons(GTK_FILE_SELECTION(s_filesel)); |
| gtk_widget_show (s_filesel); |
| } |
| |
| /**************************************************************************** |
| * read_clib_callback |
| ****************************************************************************/ |
| |
| static void read_clib_callback(GtkToggleButton *item, gpointer data) |
| { |
| |
| s_filesel = gtk_file_selection_new("Read clib data From..."); |
| |
| gtk_file_selection_set_filename(GTK_FILE_SELECTION(s_filesel), |
| "clib.out"); |
| |
| gtk_signal_connect (GTK_OBJECT ( |
| GTK_FILE_SELECTION(s_filesel)->ok_button), |
| "clicked", |
| GTK_SIGNAL_FUNC(get_clib_name), NULL); |
| |
| gtk_signal_connect_object (GTK_OBJECT ( |
| GTK_FILE_SELECTION(s_filesel)->ok_button), |
| "clicked", |
| GTK_SIGNAL_FUNC (gtk_widget_destroy), |
| (gpointer) s_filesel); |
| |
| gtk_signal_connect_object (GTK_OBJECT ( |
| GTK_FILE_SELECTION(s_filesel)->cancel_button), |
| "clicked", |
| GTK_SIGNAL_FUNC (gtk_widget_destroy), |
| (gpointer) s_filesel); |
| gtk_file_selection_hide_fileop_buttons(GTK_FILE_SELECTION(s_filesel)); |
| gtk_widget_show (s_filesel); |
| } |
| |
| /**************************************************************************** |
| * menu1_init |
| ****************************************************************************/ |
| |
| void menu1_init(void) |
| { |
| |
| s_filemenu = gtk_menu_new(); |
| |
| s_readcpel = gtk_menu_item_new_with_label |
| ("Read CPEL file"); |
| gtk_menu_append(GTK_MENU(s_filemenu), s_readcpel); |
| gtk_signal_connect(GTK_OBJECT(s_readcpel), "activate", |
| GTK_SIGNAL_FUNC(read_cpel_callback), 0); |
| |
| s_readclib = gtk_menu_item_new_with_label |
| ("Read CLIB file"); |
| gtk_menu_append(GTK_MENU(s_filemenu), s_readclib); |
| gtk_signal_connect(GTK_OBJECT(s_readclib), "activate", |
| GTK_SIGNAL_FUNC(read_clib_callback), 0); |
| |
| s_readdefs = gtk_menu_item_new_with_label ("Read Event Definitions"); |
| gtk_menu_append(GTK_MENU(s_filemenu), s_readdefs); |
| gtk_signal_connect(GTK_OBJECT(s_readdefs), "activate", |
| GTK_SIGNAL_FUNC(read_eventdef_callback), 0); |
| |
| s_readevents = gtk_menu_item_new_with_label ("Read Event Log"); |
| gtk_menu_append(GTK_MENU(s_filemenu), s_readevents); |
| gtk_signal_connect(GTK_OBJECT(s_readevents), "activate", |
| GTK_SIGNAL_FUNC(read_events_callback), 0); |
| |
| s_readeventsclock = gtk_menu_item_new_with_label |
| ("Read Event Log with Different Clock Rate"); |
| gtk_menu_append(GTK_MENU(s_filemenu), s_readeventsclock); |
| gtk_signal_connect(GTK_OBJECT(s_readeventsclock), "activate", |
| GTK_SIGNAL_FUNC(read_eventsclock_callback), 0); |
| |
| s_print = gtk_menu_item_new_with_label ("Print"); |
| gtk_menu_append(GTK_MENU(s_filemenu), s_print); |
| gtk_signal_connect(GTK_OBJECT(s_print), "activate", |
| GTK_SIGNAL_FUNC(view1_print_callback), 0); |
| |
| s_quit = gtk_menu_item_new_with_label ("Exit"); |
| gtk_menu_append(GTK_MENU(s_filemenu), s_quit); |
| gtk_signal_connect(GTK_OBJECT(s_quit), "activate", |
| GTK_SIGNAL_FUNC(gtk_main_quit), 0); |
| |
| s_mainfilemenu = gtk_menu_item_new_with_label("File"); |
| gtk_menu_item_set_submenu(GTK_MENU_ITEM(s_mainfilemenu), s_filemenu); |
| |
| s_helpmenu = gtk_menu_new(); |
| |
| s_help_general = gtk_menu_item_new_with_label ("General"); |
| gtk_menu_append(GTK_MENU(s_helpmenu), s_help_general); |
| gtk_signal_connect(GTK_OBJECT(s_help_general), "activate", |
| GTK_SIGNAL_FUNC(help_general_callback), 0); |
| |
| s_help_about = gtk_menu_item_new_with_label ("About"); |
| gtk_menu_append(GTK_MENU(s_helpmenu), s_help_about); |
| gtk_signal_connect(GTK_OBJECT(s_help_about), "activate", |
| GTK_SIGNAL_FUNC(help_about_callback), 0); |
| |
| s_mainhelpmenu = gtk_menu_item_new_with_label("Help"); |
| gtk_menu_item_set_submenu(GTK_MENU_ITEM(s_mainhelpmenu), s_helpmenu); |
| |
| s_mainmenubar = gtk_menu_bar_new(); |
| gtk_menu_bar_append(GTK_MENU_BAR(s_mainmenubar), s_mainfilemenu); |
| gtk_menu_bar_append(GTK_MENU_BAR(s_mainmenubar), s_mainhelpmenu); |
| gtk_widget_show_all(s_mainmenubar); |
| |
| gtk_box_pack_start(GTK_BOX(g_mainvbox), s_mainmenubar, FALSE, FALSE, 0); |
| } |