diff options
Diffstat (limited to 'src/beaver-target-qemu.c')
-rw-r--r-- | src/beaver-target-qemu.c | 346 |
1 files changed, 346 insertions, 0 deletions
diff --git a/src/beaver-target-qemu.c b/src/beaver-target-qemu.c new file mode 100644 index 0000000..e45a799 --- /dev/null +++ b/src/beaver-target-qemu.c @@ -0,0 +1,346 @@ +/* + * Copyright (C) 2007, 2008 OpenedHand Ltd. + * Authored by: Rob Bradford <rob@o-hand.com> + * + * This is free software: you can redistribute it and/or modify it under the + * terms of the GNU General Public License as published by the Free Software + * Foundation, version 2 of the License. + * + * This software is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "beaver-target-qemu.h" +#include "beaver-util.h" + +G_DEFINE_TYPE (BeaverTargetQEMU, beaver_target_qemu, BEAVER_TYPE_TARGET) + +#define TARGET_QEMU_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), BEAVER_TYPE_TARGET_QEMU, BeaverTargetQEMUPrivate)) + +#define QEMU_IP_ADDRESS "192.168.7.2" +#define QEMU_SCRIPT "poky-qemu" +#define ICON_FILE "anjuta-plugin-sdk.png" +#define SSH_OPTIONS "-o", "CheckHostIP no", "-o", \ + "StrictHostKeyChecking no", "-o", "UserKnownHostsFile /dev/null" + +typedef struct _BeaverTargetQEMUPrivate BeaverTargetQEMUPrivate; + +struct _BeaverTargetQEMUPrivate +{ + gchar *rootfs; + gchar *kernel; + + BeaverTargetState state; + + AnjutaLauncher *launcher; + IAnjutaMessageView *msg_view; +}; + +enum +{ + PROP_0 = 0, + PROP_ROOTFS, + PROP_KERNEL, + PROP_IP_ADDRESS, +}; + +static BeaverTargetState beaver_target_qemu_get_state (BeaverTarget *target); +static void beaver_target_qemu_set_state (BeaverTarget *target, BeaverTargetState state); +static const gchar *beaver_target_qemu_get_ip_address (BeaverTarget *target); + +static void launcher_data_cb (AnjutaLauncher *launcher, + AnjutaLauncherOutputType type, const gchar *chars, gpointer userdata); +static void launcher_child_exited_cb (AnjutaLauncher *launcher, gint child_pid, + gint status, gulong time, gpointer userdata); + +static void +beaver_target_qemu_get_property (GObject *object, guint property_id, + GValue *value, GParamSpec *pspec) +{ + BeaverTargetQEMUPrivate *priv = TARGET_QEMU_PRIVATE (object); + + switch (property_id) { + case PROP_ROOTFS: + g_value_set_string (value, priv->rootfs); + break; + case PROP_KERNEL: + g_value_set_string (value, priv->kernel); + break; + case PROP_IP_ADDRESS: + g_value_set_string (value, QEMU_IP_ADDRESS); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +beaver_target_qemu_set_property (GObject *object, guint property_id, + const GValue *value, GParamSpec *pspec) +{ + BeaverTargetQEMUPrivate *priv = TARGET_QEMU_PRIVATE (object); + gchar *old_rootfs = NULL; + gchar *old_kernel = NULL; + + switch (property_id) { + case PROP_ROOTFS: + old_rootfs = priv->rootfs; + priv->rootfs = g_value_dup_string (value); + break; + case PROP_KERNEL: + old_kernel = priv->kernel; + priv->kernel = g_value_dup_string (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } + + /* don't do anything if we are running */ + if (!priv->launcher || anjuta_launcher_is_busy (priv->launcher)) + { + if ((old_kernel && old_rootfs) && + !(priv->rootfs && priv->kernel)) + { + beaver_target_qemu_set_state (BEAVER_TARGET (object), + TARGET_STATE_UNKNOWN); + } else if (priv->rootfs && priv->kernel) { + beaver_target_qemu_set_state (BEAVER_TARGET (object), + TARGET_STATE_STOPPED); + } + } + + g_free (old_rootfs); + g_free (old_kernel); +} + +static void +beaver_target_qemu_dispose (GObject *object) +{ + BeaverTargetQEMUPrivate *priv = TARGET_QEMU_PRIVATE (object); + IAnjutaMessageManager *msg_manager = NULL; + + if (priv->launcher) + { + g_object_unref (priv->launcher); + priv->launcher = NULL; + } + + if (priv->msg_view) + { + msg_manager = beaver_target_get_message_manager (BEAVER_TARGET (object)); + ianjuta_message_manager_remove_view (msg_manager, priv->msg_view, NULL); + priv->msg_view = NULL; + } + + if (G_OBJECT_CLASS (beaver_target_qemu_parent_class)->dispose) + G_OBJECT_CLASS (beaver_target_qemu_parent_class)->dispose (object); +} + +static void +beaver_target_qemu_finalize (GObject *object) +{ + G_OBJECT_CLASS (beaver_target_qemu_parent_class)->finalize (object); +} + +static void +beaver_target_qemu_class_init (BeaverTargetQEMUClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + BeaverTargetClass *target_class = BEAVER_TARGET_CLASS (klass); + GParamSpec *pspec = NULL; + + g_type_class_add_private (klass, sizeof (BeaverTargetQEMUPrivate)); + + object_class->get_property = beaver_target_qemu_get_property; + object_class->set_property = beaver_target_qemu_set_property; + object_class->dispose = beaver_target_qemu_dispose; + object_class->finalize = beaver_target_qemu_finalize; + + target_class->get_state = beaver_target_qemu_get_state; + target_class->set_state = beaver_target_qemu_set_state; + target_class->get_ip_address = beaver_target_qemu_get_ip_address; + + pspec = g_param_spec_string ("rootfs", "rootfs", "rootfs", NULL, + G_PARAM_READWRITE); + g_object_class_install_property (object_class, PROP_ROOTFS, pspec); + + pspec = g_param_spec_string ("kernel", "kernel", "kernel", NULL, + G_PARAM_READWRITE); + g_object_class_install_property (object_class, PROP_KERNEL, pspec); + + pspec = g_param_spec_string ("ip-address", "ip-address", "ip-address", NULL, + G_PARAM_READABLE); + g_object_class_install_property (object_class, PROP_IP_ADDRESS, pspec); +} + +static void +beaver_target_qemu_init (BeaverTargetQEMU *self) +{ +} + +BeaverTarget * +beaver_target_qemu_new (AnjutaShell *shell) +{ + return g_object_new (BEAVER_TYPE_TARGET_QEMU, + "shell", shell, + NULL); +} + +gboolean +beaver_target_qemu_start (BeaverTargetQEMU *btq, GError **out_err) +{ + BeaverTargetQEMUPrivate *priv = TARGET_QEMU_PRIVATE (btq); + GError *error = NULL; + IAnjutaMessageManager *msg_manager = NULL; + + if (!priv->msg_view) + { + /* Create a new view */ + msg_manager = beaver_target_get_message_manager (BEAVER_TARGET (btq)); + priv->msg_view = ianjuta_message_manager_add_view (msg_manager, + _("QEMU"), ICON_FILE, &error); + + if (!priv->msg_view) + { + g_warning ("Error getting view: %s", error->message); + g_clear_error (&error); + } else { + g_signal_connect (priv->msg_view, "buffer-flushed", + (GCallback)beaver_util_message_view_buffer_flushed_cb, NULL); + + /* When the view is destroyed make the pointer to it null */ + g_object_add_weak_pointer (G_OBJECT (priv->msg_view), + (gpointer *)&priv->msg_view); + + ianjuta_message_manager_set_current_view (msg_manager, priv->msg_view, + &error); + + if (error != NULL) + { + g_warning ("Error setting current message view: %s", error->message); + g_clear_error (&error); + } + } + } + + if (!priv->launcher) + { + priv->launcher = anjuta_launcher_new (); + g_signal_connect (priv->launcher, "child-exited", + (GCallback)launcher_child_exited_cb, btq); + } + + if (priv->kernel && priv->rootfs) + { + gchar *args[] = {QEMU_SCRIPT, priv->kernel, priv->rootfs, NULL}; + + if (!anjuta_launcher_execute_v (priv->launcher, args, launcher_data_cb, btq)) + { + g_warning ("Error launching QEMU"); + return FALSE; + } else { + beaver_target_qemu_set_state (BEAVER_TARGET (btq), + TARGET_STATE_READY); + } + } + + return TRUE; +} + +gboolean +beaver_target_qemu_shutdown (BeaverTargetQEMU *btq, GError **out_err) +{ + gchar *args[] = { "reboot", NULL }; + + return beaver_target_run_remote_v (BEAVER_TARGET (btq), args, NULL); +} + +static BeaverTargetState +beaver_target_qemu_get_state (BeaverTarget *target) +{ + BeaverTargetQEMUPrivate *priv = TARGET_QEMU_PRIVATE (target); + + return priv->state; +} + +static const gchar * +beaver_target_qemu_get_ip_address (BeaverTarget *target) +{ + return QEMU_IP_ADDRESS; +} + +static void +beaver_target_qemu_set_state (BeaverTarget *target, BeaverTargetState state) +{ + BeaverTargetQEMU *btq = BEAVER_TARGET_QEMU (target); + BeaverTargetQEMUPrivate *priv = TARGET_QEMU_PRIVATE (btq); + + priv->state = state; + g_signal_emit_by_name (btq, "state-changed"); +} + +static void +launcher_data_cb (AnjutaLauncher *launcher, + AnjutaLauncherOutputType type, const gchar *chars, gpointer userdata) +{ + BeaverTargetQEMUPrivate *priv = TARGET_QEMU_PRIVATE (userdata); + GError *error = NULL; + + if (priv->msg_view) + { + /* Append to the buffer for the message view to deal with the newlines */ + ianjuta_message_view_buffer_append (priv->msg_view, chars, &error); + + if (error != NULL) + { + g_warning ("Error appending to message view: %s", error->message); + g_clear_error (&error); + } + } else { + g_warning ("No message view to append to."); + } +} +/* +static void +action_shutdown_qemu_activate_cb (GtkAction *actio, gpointer userdata) +{ + AnjutaPluginSdk *sp = (AnjutaPluginSdk *)userdata; + gchar *args[] = { "ssh", SSH_OPTIONS, + "root@"QEMU_IP_ADDRESS, "reboot", NULL}; + + if (!sp->remote_launcher) + { + sp->remote_launcher = anjuta_launcher_new (); + g_signal_connect (sp->remote_launcher, "child-exited", + (GCallback)remote_launcher_child_exited_cb, sp); + } + + if (anjuta_launcher_execute_v (sp->remote_launcher, args, NULL, NULL)) + { + gtk_action_set_sensitive (sp->qemu_shutdown_action, FALSE); + } else { + g_warning ("Error whilst launching reboot (for shutdown) command"); + } +} +*/ + +static void +launcher_child_exited_cb (AnjutaLauncher *launcher, gint child_pid, + gint status, gulong time, gpointer userdata) +{ + BeaverTargetQEMUPrivate *priv = TARGET_QEMU_PRIVATE (userdata); + + /* check we're still valid */ + if (priv->rootfs && priv->kernel) + { + beaver_target_qemu_set_state (BEAVER_TARGET (userdata), TARGET_STATE_STOPPED); + } else { + beaver_target_qemu_set_state (BEAVER_TARGET (userdata), TARGET_STATE_UNKNOWN); + } +} |