diff options
Diffstat (limited to 'devices.c')
-rw-r--r-- | devices.c | 136 |
1 files changed, 136 insertions, 0 deletions
diff --git a/devices.c b/devices.c new file mode 100644 index 0000000..07de700 --- /dev/null +++ b/devices.c @@ -0,0 +1,136 @@ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <errno.h> + +#include <gtk/gtk.h> + +#include "qemu-gtk.h" + +/* ----------------------------------------------------------------- */ + +static char mc_xml_start[] = +"<ui>\n" +" <menubar name='MainMenu'>\n" +" <menu action='DevicesMenu'>\n" +" <menu action='MediaChangeSubMenu'>\n"; + +static char mc_xml_end[] = +" </menu>\n" +" </menu>\n" +" </menubar>\n" +"</ui>\n"; + +/* ----------------------------------------------------------------- */ + +static void menu_cb_change_media(GtkAction *action, void *data) +{ + struct qemu_window *win = data; + GtkWidget *dialog; + char *filename; + char name[32], title[128], cmd[128]; + + if (1 != sscanf(gtk_action_get_name(action), "ChangeMedia_%31s", name)) + return; + if (debug) + fprintf(stderr, "%s: %s\n", __FUNCTION__, name); + + snprintf(title, sizeof(title), "Pick image file for %s", name); + dialog = gtk_file_chooser_dialog_new (title, GTK_WINDOW(win->toplevel), + GTK_FILE_CHOOSER_ACTION_OPEN, + GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, + GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, + NULL); + + if (gtk_dialog_run(GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT) { + filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)); + if (debug) + fprintf(stderr, "%s: %s\n", __FUNCTION__, filename); +#if 0 + /* not required it seems */ + snprintf(cmd, sizeof(cmd), "eject %s", name); + monitor_append(win, cmd); +#endif + snprintf(cmd, sizeof(cmd), "change %s %s", name, filename); + monitor_append(win, cmd); + monitor_append(win, "info block"); + g_free (filename); + } + gtk_widget_destroy(dialog); +} + +void devices_parse_info_block(struct qemu_window *win, char *str) +{ + char name[32], type[16], line[256], *file, *ptr; + char action[128], label[128]; + int removable, pos, xpos, len, rc; + GtkActionEntry entry; + GError *err = NULL; + char *xml; + + /* remove */ + if (win->mc_id) { + gtk_ui_manager_remove_ui(win->ui, win->mc_id); + win->mc_id = 0; + } + if (win->mc_ag) { + gtk_ui_manager_remove_action_group(win->ui, win->mc_ag); + g_object_unref(win->mc_ag); + win->mc_ag = NULL; + } + + /* start */ + memset(&entry, 0, sizeof(entry)); + entry.callback = G_CALLBACK(menu_cb_change_media); + win->mc_ag = gtk_action_group_new("ChangeMediaActions"); + + xpos = 0; xml = malloc(strlen(mc_xml_start)+1); + xpos += sprintf(xml+xpos, "%s", mc_xml_start); + + /* parse & build */ + for (pos = 0;; pos += len) { + rc = sscanf(str+pos, "%31[^:]: type=%15s removable=%d %255[^\r\n]%n", + name, type, &removable, line, &len); + if (rc != 4) + break; + while (str[pos+len] == '\r' || str[pos+len] == '\n') + len++; + if (!removable) + continue; + file = strstr(line, "file="); + if (file) { + file += 5; + ptr = strchr(file, ' '); + if (ptr) + *ptr = 0; + } else { + file = "<empty>"; + } + if (debug) + fprintf(stderr, "%s: %s (%s, %s) - [%s]\n", + __FUNCTION__, name, type, file, line); + + snprintf(action, sizeof(action), "ChangeMedia_%s", name); + snprintf(label, sizeof(label), "%s (%s, %s)", name, type, file); + xml = realloc(xml, xpos + 128); + xpos += snprintf(xml+xpos, 128, " <menuitem action='%s'/>\n", action); + entry.name = action; + entry.label = label; + gtk_action_group_add_actions(win->mc_ag, &entry, 1, win); + } + + /* finish */ + xml = realloc(xml, xpos + strlen(mc_xml_end)+1); + xpos += sprintf(xml+xpos, "%s", mc_xml_end); + + /* add */ + if (debug) + fprintf(stderr, "---\n%s---\n", xml); + gtk_ui_manager_insert_action_group(win->ui, win->mc_ag, 1); + win->mc_id = gtk_ui_manager_add_ui_from_string(win->ui, xml, -1, &err); + if (!win->mc_id) { + g_message("building media change menu failed: %s", err->message); + g_error_free(err); + } +} |