diff options
author | kraxel <kraxel> | 2008-09-30 12:14:49 +0000 |
---|---|---|
committer | kraxel <kraxel> | 2008-09-30 12:14:49 +0000 |
commit | eb91e8c3ca50b3124b40e37a5c5836734eb36000 (patch) | |
tree | 5feaecb9453ce70ed9aff3069d98602349cbacfe | |
parent | defe66190b7e8b1c877b44d6cbb8a20b8eb13f24 (diff) | |
download | qemu-gtk-eb91e8c3ca50b3124b40e37a5c5836734eb36000.tar.gz |
- media change support.
-rw-r--r-- | GNUmakefile | 2 | ||||
-rw-r--r-- | devices.c | 136 | ||||
-rw-r--r-- | monitor.c | 29 | ||||
-rw-r--r-- | qemu-gtk.c | 24 | ||||
-rw-r--r-- | qemu-gtk.h | 9 |
5 files changed, 191 insertions, 9 deletions
diff --git a/GNUmakefile b/GNUmakefile index 87aec2f..c79fb2f 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -57,7 +57,7 @@ realclean distclean: clean ############################################# -qemu-gtk: qemu-gtk.o monitor.o tcp.o +qemu-gtk: qemu-gtk.o monitor.o devices.o tcp.o include mk/Compile.mk include mk/Maintainer.mk 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); + } +} @@ -15,11 +15,18 @@ /* ----------------------------------------------------------------- */ +static void show_error(struct qemu_window *win, char *cmd, char *reply) +{ + /* FIXME: show error dialog */ + fprintf(stderr, "ERROR: %s: %s\n", cmd, reply); +} + static int monitor_parse(struct qemu_window *win, char *buf, int len) { char *reply, *prompt, *cmd; int off; + /* handle vnc password change */ if (win->vnc_send_password && win->mrun && !strcmp(win->mrun->cmd, "change vnc password") && strstr(buf, "Password: ")) @@ -35,6 +42,7 @@ static int monitor_parse(struct qemu_window *win, char *buf, int len) return 0; } + /* parse buffer */ prompt = strstr(buf, "(qemu) "); if (NULL == prompt) { return 0; @@ -57,15 +65,18 @@ static int monitor_parse(struct qemu_window *win, char *buf, int len) goto out; } reply += 2; - if (debug) fprintf(stderr, "%s: \"%s\" -> [%s]\n", __FUNCTION__, cmd, reply); + + /* parse reply */ if (0 == strcmp(cmd, "info version")) { snprintf(win->version, sizeof(win->version), "%s", reply); update_status(win); + } else if (0 == strcmp(cmd, "info name")) { snprintf(win->name, sizeof(win->name), "%s", reply); update_status(win); + } else if (0 == strcmp(cmd, "info vnc")) { if (1 == sscanf(reply, "VNC server active on: %127[^\r\n]", win->vnc_display) && @@ -83,8 +94,16 @@ static int monitor_parse(struct qemu_window *win, char *buf, int len) vnc_connect(win); } } + } else if (0 == strcmp(cmd, "change vnc password")) { vnc_connect(win); + + } else if (0 == strcmp(cmd, "info block")) { + devices_parse_info_block(win, reply); + + } else if (0 == strncmp(cmd, "eject ", 6) || + 0 == strncmp(cmd, "change ", 7)) { + show_error(win, cmd, reply); } out: @@ -118,11 +137,16 @@ void monitor_append(struct qemu_window *win, char *cmd) ; mq->next = malloc(sizeof(*mq)); mq = mq->next; + if (debug) + fprintf(stderr, "%s: tail: %s\n", __FUNCTION__, cmd); } else { win->mqueue = malloc(sizeof(*mq)); mq = win->mqueue; - if (!win->mused && win->msize) + if (!win->mrun && !win->mused && win->msize) try_send = 1; + if (debug) + fprintf(stderr, "%s: %s: %s\n", __FUNCTION__, + try_send ? "send" : "head", cmd); } mq->next = NULL; snprintf(mq->cmd, sizeof(mq->cmd), "%s", cmd); @@ -200,5 +224,6 @@ int monitor_connect(struct qemu_window *win, char *dest) monitor_append(win, "info version"); monitor_append(win, "info name"); monitor_append(win, "info vnc"); + monitor_append(win, "info block"); return fd; } @@ -416,6 +416,7 @@ static int conn_connect(struct qemu_conn *conn, char *name, char *dest) static const GtkActionEntry entries[] = { { + /* --- menu bar --- */ .name = "FileMenu", .label = "_File", },{ @@ -428,22 +429,33 @@ static const GtkActionEntry entries[] = { .name = "VMMenu", .label = "_VM", },{ + .name = "DevicesMenu", + .label = "_Devices", + },{ .name = "HelpMenu", .label = "_Help", + },{ + /* --- sub menus --- */ + .name = "MediaChangeSubMenu", + .label = "_Change media", },{ + + /* --- file menu --- */ .name = "Close", .stock_id = GTK_STOCK_CLOSE, .label = "_Close", .accelerator = "<control>Q", .callback = G_CALLBACK(menu_cb_close), - },{ + + /* --- input menu --- */ .name = "SendCtrlAltDel", .label = "Send Ctrl-Alt-Del", .callback = G_CALLBACK(menu_cb_send_ctrlaltdel), - },{ + + /* --- vm menu --- */ .name = "MonitorStop", .stock_id = GTK_STOCK_MEDIA_PAUSE, .label = "_Pause", @@ -461,13 +473,13 @@ static const GtkActionEntry entries[] = { .name = "MonitorSysPowerdown", .label = "_Shutdown", .callback = G_CALLBACK(menu_cb_monitor_sys_powerdown), - },{ .name = "RunGdb", .label = "_Debug with gdb", .callback = G_CALLBACK(menu_cb_run_gdb), - },{ + + /* --- help menu --- */ .name = "About", .stock_id = GTK_STOCK_ABOUT, .label = "_About ...", @@ -522,6 +534,10 @@ static char ui_xml[] = " <separator/>" " <menuitem action='RunGdb'/>" " </menu>" +" <menu action='DevicesMenu'>" +" <menu action='MediaChangeSubMenu'>" +" </menu>" +" </menu>" " <menu action='HelpMenu'>" " <menuitem action='About'/>" " </menu>" @@ -2,7 +2,7 @@ struct qemu_window; struct qemu_mq { struct qemu_mq *next; - char cmd[64]; + char cmd[128]; }; enum vnc_state { @@ -52,6 +52,10 @@ struct qemu_window { struct qemu_mq *mqueue; struct qemu_mq *mrun; + /* devices */ + GtkActionGroup *mc_ag; + guint mc_id; + /* gdb */ GtkWidget *gdb_vte; pid_t gdb_pid; @@ -76,4 +80,5 @@ void qemu_conn_tab(struct qemu_window *win, struct qemu_conn *conn, int pos); int monitor_connect(struct qemu_window *win, char *dest); void monitor_append(struct qemu_window *win, char *cmd); - +/* devices.c */ +void devices_parse_info_block(struct qemu_window *win, char *str); |