#include #include #include #include #include #include #include "qemu-gtk.h" /* ----------------------------------------------------------------- */ static char media_xml[] = "\n" " \n" " \n" " \n" "%s" " \n" " \n" "%s" " \n" " \n" " \n" "\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); } static void menu_cb_eject_media(GtkAction *action, void *data) { struct qemu_window *win = data; char name[32], cmd[128]; if (1 != sscanf(gtk_action_get_name(action), "EjectMedia_%31s", name)) return; if (debug) fprintf(stderr, "%s: %s\n", __FUNCTION__, name); snprintf(cmd, sizeof(cmd), "eject %s", name); monitor_append(win, cmd); monitor_append(win, "info block"); } void devices_parse_info_block(struct qemu_window *win, char *str) { char name[32], type[16], line[256], *file, *ptr, *xml; char action[128], label[128]; int removable, pos, len, rc, eject; GtkActionEntry c_entry, e_entry; char *c_xml = NULL, *e_xml = NULL; int c_pos = 0, e_pos = 0; GError *err = NULL; /* 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(&c_entry, 0, sizeof(c_entry)); c_entry.callback = G_CALLBACK(menu_cb_change_media); memset(&e_entry, 0, sizeof(e_entry)); e_entry.callback = G_CALLBACK(menu_cb_eject_media); win->mc_ag = gtk_action_group_new("MediaActions"); /* 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; #if 1 /* basename */ ptr = strrchr(file, '/'); if (ptr) file = ptr+1; #endif eject = 1; } else { file = ""; eject = 0; } 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); c_entry.name = action; c_entry.label = label; gtk_action_group_add_actions(win->mc_ag, &c_entry, 1, win); c_xml = realloc(c_xml, c_pos + 128); c_pos += snprintf(c_xml+c_pos, 128, " \n", action); if (eject) { snprintf(action, sizeof(action), "EjectMedia_%s", name); snprintf(label, sizeof(label), "%s (%s, %s)", name, type, file); e_entry.name = action; e_entry.label = label; gtk_action_group_add_actions(win->mc_ag, &e_entry, 1, win); e_xml = realloc(e_xml, e_pos + 128); e_pos += snprintf(e_xml+e_pos, 128, " \n", action); } } xml = malloc(e_pos + c_pos + strlen(media_xml)); sprintf(xml, media_xml, e_pos ? e_xml : "", c_pos ? c_xml : ""); /* 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); } free(c_xml); free(e_xml); free(xml); }