dpdk: Add support for Mellanox ConnectX-4 devices
[vpp.git] / src / tools / g2 / menu1.c
1 /* 
2  *------------------------------------------------------------------
3  * Copyright (c) 2006-2016 Cisco and/or its affiliates.
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <stdio.h>
18 #include <gtk/gtk.h>
19 #define GTK_ENABLE_BROKEN // DGMS
20 #include <gtk/gtktext.h>
21 #include <stdlib.h>
22 #include "g2.h"
23 #include <string.h>
24
25 /*
26  * locals
27  */
28 static GtkWidget *s_mainmenubar;
29 static GtkWidget *s_filemenu;
30 static GtkWidget *s_readdefs;
31 static GtkWidget *s_readevents;
32 static GtkWidget *s_readeventsclock;
33 static GtkWidget *s_readcpel;
34 static GtkWidget *s_readclib;
35 static GtkWidget *s_print;
36 static GtkWidget *s_quit;
37
38 static GtkWidget *s_mainfilemenu;
39 static GtkWidget *s_help_general;
40 static GtkWidget *s_help_about;
41 static GtkWidget *s_mainhelpmenu;
42 static GtkWidget *s_helpmenu;
43
44 static GtkWidget *s_filesel;
45 static GtkWidget *s_eventsel;
46
47 typedef struct md_ {
48     GtkWidget *entry;
49     GtkWidget *label;
50     GtkWidget *dialog;
51     boolean (*callback)(char *);
52     char *retry_text;
53 } md_t;
54
55 char *general_help = "\n"
56 "G2 is a performance event visualization tool.\n"
57 "\n"
58 "To view CPEL-format event data:\n"
59 "g2 --cpel <filename>\n"
60 "or use the File Menu->Read CPEL file option.\n"
61 "\n"
62 "To view vppinfra-format (.../open-repo/vppinfra/vppinfra/elog.h) event data:\n"
63 "g2 --clib <filename>\n"
64 "or use the File Menu->Read clib file option.\n"
65 "\n"
66 "To toggle event detail boxes, left-mouse-click on an event.\n"
67 "\n"
68 "To zoom to an area, depress the left mouse button. Move the\n"
69 "mouse. Release the mouse.\n"
70 "\n"
71 "To use the time ruler, depress the right mouse button.  Move the\n"
72 "mouse. Release when done.\n"
73 "\n"
74 "To push a track to the bottom, <ctrl><left-mouse>\n"
75 "\n"
76 "To pull a track to the top, <shift><left-mouse>\n"
77 "\n"
78 "To selectively color/uncolor a track, <ctrl><shift><left-mouse>\n"
79 "\n"
80 "To make the mouse scrollwheel faster, press <shift>\n"
81 "\n"
82 "Hotkeys, supposedly Quake-like:\n"
83 "      w - zoom-in\n"
84 "      s - zoom-out\n"
85 "      a - pan-left\n"
86 "      d - pan-right\n"
87 "      r - pan-up\n"
88 "      f - pan-down\n"
89 "      t - less traces\n"
90 "      g - more traces\n"
91 "\n"
92 "      e - toggle summary-mode\n"
93 "      c - toggle color-mode\n"
94 "\n"
95 "      x - take snapshot\n"
96 "      z - go to next snapshot\n"
97 "      p - put snapshots to snapshots.g2 \n"
98 "      l - load snapshots from snapshots.g2\n"
99 "\n"
100 "<ctrl>q - quit\n"
101 "Send comments / bug reports to the \"fd.io\" mailing list.\n";
102
103 /****************************************************************************
104 * debug_dialog_callback
105 ****************************************************************************/
106
107 boolean debug_dialog_callback (char *s)
108 {
109     g_print("Dialog result: %s", s);
110     return (TRUE);
111 }
112
113 /****************************************************************************
114 * get_dialog_value
115 ****************************************************************************/
116
117 static void get_dialog_value (GtkWidget *dialog, gpointer user_data)
118 {
119     md_t *md = (md_t *)user_data;
120     char * cb_arg;
121     
122     cb_arg = (char *) gtk_entry_get_text(GTK_ENTRY(md->entry));
123
124     if ((*md->callback)(cb_arg)) {
125         gtk_grab_remove(md->dialog);
126         gtk_widget_destroy(md->dialog);
127     } else {
128         gtk_label_set_text (GTK_LABEL(md->label), md->retry_text);
129     }
130 }
131
132 /****************************************************************************
133 * modal_dialog
134 ****************************************************************************/
135
136 void modal_dialog (char *label_text, char *retry_text, char *default_value, 
137                    boolean (*cb)(char *))
138 {
139     GtkWidget *dialog, *label, *ok_button, *entry;
140     static md_t dlg;
141     md_t *md = &dlg;
142
143     dialog = gtk_dialog_new();
144     label = gtk_label_new(label_text);
145
146     entry = gtk_entry_new();
147     if (default_value)
148         gtk_entry_set_text(GTK_ENTRY(entry), default_value);
149
150     ok_button = gtk_button_new_with_label("OK");
151
152     md->entry = entry;
153     md->label = label;
154     md->retry_text = retry_text;
155     md->dialog = dialog;
156     if (cb)
157         md->callback = cb;
158     else
159         md->callback = debug_dialog_callback;
160
161     gtk_signal_connect (GTK_OBJECT (ok_button), "clicked", 
162                         GTK_SIGNAL_FUNC(get_dialog_value), (gpointer) md);
163
164     gtk_signal_connect (GTK_OBJECT (entry), "activate", 
165                         GTK_SIGNAL_FUNC(get_dialog_value), (gpointer) md);
166
167     gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->action_area),
168                       entry);
169
170     gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->action_area),
171                       ok_button);
172     gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), label);
173     gtk_widget_show_all(dialog);
174     gtk_widget_grab_focus(entry);
175     gtk_grab_add(dialog);
176 }
177
178 /****************************************************************************
179 * get_eventdef_name
180 ****************************************************************************/
181
182 static void get_eventdef_name (GtkFileSelection *sel, gpointer user_data)
183 {
184     char *filename = (char *) gtk_file_selection_get_filename (
185         GTK_FILE_SELECTION(s_filesel));
186     read_event_definitions(filename);
187     set_window_title(filename);
188 }
189
190 /****************************************************************************
191 * read_eventdef_callback
192 ****************************************************************************/
193
194 static void read_eventdef_callback(GtkToggleButton *item, gpointer data)
195 {
196     
197     s_filesel = gtk_file_selection_new("Read Event Definitions From...");
198     
199     gtk_file_selection_set_filename(GTK_FILE_SELECTION(s_filesel), 
200                                     "../h/elog.h");
201
202     gtk_signal_connect (GTK_OBJECT (
203         GTK_FILE_SELECTION(s_filesel)->ok_button),
204                         "clicked", 
205                         GTK_SIGNAL_FUNC(get_eventdef_name), NULL);
206                             
207     gtk_signal_connect_object (GTK_OBJECT (
208         GTK_FILE_SELECTION(s_filesel)->ok_button),
209                                "clicked", 
210                                GTK_SIGNAL_FUNC (gtk_widget_destroy),
211                                (gpointer) s_filesel);
212     
213     gtk_signal_connect_object (GTK_OBJECT (
214         GTK_FILE_SELECTION(s_filesel)->cancel_button),
215                                "clicked", 
216                                GTK_SIGNAL_FUNC (gtk_widget_destroy),
217                                (gpointer) s_filesel);
218     gtk_file_selection_hide_fileop_buttons(GTK_FILE_SELECTION(s_filesel));
219     gtk_widget_show (s_filesel);
220 }
221
222 /****************************************************************************
223 * get_events_name
224 ****************************************************************************/
225
226 static void get_events_name (GtkFileSelection *sel, gpointer user_data)
227 {
228     char *filename = (char *) gtk_file_selection_get_filename (
229         GTK_FILE_SELECTION(s_eventsel));
230     read_events(filename);
231     view1_display_when_idle();
232 }
233
234
235 /****************************************************************************
236 * get_ticks_per_ns
237 ****************************************************************************/
238
239 static boolean get_ticks_per_ns (char *value)
240 {
241     double rv;
242
243     rv = atof (value);
244
245     if (rv == 0.0 || rv > 100000)
246         return(FALSE);
247
248     ticks_per_ns = rv;
249     ticks_per_ns_set = TRUE;
250
251     gtk_widget_show(s_eventsel);
252     return(TRUE);
253 }
254
255 /****************************************************************************
256 * read_events_callback
257 ****************************************************************************/
258
259 static void read_events_callback(GtkToggleButton *item, gpointer data)
260 {
261     char tmpbuf [32];
262
263     s_eventsel = gtk_file_selection_new("Read Events From...");
264     
265     gtk_signal_connect (GTK_OBJECT (
266         GTK_FILE_SELECTION(s_eventsel)->ok_button),
267                         "clicked", 
268                         GTK_SIGNAL_FUNC(get_events_name), NULL);
269                             
270     gtk_signal_connect_object (GTK_OBJECT (
271         GTK_FILE_SELECTION(s_eventsel)->ok_button),
272                                "clicked", 
273                                GTK_SIGNAL_FUNC (gtk_widget_destroy),
274                                (gpointer) s_eventsel);
275     
276     gtk_signal_connect_object (GTK_OBJECT (
277         GTK_FILE_SELECTION(s_eventsel)->cancel_button),
278                                "clicked", 
279                                GTK_SIGNAL_FUNC (gtk_widget_destroy),
280                                (gpointer) s_eventsel);
281     gtk_file_selection_hide_fileop_buttons(GTK_FILE_SELECTION(s_eventsel));
282
283     if (ticks_per_ns_set)
284         gtk_widget_show (s_eventsel);
285     else {
286         sprintf(tmpbuf, "%.3f", ticks_per_ns);
287         modal_dialog ("Please enter clock ticks per nanosecond",
288                       "Invalid: Please enter clock ticks per nanosecond",
289                       tmpbuf, get_ticks_per_ns);
290     }
291 }
292
293 /****************************************************************************
294 * read_eventclock_callback
295 ****************************************************************************/
296
297 static void read_eventsclock_callback(GtkToggleButton *item, gpointer data)
298 {
299     ticks_per_ns_set = FALSE;
300     read_events_callback(item, data);
301 }
302
303 /****************************************************************************
304 * infobox_size_request
305 ****************************************************************************/
306
307 void infobox_size_request (GtkWidget *widget, GtkRequisition *req,
308                            gpointer user_data)
309 {
310     char *text = (char *)user_data;
311     char *cp;
312     int widest_line_in_chars;
313     int w;
314     int nlines;
315     
316     /*
317      * You'd think that the string extent function would work here.
318      * You'd be wrong. 
319      */
320     nlines = w = widest_line_in_chars = 0;
321     for (cp = text; *cp; cp++) {
322         if (*cp == '\n') {
323             if (w > widest_line_in_chars) {
324                 widest_line_in_chars = w;
325             }
326             w = 0;
327             nlines++;
328         }
329         w++;
330     }
331
332     nlines++;
333
334     req->width = (widest_line_in_chars * 8) + 20;
335     req->height = (nlines * 13) + 10;
336 }
337
338 /****************************************************************************
339 * infobox
340 ****************************************************************************/
341
342 void infobox(char *label_text, char *text)
343 {
344     GtkWidget *dialog, *label, *ok_button, *entry;
345     GtkWidget *box;
346
347     dialog = gtk_dialog_new();
348     label = gtk_label_new(label_text);
349
350     entry = gtk_text_new(NULL, NULL);
351
352     gtk_signal_connect (GTK_OBJECT (entry), "size-request", 
353                         GTK_SIGNAL_FUNC(infobox_size_request), 
354                         (gpointer) text);
355
356     gtk_text_insert(GTK_TEXT(entry), g_font, &fg_black, &bg_white,
357                     text, -1);
358
359     gtk_text_set_editable(GTK_TEXT(entry), FALSE);
360
361     ok_button = gtk_button_new_with_label("OK");
362
363     gtk_signal_connect_object (GTK_OBJECT (ok_button), "clicked", 
364                                GTK_SIGNAL_FUNC(gtk_widget_destroy), 
365                                (gpointer) GTK_OBJECT(dialog));
366
367     box = gtk_vbox_new(FALSE, 5);
368
369
370     gtk_box_pack_start(GTK_BOX(box), entry, TRUE, TRUE, 0);
371     gtk_box_pack_start(GTK_BOX(box), ok_button, FALSE, FALSE, 0);
372
373     gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->action_area),
374                       box);
375
376     gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), label);
377     gtk_widget_show_all(dialog);
378 }
379
380 /****************************************************************************
381 * help_general_callback
382 ****************************************************************************/
383
384 static void help_general_callback(GtkToggleButton *item, gpointer data)
385 {
386     infobox("General Help", general_help);
387 }
388
389 /****************************************************************************
390 * help_about_callback
391 ****************************************************************************/
392
393 static void help_about_callback(GtkToggleButton *item, gpointer data)
394 {
395     char tmpbuf [1024];
396     sprintf (tmpbuf, "G2 -- Graphical Event Viewer\n\n");
397     view1_about(tmpbuf);
398     pointsel_about(tmpbuf);
399     events_about(tmpbuf);
400     sprintf (tmpbuf+strlen(tmpbuf), "\n%s\n", version_string);
401     sprintf (tmpbuf+strlen(tmpbuf), "%s\n", minor_v_string);
402     infobox("About", tmpbuf);
403 }
404
405
406 /****************************************************************************
407 * get_cpel_name
408 ****************************************************************************/
409
410 static void get_cpel_name (GtkFileSelection *sel, gpointer user_data)
411 {
412     char *filename = (char *)gtk_file_selection_get_filename (
413         GTK_FILE_SELECTION(s_filesel));
414     read_cpel_file(filename);
415     set_window_title(filename);
416 }
417
418 /****************************************************************************
419 * get_clib_name
420 ****************************************************************************/
421
422 static void get_clib_name (GtkFileSelection *sel, gpointer user_data)
423 {
424     char *filename = (char *) gtk_file_selection_get_filename (
425         GTK_FILE_SELECTION(s_filesel));
426     read_clib_file(filename);
427     set_window_title(filename);
428 }
429
430 /****************************************************************************
431 * read_cpel_callback
432 ****************************************************************************/
433
434 static void read_cpel_callback(GtkToggleButton *item, gpointer data)
435 {
436     
437     s_filesel = gtk_file_selection_new("Read CPEL data from...");
438     
439     gtk_file_selection_set_filename(GTK_FILE_SELECTION(s_filesel), 
440                                     "cpel.out");
441
442     gtk_signal_connect (GTK_OBJECT (
443         GTK_FILE_SELECTION(s_filesel)->ok_button),
444                         "clicked", 
445                         GTK_SIGNAL_FUNC(get_cpel_name), NULL);
446                             
447     gtk_signal_connect_object (GTK_OBJECT (
448         GTK_FILE_SELECTION(s_filesel)->ok_button),
449                                "clicked", 
450                                GTK_SIGNAL_FUNC (gtk_widget_destroy),
451                                (gpointer) s_filesel);
452     
453     gtk_signal_connect_object (GTK_OBJECT (
454         GTK_FILE_SELECTION(s_filesel)->cancel_button),
455                                "clicked", 
456                                GTK_SIGNAL_FUNC (gtk_widget_destroy),
457                                (gpointer) s_filesel);
458     gtk_file_selection_hide_fileop_buttons(GTK_FILE_SELECTION(s_filesel));
459     gtk_widget_show (s_filesel);
460 }
461
462 /****************************************************************************
463 * read_clib_callback
464 ****************************************************************************/
465
466 static void read_clib_callback(GtkToggleButton *item, gpointer data)
467 {
468     
469     s_filesel = gtk_file_selection_new("Read clib data From...");
470     
471     gtk_file_selection_set_filename(GTK_FILE_SELECTION(s_filesel), 
472                                     "clib.out");
473
474     gtk_signal_connect (GTK_OBJECT (
475         GTK_FILE_SELECTION(s_filesel)->ok_button),
476                         "clicked", 
477                         GTK_SIGNAL_FUNC(get_clib_name), NULL);
478                             
479     gtk_signal_connect_object (GTK_OBJECT (
480         GTK_FILE_SELECTION(s_filesel)->ok_button),
481                                "clicked", 
482                                GTK_SIGNAL_FUNC (gtk_widget_destroy),
483                                (gpointer) s_filesel);
484     
485     gtk_signal_connect_object (GTK_OBJECT (
486         GTK_FILE_SELECTION(s_filesel)->cancel_button),
487                                "clicked", 
488                                GTK_SIGNAL_FUNC (gtk_widget_destroy),
489                                (gpointer) s_filesel);
490     gtk_file_selection_hide_fileop_buttons(GTK_FILE_SELECTION(s_filesel));
491     gtk_widget_show (s_filesel);
492 }
493
494 /****************************************************************************
495 * menu1_init
496 ****************************************************************************/
497
498 void menu1_init(void)
499 {
500
501     s_filemenu = gtk_menu_new();
502
503     s_readcpel = gtk_menu_item_new_with_label 
504         ("Read CPEL file");
505     gtk_menu_append(GTK_MENU(s_filemenu), s_readcpel);
506     gtk_signal_connect(GTK_OBJECT(s_readcpel), "activate", 
507                        GTK_SIGNAL_FUNC(read_cpel_callback), 0);
508
509     s_readclib = gtk_menu_item_new_with_label 
510         ("Read CLIB file");
511     gtk_menu_append(GTK_MENU(s_filemenu), s_readclib);
512     gtk_signal_connect(GTK_OBJECT(s_readclib), "activate", 
513                        GTK_SIGNAL_FUNC(read_clib_callback), 0);
514     
515     s_readdefs = gtk_menu_item_new_with_label ("Read Event Definitions");
516     gtk_menu_append(GTK_MENU(s_filemenu), s_readdefs);
517     gtk_signal_connect(GTK_OBJECT(s_readdefs), "activate", 
518                        GTK_SIGNAL_FUNC(read_eventdef_callback), 0);
519     
520     s_readevents = gtk_menu_item_new_with_label ("Read Event Log");
521     gtk_menu_append(GTK_MENU(s_filemenu), s_readevents);
522     gtk_signal_connect(GTK_OBJECT(s_readevents), "activate", 
523                        GTK_SIGNAL_FUNC(read_events_callback), 0);
524     
525     s_readeventsclock = gtk_menu_item_new_with_label 
526         ("Read Event Log with Different Clock Rate");
527     gtk_menu_append(GTK_MENU(s_filemenu), s_readeventsclock);
528     gtk_signal_connect(GTK_OBJECT(s_readeventsclock), "activate", 
529                        GTK_SIGNAL_FUNC(read_eventsclock_callback), 0);
530
531     s_print = gtk_menu_item_new_with_label ("Print");
532     gtk_menu_append(GTK_MENU(s_filemenu), s_print);
533     gtk_signal_connect(GTK_OBJECT(s_print), "activate", 
534                        GTK_SIGNAL_FUNC(view1_print_callback), 0);
535     
536     s_quit = gtk_menu_item_new_with_label ("Exit");
537     gtk_menu_append(GTK_MENU(s_filemenu), s_quit);
538     gtk_signal_connect(GTK_OBJECT(s_quit), "activate", 
539                        GTK_SIGNAL_FUNC(gtk_main_quit), 0);
540
541     s_mainfilemenu = gtk_menu_item_new_with_label("File");
542     gtk_menu_item_set_submenu(GTK_MENU_ITEM(s_mainfilemenu), s_filemenu);
543
544     s_helpmenu = gtk_menu_new();
545
546     s_help_general = gtk_menu_item_new_with_label ("General");
547     gtk_menu_append(GTK_MENU(s_helpmenu), s_help_general);
548     gtk_signal_connect(GTK_OBJECT(s_help_general), "activate", 
549                        GTK_SIGNAL_FUNC(help_general_callback), 0);
550
551     s_help_about = gtk_menu_item_new_with_label ("About");
552     gtk_menu_append(GTK_MENU(s_helpmenu), s_help_about);
553     gtk_signal_connect(GTK_OBJECT(s_help_about), "activate", 
554                        GTK_SIGNAL_FUNC(help_about_callback), 0);
555
556     s_mainhelpmenu = gtk_menu_item_new_with_label("Help");
557     gtk_menu_item_set_submenu(GTK_MENU_ITEM(s_mainhelpmenu), s_helpmenu);
558
559     s_mainmenubar = gtk_menu_bar_new();
560     gtk_menu_bar_append(GTK_MENU_BAR(s_mainmenubar), s_mainfilemenu);
561     gtk_menu_bar_append(GTK_MENU_BAR(s_mainmenubar), s_mainhelpmenu);
562     gtk_widget_show_all(s_mainmenubar);
563
564     gtk_box_pack_start(GTK_BOX(g_mainvbox), s_mainmenubar, FALSE, FALSE, 0);
565 }