]> sigrok.org Git - sigrok-gtk.git/blame - toolbar.c
sr: rename all sr_hwplugin(s)_* functions to sr_hw_*
[sigrok-gtk.git] / toolbar.c
CommitLineData
3f63165c
UH
1/*
2 * This file is part of the sigrok project.
3 *
4 * Copyright (C) 2011 Gareth McMullin <gareth@blacksphere.co.nz>
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include <stdlib.h>
21
22#include <sigrok.h>
23
24#include <gtk/gtk.h>
25
26#include <stdlib.h>
27
28#include "sigrok-gtk.h"
29
30enum {
31 DEV_PROP_CAPABILITY,
32 DEV_PROP_TYPE,
33 DEV_PROP_SHORTNAME,
34 DEV_PROP_DESCRIPTION,
35 DEV_PROP_IS_TEXT,
36 DEV_PROP_TEXTVALUE,
37 DEV_PROP_BOOLVALUE,
38 MAX_DEV_PROP
39};
40
41static void prop_edited(GtkCellRendererText *cel, gchar *path, gchar *text,
42 GtkListStore *props)
43{
44 (void)cel;
45
46 struct sr_device *device = g_object_get_data(G_OBJECT(props), "device");
47 GtkTreeIter iter;
48 int type, cap;
49 guint64 tmp_u64;
50 int ret = SR_ERR;
51
52 gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(props), &iter, path);
53 gtk_tree_model_get(GTK_TREE_MODEL(props), &iter,
54 DEV_PROP_CAPABILITY, &cap,
55 DEV_PROP_TYPE, &type, -1);
56
57 switch (type) {
58 case SR_T_UINT64:
59 if (sr_parse_sizestring(text, &tmp_u64) != SR_OK)
60 return;
61
62 ret = device->plugin->set_configuration(device->plugin_index,
63 cap, &tmp_u64);
64 break;
65 case SR_T_CHAR:
66 ret = device->plugin-> set_configuration(device->plugin_index,
67 cap, text);
68 break;
69 /* SR_T_BOOL will be handled by prop_toggled */
70 }
71
72 if (!ret)
73 gtk_list_store_set(props, &iter, DEV_PROP_TEXTVALUE, text, -1);
74}
75
76static void prop_toggled(GtkCellRendererToggle *cel, gchar *path,
77 GtkListStore *props)
78{
79 struct sr_device *device = g_object_get_data(G_OBJECT(props), "device");
80 GtkTreeIter iter;
81 int type, cap;
82 int ret;
83 gboolean val;
84 gtk_tree_model_get_iter_from_string(GTK_TREE_MODEL(props), &iter, path);
85 gtk_tree_model_get(GTK_TREE_MODEL(props), &iter,
86 DEV_PROP_CAPABILITY, &cap,
87 DEV_PROP_TYPE, &type, -1);
88
89 val = !gtk_cell_renderer_toggle_get_active(cel);
90 ret = device->plugin-> set_configuration(device->plugin_index, cap,
91 GINT_TO_POINTER(val));
92
93 if (!ret)
94 gtk_list_store_set(props, &iter, DEV_PROP_BOOLVALUE, val, -1);
95}
96
97void dev_prop_bool_data_func(GtkCellLayout *cell_layout,
98 GtkCellRenderer *cell,
99 GtkTreeModel *tree_model,
100 GtkTreeIter *iter,
101 gpointer data)
102{
103 (void)cell_layout;
104 (void)data;
105
106 gboolean istext, val;
107 gtk_tree_model_get(tree_model, iter,
108 DEV_PROP_IS_TEXT, &istext,
109 DEV_PROP_BOOLVALUE, &val, -1);
110 g_object_set(G_OBJECT(cell), "visible", !istext, "active", val, NULL);
111}
112
113static void dev_set_options(GtkAction *action, GtkWindow *parent)
114{
115 (void)action;
116
117 struct sr_device *device = g_object_get_data(G_OBJECT(parent), "device");
118 if (!device)
119 return;
120
121 GtkWidget *dialog = gtk_dialog_new_with_buttons("Device Properties",
122 parent, GTK_DIALOG_MODAL,
123 GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
124 NULL);
125 GtkWidget *sw = gtk_scrolled_window_new(NULL, NULL);
126 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw),
127 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
128 gtk_widget_set_size_request(sw, 300, 200);
129 GtkWidget *tv = gtk_tree_view_new();
130 gtk_container_add(GTK_CONTAINER(sw), tv);
131 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), sw,
132 TRUE, TRUE, 0);
133
134 /* Populate list store with config options */
135 GtkListStore *props = gtk_list_store_new(MAX_DEV_PROP,
136 G_TYPE_INT, G_TYPE_INT,
137 G_TYPE_STRING, G_TYPE_STRING,
138 G_TYPE_BOOLEAN, G_TYPE_STRING,
139 G_TYPE_BOOLEAN);
140 gtk_tree_view_set_model(GTK_TREE_VIEW(tv), GTK_TREE_MODEL(props));
141 int *capabilities = device->plugin->get_capabilities();
142 int cap;
143 GtkTreeIter iter;
144 for (cap = 0; capabilities[cap]; cap++) {
145 struct sr_hwcap_option *hwo;
a9f1783a 146 if (!(hwo = sr_hw_hwcap_get(capabilities[cap])))
3f63165c
UH
147 continue;
148 gtk_list_store_append(props, &iter);
149 gtk_list_store_set(props, &iter,
150 DEV_PROP_CAPABILITY, capabilities[cap],
151 DEV_PROP_TYPE, hwo->type,
152 DEV_PROP_SHORTNAME, hwo->shortname,
153 DEV_PROP_DESCRIPTION, hwo->description,
154 DEV_PROP_IS_TEXT, hwo->type != SR_T_BOOL,
155 -1);
156 }
157
158 /* Popup tooltop containing description if mouse hovers */
159 gtk_tree_view_set_tooltip_column(GTK_TREE_VIEW(tv),
160 DEV_PROP_DESCRIPTION);
161
162 /* Save device with list so that property can be set by edited
163 * handler. */
164 g_object_set_data(G_OBJECT(props), "device", device);
165
166 /* Add columns to the tree view */
167 GtkTreeViewColumn *col;
168 col = gtk_tree_view_column_new_with_attributes("Property",
169 gtk_cell_renderer_text_new(),
170 "text", DEV_PROP_SHORTNAME, NULL);
171 gtk_tree_view_append_column(GTK_TREE_VIEW(tv), col);
172 /* We pack both a text and toggle renderer. Only one will be visible.
173 * depending on type.
174 */
175 GtkCellRenderer *cel = gtk_cell_renderer_text_new();
176 g_object_set(cel, "editable", TRUE, NULL);
177 g_signal_connect(cel, "edited", G_CALLBACK(prop_edited), props);
178 col = gtk_tree_view_column_new_with_attributes("Value",
179 cel, "text", DEV_PROP_TEXTVALUE,
180 "visible", DEV_PROP_IS_TEXT, NULL);
181 cel = gtk_cell_renderer_toggle_new();
182 g_signal_connect(cel, "toggled", G_CALLBACK(prop_toggled), props);
183 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(col), cel, TRUE);
184 gtk_cell_layout_set_cell_data_func(GTK_CELL_LAYOUT(col), cel,
185 dev_prop_bool_data_func, NULL, NULL);
186 gtk_tree_view_append_column(GTK_TREE_VIEW(tv), col);
187
188
189 gtk_widget_show_all(dialog);
190 gtk_dialog_run(GTK_DIALOG(dialog));
191
192 gtk_widget_destroy(dialog);
193}
194
195enum {
196 PROBE_NUMBER,
197 PROBE_ENABLED,
198 PROBE_NAME,
199 PROBE_TRIGGER,
200 MAX_PROBE
201};
202
203static void probe_toggled(GtkCellRenderer *cel, gchar *path,
204 GtkTreeModel *probes)
205{
206 struct sr_device *device = g_object_get_data(G_OBJECT(probes), "device");
207 GtkTreeIter iter;
208 struct sr_probe *probe;
209 gint i;
210 gboolean en;
211
212 (void)cel;
213
214 gtk_tree_model_get_iter_from_string(probes, &iter, path);
215 gtk_tree_model_get(probes, &iter, PROBE_NUMBER, &i,
216 PROBE_ENABLED, &en, -1);
91a22b68 217 probe = sr_dev_probe_find(device, i);
3f63165c
UH
218 probe->enabled = !en;
219 gtk_list_store_set(GTK_LIST_STORE(probes), &iter,
220 PROBE_ENABLED, probe->enabled, -1);
221}
222
223static void probe_named(GtkCellRendererText *cel, gchar *path, gchar *text,
224 GtkTreeModel *probes)
225{
226 struct sr_device *device = g_object_get_data(G_OBJECT(probes), "device");
227 GtkTreeIter iter;
228 gint i;
229
230 (void)cel;
231
232 gtk_tree_model_get_iter_from_string(probes, &iter, path);
233 gtk_tree_model_get(probes, &iter, PROBE_NUMBER, &i, -1);
91a22b68 234 sr_dev_probe_name(device, i, text);
3f63165c
UH
235 gtk_list_store_set(GTK_LIST_STORE(probes), &iter, PROBE_NAME, text, -1);
236}
237
238static void probe_trigger_set(GtkCellRendererText *cel, gchar *path,
239 gchar *text, GtkTreeModel *probes)
240{
241 struct sr_device *device = g_object_get_data(G_OBJECT(probes), "device");
242 GtkTreeIter iter;
243 gint i;
244
245 (void)cel;
246
247 gtk_tree_model_get_iter_from_string(probes, &iter, path);
248 gtk_tree_model_get(probes, &iter, PROBE_NUMBER, &i, -1);
91a22b68 249 sr_dev_trigger_set(device, i, text);
3f63165c
UH
250 gtk_list_store_set(GTK_LIST_STORE(probes), &iter,
251 PROBE_TRIGGER, text, -1);
252}
253
254static void dev_set_probes(GtkAction *action, GtkWindow *parent)
255{
256 (void)action;
257
258 struct sr_device *device = g_object_get_data(G_OBJECT(parent), "device");
259 if (!device)
260 return;
261
262 GtkWidget *dialog = gtk_dialog_new_with_buttons("Configure Probes",
263 parent, GTK_DIALOG_MODAL,
264 GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE,
265 NULL);
266 GtkWidget *sw = gtk_scrolled_window_new(NULL, NULL);
267 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw),
268 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
269 gtk_widget_set_size_request(sw, 300, 200);
270 GtkWidget *tv = gtk_tree_view_new();
271 gtk_container_add(GTK_CONTAINER(sw), tv);
272 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), sw,
273 TRUE, TRUE, 0);
274
275 /* Populate list store with probe options */
276 GtkListStore *probes = gtk_list_store_new(MAX_PROBE,
277 G_TYPE_INT, G_TYPE_BOOLEAN,
278 G_TYPE_STRING, GTK_TYPE_STRING);
279 gtk_tree_view_set_model(GTK_TREE_VIEW(tv), GTK_TREE_MODEL(probes));
280 GtkTreeIter iter;
281 GSList *p;
282 int i;
283 for (p = device->probes, i = 1; p; p = g_slist_next(p), i++) {
284 struct sr_probe *probe = p->data;
285 gtk_list_store_append(probes, &iter);
286 gtk_list_store_set(probes, &iter, PROBE_NUMBER, i,
287 PROBE_ENABLED, probe->enabled,
288 PROBE_NAME, probe->name,
289 PROBE_TRIGGER, probe->trigger,
290 -1);
291 }
292
293 /* Save device with list so that property can be set by edited
294 * handler. */
295 g_object_set_data(G_OBJECT(probes), "device", device);
296
297 /* Add columns to the tree view */
298 GtkTreeViewColumn *col;
299 col = gtk_tree_view_column_new_with_attributes("Probe",
300 gtk_cell_renderer_text_new(),
301 "text", PROBE_NUMBER, NULL);
302 gtk_tree_view_append_column(GTK_TREE_VIEW(tv), col);
303 GtkCellRenderer *cel = gtk_cell_renderer_toggle_new();
304 g_object_set(cel, "activatable", TRUE, NULL);
305 g_signal_connect(cel, "toggled", G_CALLBACK(probe_toggled), probes);
306 col = gtk_tree_view_column_new_with_attributes("En",
307 cel, "active", PROBE_ENABLED, NULL);
308 gtk_tree_view_append_column(GTK_TREE_VIEW(tv), col);
309 cel = gtk_cell_renderer_text_new();
310 g_object_set(cel, "editable", TRUE, NULL);
311 g_signal_connect(cel, "edited", G_CALLBACK(probe_named), probes);
312 col = gtk_tree_view_column_new_with_attributes("Signal Name", cel,
313 "text", PROBE_NAME,
314 "sensitive", PROBE_ENABLED, NULL);
315 gtk_tree_view_column_set_resizable(col, TRUE);
316 gtk_tree_view_append_column(GTK_TREE_VIEW(tv), col);
317 cel = gtk_cell_renderer_text_new();
318 g_object_set(cel, "editable", TRUE, NULL);
319 g_signal_connect(cel, "edited", G_CALLBACK(probe_trigger_set), probes);
320 col = gtk_tree_view_column_new_with_attributes("Trigger", cel,
321 "text", PROBE_TRIGGER,
322 "sensitive", PROBE_ENABLED, NULL);
323 gtk_tree_view_append_column(GTK_TREE_VIEW(tv), col);
324
325 gtk_widget_show_all(dialog);
326 gtk_dialog_run(GTK_DIALOG(dialog));
327
328 gtk_widget_destroy(dialog);
329}
330
331static void capture_run(GtkAction *action, GObject *parent)
332{
333 (void)action;
334
335 struct sr_device *device = g_object_get_data(G_OBJECT(parent), "device");
336 GtkEntry *timesamples = g_object_get_data(parent, "timesamples");
337 GtkComboBox *timeunit = g_object_get_data(parent, "timeunit");
338 gint i = gtk_combo_box_get_active(timeunit);
339 guint64 time_msec = 0;
340 guint64 limit_samples = 0;
341
342 switch (i) {
343 case 0: /* Samples */
344 sr_parse_sizestring(gtk_entry_get_text(timesamples),
345 &limit_samples);
346 break;
347 case 1: /* Milliseconds */
348 time_msec = strtoull(gtk_entry_get_text(timesamples), NULL, 10);
349 break;
350 case 2: /* Seconds */
351 time_msec = strtoull(gtk_entry_get_text(timesamples), NULL, 10)
352 * 1000;
353 break;
354 }
355
356 if (time_msec) {
a9f1783a 357 if (sr_hw_has_hwcap(device->plugin, SR_HWCAP_LIMIT_MSEC)) {
3f63165c
UH
358 if (device->plugin->set_configuration(device->plugin_index,
359 SR_HWCAP_LIMIT_MSEC,
360 &time_msec) != SR_OK) {
361 g_critical("Failed to configure time limit.");
362 sr_session_destroy();
363 return;
364 }
365 } else {
366 /* time limit set, but device doesn't support this...
367 * convert to samples based on the samplerate.
368 */
369 limit_samples = 0;
91a22b68 370 if (sr_dev_has_hwcap(device, SR_HWCAP_SAMPLERATE)) {
3f63165c
UH
371 guint64 tmp_u64;
372 tmp_u64 = *((uint64_t *) device->plugin->get_device_info(
373 device->plugin_index,
374 SR_DI_CUR_SAMPLERATE));
375 limit_samples = tmp_u64 * time_msec / (uint64_t) 1000;
376 }
377 if (limit_samples == 0) {
378 g_critical("Not enough time at this samplerate.");
379 return;
380 }
381
382 if (device->plugin->set_configuration(device->plugin_index,
383 SR_HWCAP_LIMIT_SAMPLES,
384 &limit_samples) != SR_OK) {
385 g_critical("Failed to configure time-based sample limit.");
386 return;
387 }
388 }
389 }
390 if (limit_samples) {
391 if (device->plugin->set_configuration(device->plugin_index,
392 SR_HWCAP_LIMIT_SAMPLES,
393 &limit_samples) != SR_OK) {
394 g_critical("Failed to configure sample limit.");
395 return;
396 }
397 }
398
399 if (device->plugin->set_configuration(device->plugin_index,
400 SR_HWCAP_PROBECONFIG, (char *)device->probes) != SR_OK) {
401 printf("Failed to configure probes.\n");
402 sr_session_destroy();
403 return;
404 }
405
406 if (sr_session_start() != SR_OK) {
407 g_critical("Failed to start session.");
408 return;
409 }
410
411 sr_session_run();
412}
413
414static void dev_file_open(GtkAction *action, GtkWindow *parent)
415{
416 (void)action;
417 static GtkWidget *dialog;
418 const gchar *filename;
419
420 if(!dialog)
421 dialog = gtk_file_chooser_dialog_new("Open", parent,
422 GTK_FILE_CHOOSER_ACTION_OPEN,
423 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
424 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL);
425 g_signal_connect(dialog, "delete-event",
426 G_CALLBACK(gtk_widget_hide_on_delete),
427 NULL);
428
429 if (gtk_dialog_run(GTK_DIALOG(dialog)) != GTK_RESPONSE_ACCEPT) {
430 /* Dialog was cancelled or closed */
431 gtk_widget_hide(dialog);
432 return;
433 }
434
435 gtk_widget_hide(dialog);
436
437 filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
438 load_input_file(parent, filename);
439}
440
441void toggle_log(GtkToggleAction *action, GObject *parent)
442{
443 GtkWidget *log = g_object_get_data(parent, "logview");
444 gtk_widget_set_visible(log, gtk_toggle_action_get_active(action));
445}
446
447void zoom_in(GtkAction *action, GObject *parent)
448{
449 (void)action;
450
451 GtkWidget *sigview = g_object_get_data(parent, "sigview");
452 sigview_zoom(sigview, 1.5, 0);
453}
454
455void zoom_out(GtkAction *action, GObject *parent)
456{
457 (void)action;
458
459 GtkWidget *sigview = g_object_get_data(parent, "sigview");
460 sigview_zoom(sigview, 1/1.5, 0);
461}
462
463void zoom_fit(GtkAction *action, GObject *parent)
464{
465 (void)action;
466
467 GtkWidget *sigview = g_object_get_data(parent, "sigview");
468 sigview_zoom(sigview, 0, 0);
469}
470
471static const GtkActionEntry action_items[] = {
472 /* name, stock-id, label, accel, tooltip, callback */
473 {"DevMenu", NULL, "_Device", NULL, NULL, NULL},
474 {"DevOpen", GTK_STOCK_OPEN, "_Open", "<control>O",
475 "Open Session File", G_CALLBACK(dev_file_open)},
476 {"DevSelectMenu", NULL, "Select Device", NULL, NULL, NULL},
477 {"DevRescan", GTK_STOCK_REFRESH, "_Rescan", "<control>R",
478 "Rescan for LA devices", G_CALLBACK(dev_select_rescan)},
479 {"DevProperties", GTK_STOCK_PROPERTIES, "_Properties", "<control>P",
480 "Configure LA", G_CALLBACK(dev_set_options)},
481 {"DevProbes", GTK_STOCK_COLOR_PICKER, "_Probes", "<control>O",
482 "Configure Probes", G_CALLBACK(dev_set_probes)},
483 {"DevAcquire", GTK_STOCK_EXECUTE, "_Acquire", "<control>A",
484 "Acquire Samples", G_CALLBACK(capture_run)},
485 {"Exit", GTK_STOCK_QUIT, "E_xit", "<control>Q",
486 "Exit the program", G_CALLBACK(gtk_main_quit) },
487
488 {"ViewMenu", NULL, "_View", NULL, NULL, NULL},
489 {"ViewZoomIn", GTK_STOCK_ZOOM_IN, "Zoom _In", "<control>z", NULL,
490 G_CALLBACK(zoom_in)},
491 {"ViewZoomOut", GTK_STOCK_ZOOM_OUT, "Zoom _Out", "<control><shift>Z",
492 NULL, G_CALLBACK(zoom_out)},
493 {"ViewZoomFit", GTK_STOCK_ZOOM_FIT, NULL, NULL,
494 NULL, G_CALLBACK(zoom_fit)},
495
496 {"HelpMenu", NULL, "_Help", NULL, NULL, NULL},
497 {"HelpWiki", GTK_STOCK_ABOUT, "Sigrok _Wiki", NULL, NULL,
498 G_CALLBACK(help_wiki)},
499 {"HelpAbout", GTK_STOCK_ABOUT, "_About", NULL, NULL,
500 G_CALLBACK(help_about)},
501};
502
503static const GtkToggleActionEntry toggle_items[] = {
504 /* name, stock-id, label, accel, tooltip, callback, isactive */
505 {"ViewLog", GTK_STOCK_JUSTIFY_LEFT, "_Log", NULL, NULL,
506 G_CALLBACK(toggle_log), FALSE},
507};
508
509static const char ui_xml[] =
510"<ui>"
511" <menubar>"
512" <menu action='DevMenu'>"
513" <menuitem action='DevOpen'/>"
514" <separator/>"
515" <menu action='DevSelectMenu'>"
516" <separator/>"
517" <menuitem action='DevRescan'/>"
518" </menu>"
519" <menuitem action='DevProperties'/>"
520" <menuitem action='DevProbes'/>"
521" <separator/>"
522" <menuitem action='DevAcquire'/>"
523" <separator/>"
524" <menuitem action='Exit'/>"
525" </menu>"
526" <menu action='ViewMenu'>"
527" <menuitem action='ViewZoomIn'/>"
528" <menuitem action='ViewZoomOut'/>"
529" <menuitem action='ViewZoomFit'/>"
530" <separator/>"
531" <menuitem action='ViewLog'/>"
532" </menu>"
533" <menu action='HelpMenu'>"
534" <menuitem action='HelpWiki'/>"
535" <menuitem action='HelpAbout'/>"
536" </menu>"
537" </menubar>"
538" <toolbar>"
539" <placeholder name='DevSelect'/>"
540" <toolitem action='DevRescan'/>"
541" <toolitem action='DevProperties'/>"
542" <toolitem action='DevProbes'/>"
543" <separator/>"
544" <placeholder name='DevSampleCount' />"
545" <toolitem action='DevAcquire'/>"
546" <separator/>"
547" <toolitem action='ViewZoomIn'/>"
548" <toolitem action='ViewZoomOut'/>"
549" <toolitem action='ViewZoomFit'/>"
550" <separator/>"
551" </toolbar>"
552"</ui>";
553
554GtkWidget *toolbar_init(GtkWindow *parent)
555{
556 GtkWidget *vbox = gtk_vbox_new(FALSE, 0);
557 GtkToolbar *toolbar;
558 GtkActionGroup *ag = gtk_action_group_new("Actions");
559 gtk_action_group_add_actions(ag, action_items,
560 G_N_ELEMENTS(action_items), parent);
561 gtk_action_group_add_toggle_actions(ag, toggle_items,
562 G_N_ELEMENTS(toggle_items), parent);
563
564 GtkUIManager *ui = gtk_ui_manager_new();
565 g_object_set_data(G_OBJECT(parent), "ui_manager", ui);
566 gtk_ui_manager_insert_action_group(ui, ag, 0);
567 GtkAccelGroup *accel = gtk_ui_manager_get_accel_group(ui);
568 gtk_window_add_accel_group(parent, accel);
569
570 GError *error = NULL;
571 if (!gtk_ui_manager_add_ui_from_string (ui, ui_xml, -1, &error)) {
572 g_message ("building menus failed: %s", error->message);
573 g_error_free (error);
574 exit (-1);
575 }
576
577 GtkWidget *menubar = gtk_ui_manager_get_widget(ui, "/menubar");
578 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(menubar), FALSE, TRUE, 0);
579 toolbar = GTK_TOOLBAR(gtk_ui_manager_get_widget(ui, "/toolbar"));
580 gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(toolbar), FALSE, TRUE, 0);
581
582 /* Device selection GtkComboBox */
583 GtkToolItem *toolitem = gtk_tool_item_new();
584 GtkWidget *align = gtk_alignment_new(0.5, 0.5, 2, 0);
585 GtkWidget *dev = dev_select_combo_box_new(parent);
586
587 gtk_container_add(GTK_CONTAINER(align), dev);
588 gtk_container_add(GTK_CONTAINER(toolitem), align);
589 gtk_toolbar_insert(toolbar, toolitem, 0);
590
591 /* Time/Samples entry */
592 toolitem = gtk_tool_item_new();
593 GtkWidget *timesamples = gtk_entry_new();
594 gtk_entry_set_text(GTK_ENTRY(timesamples), "100");
595 gtk_entry_set_alignment(GTK_ENTRY(timesamples), 1.0);
596 gtk_widget_set_size_request(timesamples, 100, -1);
597 gtk_container_add(GTK_CONTAINER(toolitem), timesamples);
598 gtk_toolbar_insert(toolbar, toolitem, 7);
599
600 /* Time unit combo box */
601 toolitem = gtk_tool_item_new();
602 align = gtk_alignment_new(0.5, 0.5, 2, 0);
603 GtkWidget *timeunit = gtk_combo_box_new_text();
604 gtk_combo_box_append_text(GTK_COMBO_BOX(timeunit), "samples");
605 gtk_combo_box_append_text(GTK_COMBO_BOX(timeunit), "ms");
606 gtk_combo_box_append_text(GTK_COMBO_BOX(timeunit), "s");
607 gtk_combo_box_set_active(GTK_COMBO_BOX(timeunit), 0);
608 gtk_container_add(GTK_CONTAINER(align), timeunit);
609 gtk_container_add(GTK_CONTAINER(toolitem), align);
610 gtk_toolbar_insert(toolbar, toolitem, 8);
611
612 g_object_set_data(G_OBJECT(parent), "timesamples", timesamples);
613 g_object_set_data(G_OBJECT(parent), "timeunit", timeunit);
614
615 return GTK_WIDGET(vbox);
616}
617