diff options
-rw-r--r-- | ChangeLog | 40 | ||||
-rw-r--r-- | src/Makefile.am | 5 | ||||
-rw-r--r-- | src/beaver-target-qemu.c | 346 | ||||
-rw-r--r-- | src/beaver-target-qemu.h | 70 | ||||
-rw-r--r-- | src/beaver-target.c | 296 | ||||
-rw-r--r-- | src/beaver-target.h | 89 | ||||
-rw-r--r-- | src/beaver-util.c | 108 | ||||
-rw-r--r-- | src/beaver-util.h | 27 | ||||
-rw-r--r-- | src/plugin.c | 304 | ||||
-rw-r--r-- | src/plugin.h | 10 |
10 files changed, 1107 insertions, 188 deletions
@@ -1,3 +1,43 @@ +2008-03-17 Rob Bradford <rob@openedhand.com> + + * src/Makefile.am: + * src/beaver-target-qemu.c: (beaver_target_qemu_get_property), + (beaver_target_qemu_set_property), (beaver_target_qemu_dispose), + (beaver_target_qemu_finalize), (beaver_target_qemu_class_init), + (beaver_target_qemu_init), (beaver_target_qemu_new), + (beaver_target_qemu_start), (beaver_target_qemu_shutdown), + (beaver_target_qemu_get_state), + (beaver_target_qemu_get_ip_address), + (beaver_target_qemu_set_state), (launcher_data_cb), + (launcher_child_exited_cb): + * src/beaver-target-qemu.h: + * src/beaver-target.c: (beaver_target_get_property), + (beaver_target_set_property), (beaver_target_dispose), + (beaver_target_finalize), (beaver_target_class_init), + (beaver_target_init), (beaver_target_get_state), + (beaver_target_set_state), (beaver_target_get_ip_address), + (beaver_target_get_message_manager), (beaver_target_run_remote_v), + (_beaver_target_run_remote_v), (launcher_child_exited_cb), + (launcher_data_cb): + * src/beaver-target.h: + * src/beaver-util.c: (beaver_util_message_view_buffer_flushed_cb), + (beaver_util_strv_concat), (beaver_util_strv_joinv): + * src/beaver-util.h: + * src/plugin.c: (deploy_do_copy), + (action_shutdown_qemu_activate_cb), + (action_start_qemu_activate_cb), + (action_remote_debug_stop_activate_cb), (do_local_gdb), + (do_remote_gdb), (action_remote_run_activate_cb), + (action_remote_profile_activate_cb), + (remote_gdb_launcher_child_exited_cb), + (oprofileui_launcher_child_exited_cb), + (rootfs_preference_notify_cb), (kernel_preference_notify_cb), + (project_root_uri_value_added), (target_state_changed_cb), + (anjuta_plugin_sdk_activate), (anjuta_plugin_sdk_deactivate): + * src/plugin.h: + Refactor out some operations on the target to allow using a real + device as the target (rather than QEMU.) + 2008-03-11 Rob Bradford <rob@openedhand.com> * src/plugin.c: (update_path), (update_environment): diff --git a/src/Makefile.am b/src/Makefile.am index ca14ab2..662e736 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -42,7 +42,10 @@ plugindir = $(anjuta_plugin_dir) plugin_LTLIBRARIES = libanjuta-plugin-sdk.la # Plugin sources -libanjuta_plugin_sdk_la_SOURCES = plugin.c plugin.h +libanjuta_plugin_sdk_la_SOURCES = plugin.c plugin.h \ + beaver-target.c beaver-target.h \ + beaver-target-qemu.c beaver-target-qemu.h \ + beaver-util.c beaver-util.h # Plugin dependencies libanjuta_plugin_sdk_la_LIBADD = \ 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); + } +} diff --git a/src/beaver-target-qemu.h b/src/beaver-target-qemu.h new file mode 100644 index 0000000..ed76c85 --- /dev/null +++ b/src/beaver-target-qemu.h @@ -0,0 +1,70 @@ +/* + * 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/>. + */ + +#ifndef _BEAVER_TARGET_QEMU +#define _BEAVER_TARGET_QEMU + +#include <config.h> +#include <glib-object.h> + +#include <libanjuta/anjuta-plugin.h> +#include <libanjuta/interfaces/ianjuta-message-manager.h> +#include <libanjuta/anjuta-launcher.h> + +#include "beaver-target.h" + +G_BEGIN_DECLS + +#define BEAVER_TYPE_TARGET_QEMU beaver_target_qemu_get_type() + +#define BEAVER_TARGET_QEMU(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + BEAVER_TYPE_TARGET_QEMU, BeaverTargetQEMU)) + +#define BEAVER_TARGET_QEMU_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), \ + BEAVER_TYPE_TARGET_QEMU, BeaverTargetQEMUClass)) + +#define BEAVER_IS_TARGET_QEMU(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ + BEAVER_TYPE_TARGET_QEMU)) + +#define BEAVER_IS_TARGET_QEMU_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), \ + BEAVER_TYPE_TARGET_QEMU)) + +#define BEAVER_TARGET_QEMU_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), \ + BEAVER_TYPE_TARGET_QEMU, BeaverTargetQEMUClass)) + +typedef struct { + BeaverTarget parent; +} BeaverTargetQEMU; + +typedef struct { + BeaverTargetClass parent_class; +} BeaverTargetQEMUClass; + +GType beaver_target_qemu_get_type (void); + +BeaverTarget *beaver_target_qemu_new (AnjutaShell *shell); +gboolean beaver_target_qemu_start (BeaverTargetQEMU *btq, GError **error); +gboolean beaver_target_qemu_shutdown (BeaverTargetQEMU *btq, GError **error); + +G_END_DECLS + +#endif /* _BEAVER_TARGET_QEMU */ diff --git a/src/beaver-target.c b/src/beaver-target.c new file mode 100644 index 0000000..696266d --- /dev/null +++ b/src/beaver-target.c @@ -0,0 +1,296 @@ +/* + * 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.h" +#include "beaver-util.h" + +G_DEFINE_TYPE (BeaverTarget, beaver_target, G_TYPE_OBJECT) + +#define TARGET_PRIVATE(o) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((o), BEAVER_TYPE_TARGET, BeaverTargetPrivate)) + +#define ICON_FILE "anjuta-plugin-sdk.png" + +typedef struct _BeaverTargetPrivate BeaverTargetPrivate; + +struct _BeaverTargetPrivate +{ + AnjutaShell *shell; + IAnjutaMessageView *msg_view; + + AnjutaLauncher *launcher; +}; + +/* for signals */ +enum { + STATE_CHANGED, + LAST_SIGNAL +}; + +enum +{ + PROP_0 = 0, + PROP_SHELL +}; + +static guint signals[LAST_SIGNAL] = { 0 }; + +static const gchar *ssh_options[] = { + "ssh", + "-l", "root", + "-o", "CheckHostIP no", + "-o", "StrictHostKeyChecking no", + "-o", "UserKnownHostsFile /dev/null", + NULL }; + +static void launcher_child_exited_cb (AnjutaLauncher *launcher, gint child_pid, + gint status, gulong time, gpointer userdata); +static void launcher_data_cb (AnjutaLauncher *launcher, + AnjutaLauncherOutputType type, const gchar *chars, gpointer userdata); +gboolean _beaver_target_run_remote_v (BeaverTarget *target, gchar **in_args, + GError **error); + +static void +beaver_target_get_property (GObject *object, guint property_id, + GValue *value, GParamSpec *pspec) +{ + switch (property_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +beaver_target_set_property (GObject *object, guint property_id, + const GValue *value, GParamSpec *pspec) +{ + BeaverTargetPrivate *priv = TARGET_PRIVATE (object); + + switch (property_id) { + case PROP_SHELL: + priv->shell = g_value_get_object (value); + + /* When the shell is destroyed make the pointer to it null */ + g_object_add_weak_pointer (G_OBJECT (priv->shell), + (gpointer *)&priv->shell); + + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + } +} + +static void +beaver_target_dispose (GObject *object) +{ + BeaverTargetPrivate *priv = TARGET_PRIVATE (object); + + if (priv->launcher) + { + g_object_unref (priv->launcher); + priv->launcher = NULL; + } + + if (G_OBJECT_CLASS (beaver_target_parent_class)->dispose) + G_OBJECT_CLASS (beaver_target_parent_class)->dispose (object); +} + +static void +beaver_target_finalize (GObject *object) +{ + G_OBJECT_CLASS (beaver_target_parent_class)->finalize (object); +} + +static void +beaver_target_class_init (BeaverTargetClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + GParamSpec *pspec = NULL; + + g_type_class_add_private (klass, sizeof (BeaverTargetPrivate)); + + object_class->get_property = beaver_target_get_property; + object_class->set_property = beaver_target_set_property; + object_class->dispose = beaver_target_dispose; + object_class->finalize = beaver_target_finalize; + + klass->run_remote_v = _beaver_target_run_remote_v; + + signals[STATE_CHANGED] = g_signal_new ("state-changed", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (BeaverTargetClass, state_changed), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + pspec = g_param_spec_object ("shell", "shell", "shell", + ANJUTA_TYPE_SHELL, + G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE); + g_object_class_install_property (object_class, PROP_SHELL, pspec); +} + +static void +beaver_target_init (BeaverTarget *self) +{ +} + +BeaverTargetState +beaver_target_get_state (BeaverTarget *target) +{ + return BEAVER_TARGET_GET_CLASS (target)->get_state (target); +} + +void +beaver_target_set_state (BeaverTarget *target, BeaverTargetState state) +{ + BEAVER_TARGET_GET_CLASS (target)->set_state (target, state); +} + +const gchar * +beaver_target_get_ip_address (BeaverTarget *target) +{ + return BEAVER_TARGET_GET_CLASS (target)->get_ip_address (target); +} + +IAnjutaMessageManager * +beaver_target_get_message_manager (BeaverTarget *target) +{ + BeaverTargetPrivate *priv = TARGET_PRIVATE (target); + IAnjutaMessageManager *msg_manager = NULL; + GError *error = NULL; + + /* Get the message view manager */ + msg_manager = anjuta_shell_get_interface (priv->shell, + IAnjutaMessageManager, &error); + + if (!msg_manager) + { + g_warning ("Error getting implementation of IAnjutaMessageManager: %s", + error->message); + g_clear_error (&error); + } + + return msg_manager; +} + +gboolean +beaver_target_run_remote_v (BeaverTarget *target, gchar **in_args, + GError **error) +{ + return BEAVER_TARGET_GET_CLASS (target)->run_remote_v (target, in_args, error); +} + +/* default implementations */ +gboolean +_beaver_target_run_remote_v (BeaverTarget *target, gchar **in_args, + GError **out_err) +{ + BeaverTargetPrivate *priv = TARGET_PRIVATE (target); + gchar **args = NULL; + gchar *ip_args[] = { (gchar *)beaver_target_get_ip_address (target), NULL }; + GError *error = NULL; + IAnjutaMessageManager *msg_manager = NULL; + + if (!priv->launcher) + { + priv->launcher = anjuta_launcher_new (); + g_signal_connect (priv->launcher, "child-exited", + (GCallback)launcher_child_exited_cb, target); + } + + args = beaver_util_strv_joinv ((gchar **)ssh_options, ip_args, in_args, NULL); + + if (!priv->msg_view) + { + /* Create a new view */ + msg_manager = beaver_target_get_message_manager (target); + priv->msg_view = ianjuta_message_manager_add_view (msg_manager, + _("Remote"), 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 (anjuta_launcher_execute_v (priv->launcher, args, launcher_data_cb, target)) + { + beaver_target_set_state (target, TARGET_STATE_BUSY); + return TRUE; + } else { + gchar *debug_str = NULL; + + debug_str = g_strjoinv (" ", args); + g_warning ("Error whilst launching command: %s", debug_str); + g_free (debug_str); + g_free (args); + + return FALSE; + } +} + +static void +launcher_child_exited_cb (AnjutaLauncher *launcher, gint child_pid, + gint status, gulong time, gpointer userdata) +{ + BeaverTarget *target = BEAVER_TARGET (userdata); + + if (beaver_target_get_state (target) == TARGET_STATE_READY) + beaver_target_set_state (target, TARGET_STATE_READY); +} + +static void +launcher_data_cb (AnjutaLauncher *launcher, + AnjutaLauncherOutputType type, const gchar *chars, gpointer userdata) +{ + BeaverTargetPrivate *priv = TARGET_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."); + } +} + diff --git a/src/beaver-target.h b/src/beaver-target.h new file mode 100644 index 0000000..fbc57c2 --- /dev/null +++ b/src/beaver-target.h @@ -0,0 +1,89 @@ +/* + * 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/>. + */ + +#ifndef _BEAVER_TARGET +#define _BEAVER_TARGET + +#include <glib-object.h> + +#include <libanjuta/anjuta-plugin.h> +#include <libanjuta/interfaces/ianjuta-message-manager.h> +#include <libanjuta/anjuta-launcher.h> + +G_BEGIN_DECLS + +#define BEAVER_TYPE_TARGET beaver_target_get_type() + +#define BEAVER_TARGET(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), \ + BEAVER_TYPE_TARGET, BeaverTarget)) + +#define BEAVER_TARGET_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), \ + BEAVER_TYPE_TARGET, BeaverTargetClass)) + +#define BEAVER_IS_TARGET(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), \ + BEAVER_TYPE_TARGET)) + +#define BEAVER_IS_TARGET_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), \ + BEAVER_TYPE_TARGET)) + +#define BEAVER_TARGET_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), \ + BEAVER_TYPE_TARGET, BeaverTargetClass)) + +typedef enum +{ + TARGET_STATE_UNKNOWN, + TARGET_STATE_STOPPED, + TARGET_STATE_READY, + TARGET_STATE_BUSY +} BeaverTargetState; + +typedef struct { + GObject parent; +} BeaverTarget; + +typedef struct { + GObjectClass parent_class; + + /* for signals */ + void (* state_changed) (BeaverTarget *target); + + /* for vfuncs */ + BeaverTargetState (* get_state) (BeaverTarget *target); + void (* set_state) (BeaverTarget *target, BeaverTargetState state); + const gchar * (* get_ip_address) (BeaverTarget *target); + + gboolean (* run_remote_v) (BeaverTarget *target, gchar **args_in, + GError **error); +} BeaverTargetClass; + +GType beaver_target_get_type (void); + +BeaverTargetState beaver_target_get_state (BeaverTarget *target); +void beaver_target_set_state (BeaverTarget *target, BeaverTargetState state); +const gchar *beaver_target_get_ip_address (BeaverTarget *target); +IAnjutaMessageManager *beaver_target_get_message_manager (BeaverTarget *target); +gboolean beaver_target_run_remote_v (BeaverTarget *target, gchar **in_args, + GError **error); + +G_END_DECLS + +#endif /* _BEAVER_TARGET */ diff --git a/src/beaver-util.c b/src/beaver-util.c new file mode 100644 index 0000000..96401b9 --- /dev/null +++ b/src/beaver-util.c @@ -0,0 +1,108 @@ +/* + * 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-util.h" + +/* + * Callback that gets fired when data gets flushed in the view because it's + * the end of line + */ +void +beaver_util_message_view_buffer_flushed_cb (IAnjutaMessageView *view, gchar *data, + gpointer userdata) +{ + /* Append to the message view */ + ianjuta_message_view_append (view, IANJUTA_MESSAGE_VIEW_TYPE_NORMAL, + data, "", NULL); +} + +/* do not free the strings in the returned vector but do free the vector */ +gchar ** +beaver_util_strv_concat (gchar **strv_1, gchar **strv_2) +{ + gchar **res = NULL; + gchar **p = NULL; + + res = g_new0 (gchar *, g_strv_length (strv_1) + g_strv_length (strv_2) + 1); + p = res; + + while (*strv_1 != NULL) + { + *p = *strv_1; + + p++; + strv_1++; + } + + while (*strv_2 != NULL) + { + *p = *strv_2; + + p++; + strv_2++; + } + + *p = NULL; + + return res; +} + +gchar ** +beaver_util_strv_joinv (gchar **strv_1, ...) +{ + gchar **res; + gchar **strv_j; + + gint i; + gint items; + + va_list args; + va_start (args, strv_1); + + items = g_strv_length (strv_1); + + res = g_malloc0 ((items + 1) * sizeof (gchar *)); + i = 0; + + while (*strv_1 != NULL) + { + res[i] = *strv_1; + + i++; + strv_1++; + } + + while ((strv_j = va_arg (args, gchar **)) != NULL) + { + items += g_strv_length (strv_j); + res = g_realloc (res, (items + 1) * sizeof (gchar *)); + + while (*strv_j != NULL) + { + res[i] = *strv_j; + + i++; + strv_j++; + } + } + + va_end (args); + + res[i] = NULL; + + return res; +} diff --git a/src/beaver-util.h b/src/beaver-util.h new file mode 100644 index 0000000..842db77 --- /dev/null +++ b/src/beaver-util.h @@ -0,0 +1,27 @@ +/* + * 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 <config.h> +#include <glib-object.h> + +#include <libanjuta/anjuta-plugin.h> +#include <libanjuta/interfaces/ianjuta-message-manager.h> + +void beaver_util_message_view_buffer_flushed_cb (IAnjutaMessageView *view, + gchar *data, gpointer userdata); +gchar **beaver_util_strv_concat (gchar **strv_1, gchar **strv_2); +gchar **beaver_util_strv_joinv (gchar **strv_1, ...); diff --git a/src/plugin.c b/src/plugin.c index 9e6fb2e..92488fa 100644 --- a/src/plugin.c +++ b/src/plugin.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007 OpenedHand Ltd. + * 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 @@ -35,7 +35,6 @@ #define g_timeout_add_seconds(interval, function, data) g_timeout_add ((interval) * 1000, function, data) #endif - #define PREFS_PROP_SDK_ROOT "sdk.root" #define PREFS_PROP_TRIPLET "sdk.triplet" #define PREFS_PROP_POKY_ROOT "sdk.poky_root" @@ -52,9 +51,6 @@ #define SSH_OPTIONS "-o", "CheckHostIP no", "-o", \ "StrictHostKeyChecking no", "-o", "UserKnownHostsFile /dev/null" -#define QEMU_IP_ADDRESS "192.168.7.2" - -#define QEMU_SCRIPT "poky-qemu" #define CONFIGURE_COMMAND "./configure --host=%s" #define AUTOGEN_COMMAND "./autogen.sh --host=%s" @@ -169,8 +165,6 @@ static GtkActionEntry actions_sdk[] = { /* Misc callback prototypes */ static void message_view_buffer_flushed_cb (IAnjutaMessageView *view, gchar *data, gpointer userdata); -static void qemu_launcher_child_exited_cb (AnjutaLauncher *launcher, - gint child_pid, gint status, gulong time, gpointer userdata); static void remote_launcher_child_exited_cb (AnjutaLauncher *launcher, gint child_pid, gint status, gulong time, gpointer userdata); static void remote_gdb_launcher_child_exited_cb (AnjutaLauncher *launcher, @@ -236,26 +230,6 @@ deploy_launcher_data_cb (AnjutaLauncher *launcher, } static void -qemu_launcher_data_cb (AnjutaLauncher *launcher, - AnjutaLauncherOutputType type, const gchar *chars, gpointer userdata) -{ - AnjutaPluginSdk *sp = (AnjutaPluginSdk *)userdata; - GError *error = NULL; - - if (sp->qemu_msg_view) - { - /* Append to the buffer for the message view to deal with the newlines */ - ianjuta_message_view_buffer_append (sp->qemu_msg_view, chars, &error); - - if (error != NULL) - { - g_warning ("Error appending to message view: %s", error->message); - g_clear_error (&error); - } - } -} - -static void remote_gdb_launcher_data_cb (AnjutaLauncher *launcher, AnjutaLauncherOutputType type, const gchar *chars, gpointer userdata) { @@ -428,9 +402,11 @@ deploy_do_local_install (AnjutaPluginSdk *sp) static void deploy_do_copy (AnjutaPluginSdk *sp) { + const gchar *ip_address = NULL; gchar *copy_cmd = NULL; - copy_cmd = g_strdup_printf (DEPLOY_COMMAND, sp->deploy_path, QEMU_IP_ADDRESS); + ip_address = beaver_target_get_ip_address (sp->target); + copy_cmd = g_strdup_printf (DEPLOY_COMMAND, sp->deploy_path, ip_address); ianjuta_message_view_append (sp->deploy_msg_view, IANJUTA_MESSAGE_VIEW_TYPE_INFO, _("Copying files to target"), "", NULL); @@ -510,21 +486,21 @@ 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) + if (BEAVER_IS_TARGET_QEMU (sp->target)) { - sp->remote_launcher = anjuta_launcher_new (); - g_signal_connect (sp->remote_launcher, "child-exited", - (GCallback)remote_launcher_child_exited_cb, sp); + beaver_target_qemu_shutdown (BEAVER_TARGET_QEMU (sp->target), NULL); } +} - if (anjuta_launcher_execute_v (sp->remote_launcher, args, NULL, NULL)) +static void +action_start_qemu_activate_cb (GtkAction *action, gpointer userdata) +{ + AnjutaPluginSdk *sp = (AnjutaPluginSdk *)userdata; + + if (BEAVER_IS_TARGET_QEMU (sp->target)) { - gtk_action_set_sensitive (sp->qemu_shutdown_action, FALSE); - } else { - g_warning ("Error whilst launching reboot (for shutdown) command"); + beaver_target_qemu_start (BEAVER_TARGET_QEMU(sp->target), NULL); } } @@ -532,8 +508,12 @@ static void action_remote_debug_stop_activate_cb (GtkAction *action, gpointer userdata) { AnjutaPluginSdk *sp = (AnjutaPluginSdk *)userdata; - gchar *args[] = { "ssh", SSH_OPTIONS, - "root@"QEMU_IP_ADDRESS, "killall gdbserver", NULL}; + gchar *args[] = { "ssh", + SSH_OPTIONS, + "-l", "root", + (gchar *)beaver_target_get_ip_address (sp->target), + "killall gdbserver", + NULL}; if (!sp->remote_launcher) { @@ -558,94 +538,6 @@ action_deploy_activate_cb (GtkAction *action, gpointer userdata) deploy_set_state (sp, DEPLOY_STATE_INITIAL); } -static void -action_start_qemu_activate_cb (GtkAction *action, gpointer userdata) -{ - AnjutaPluginSdk *sp = (AnjutaPluginSdk *)userdata; - GError *error = NULL; - IAnjutaMessageManager *msg_manager = NULL; - - /* Get the message view manager */ - msg_manager = anjuta_shell_get_interface (ANJUTA_PLUGIN (sp)->shell, - IAnjutaMessageManager, &error); - - if (!msg_manager) - { - g_warning ("Error getting implementation of IAnjutaMessageManager: %s", - error->message); - g_clear_error (&error); - - return; - } - - if (!sp->qemu_msg_view) - { - /* Create a new view */ - sp->qemu_msg_view = ianjuta_message_manager_add_view (msg_manager, - _("QEMU"), ICON_FILE, &error); - - if (!sp->qemu_msg_view) - { - g_warning ("Error getting view: %s", error->message); - g_clear_error (&error); - return; - } - - g_signal_connect (sp->qemu_msg_view, "buffer-flushed", - (GCallback)message_view_buffer_flushed_cb, sp); - - /* When the view is destroyed make the pointer to it null */ - g_object_add_weak_pointer (G_OBJECT (sp->qemu_msg_view), - (gpointer *)&sp->qemu_msg_view); - } - - ianjuta_message_manager_set_current_view (msg_manager, sp->qemu_msg_view, - &error); - - if (error != NULL) - { - g_warning ("Error setting current message view: %s", error->message); - g_clear_error (&error); - - return; - } - - if (!sp->qemu_launcher) - { - sp->qemu_launcher = anjuta_launcher_new (); - g_signal_connect (sp->qemu_launcher, "child-exited", - (GCallback)qemu_launcher_child_exited_cb, sp); - } - - if (sp->kernel && sp->rootfs) - { - gchar *args[] = {QEMU_SCRIPT, sp->kernel, sp->rootfs, NULL}; - - if (!anjuta_launcher_execute_v (sp->qemu_launcher, args, qemu_launcher_data_cb, sp)) - { - g_warning ("Error launching QEMU"); - } else { - gtk_action_set_sensitive (sp->qemu_start_action, FALSE); - gtk_action_set_sensitive (sp->qemu_shutdown_action, TRUE); - gtk_action_set_sensitive (sp->remote_run_action, TRUE); - - if (sp->triplet && sp->sdk_root) - gtk_action_set_sensitive (sp->remote_debug_action, TRUE); - - if (anjuta_util_prog_is_installed ("oprofile-viewer", FALSE)) - { - gtk_action_set_sensitive (sp->remote_profile_action, TRUE); - } - - /* Make the actions sensitive if we have a project root*/ - if (sp->project_root_uri) - { - gtk_action_set_sensitive (sp->deploy_action, TRUE); - } - } - } -} - static gint remote_debug_dialog (AnjutaPluginSdk *sp) { @@ -826,7 +718,8 @@ do_local_gdb (AnjutaPluginSdk *sp) } gdb_prefix = g_build_filename (sp->sdk_root, sp->triplet, NULL); - script_contents = g_strdup_printf (GDB_SCRIPT, gdb_prefix, QEMU_IP_ADDRESS); + script_contents = g_strdup_printf (GDB_SCRIPT, gdb_prefix, + beaver_target_get_ip_address (sp->target)); channel = g_io_channel_unix_new (fd); @@ -945,7 +838,9 @@ do_remote_gdb (AnjutaPluginSdk *sp) return; } - cmd = g_strdup_printf (REMOTE_GDB_COMMAND, QEMU_IP_ADDRESS, sp->gdb_remote_command); + cmd = g_strdup_printf (REMOTE_GDB_COMMAND, + beaver_target_get_ip_address (sp->target), + sp->gdb_remote_command); /* start the remote gdbserver */ if (anjuta_launcher_execute (sp->remote_gdb_launcher, cmd, @@ -1034,7 +929,9 @@ action_remote_run_activate_cb (GtkAction *action, switch (res) { case GTK_RESPONSE_ACCEPT: - cmd = g_strdup_printf (REMOTE_COMMAND, QEMU_IP_ADDRESS, sp->remote_command); + cmd = g_strdup_printf (REMOTE_COMMAND, + beaver_target_get_ip_address (sp->target), + sp->remote_command); ianjuta_terminal_execute_command (terminal, cur_dir, cmd, &error); break; default: @@ -1060,7 +957,9 @@ action_remote_profile_activate_cb (GtkAction *action, gpointer userdata) } search_path = g_build_filename (sp->sdk_root, sp->triplet, NULL); - cmd = g_strdup_printf (OPROFILEUI_COMMAND, QEMU_IP_ADDRESS, search_path); + cmd = g_strdup_printf (OPROFILEUI_COMMAND, + beaver_target_get_ip_address (sp->target), + search_path); if (anjuta_launcher_execute (sp->oprofileui_launcher, cmd, NULL, NULL)) { @@ -1074,24 +973,7 @@ action_remote_profile_activate_cb (GtkAction *action, gpointer userdata) } /* Callback for when qemu launcher finished */ -static void -qemu_launcher_child_exited_cb (AnjutaLauncher *launcher, gint child_pid, - gint status, gulong time, gpointer userdata) -{ - AnjutaPluginSdk *sp = (AnjutaPluginSdk *)userdata; - gtk_action_set_sensitive (sp->qemu_start_action, TRUE); - gtk_action_set_sensitive (sp->qemu_shutdown_action, FALSE); - - /* Make the deploy insensitive */ - gtk_action_set_sensitive (sp->deploy_action, FALSE); - - gtk_action_set_sensitive (sp->remote_debug_action, FALSE); - gtk_action_set_sensitive (sp->remote_run_action, FALSE); - gtk_action_set_sensitive (sp->remote_debug_stop_action, FALSE); - - gtk_action_set_sensitive (sp->remote_profile_action, FALSE); -} static void remote_launcher_child_exited_cb (AnjutaLauncher *launcher, gint child_pid, @@ -1107,8 +989,8 @@ remote_gdb_launcher_child_exited_cb (AnjutaLauncher *launcher, gint child_pid, { AnjutaPluginSdk *sp = (AnjutaPluginSdk *)userdata; - if (sp->triplet && sp->sdk_root && sp->qemu_launcher && - anjuta_launcher_is_busy (sp->qemu_launcher)) + if (sp->triplet && sp->sdk_root && + beaver_target_get_state (sp->target) == TARGET_STATE_READY) { gtk_action_set_sensitive (sp->remote_debug_action, TRUE); } @@ -1126,7 +1008,7 @@ oprofileui_launcher_child_exited_cb (AnjutaLauncher *launcher, gint child_pid, { AnjutaPluginSdk *sp = (AnjutaPluginSdk *)userdata; - if (sp->qemu_launcher && anjuta_launcher_is_busy (sp->qemu_launcher)) + if (beaver_target_get_state (sp->target) == TARGET_STATE_READY) { if (anjuta_util_prog_is_installed ("oprofile-viewer", FALSE)) { @@ -1415,13 +1297,12 @@ rootfs_preference_notify_cb (GConfClient *client, guint cnxn_id, GConfEntry *entry, gpointer userdata) { AnjutaPluginSdk *sp = (AnjutaPluginSdk *)userdata; + gchar *rootfs = NULL; - g_free (sp->rootfs); - sp->rootfs = anjuta_preferences_get (sp->prefs, PREFS_PROP_ROOTFS); - - if (sp->rootfs && sp->kernel) + if (BEAVER_IS_TARGET_QEMU (sp->target)) { - gtk_action_set_sensitive (sp->qemu_start_action, TRUE); + rootfs = anjuta_preferences_get (sp->prefs, PREFS_PROP_ROOTFS); + g_object_set (sp->target, "rootfs", rootfs, NULL); } } @@ -1430,13 +1311,12 @@ kernel_preference_notify_cb (GConfClient *client, guint cnxn_id, GConfEntry *entry, gpointer userdata) { AnjutaPluginSdk *sp = (AnjutaPluginSdk *)userdata; + gchar *kernel = NULL; - g_free (sp->kernel); - sp->kernel = anjuta_preferences_get (sp->prefs, PREFS_PROP_KERNEL); - - if (sp->rootfs && sp->kernel) + if (BEAVER_IS_TARGET_QEMU (sp->target)) { - gtk_action_set_sensitive (sp->qemu_start_action, TRUE); + kernel = anjuta_preferences_get (sp->prefs, PREFS_PROP_KERNEL); + g_object_set (sp->target, "kernel", kernel, NULL); } } @@ -1477,8 +1357,7 @@ project_root_uri_value_added (AnjutaPlugin *plugin, const gchar *name, g_free (sp->project_root_uri); sp->project_root_uri = g_value_dup_string (value); - /* if qemu is already running then turn these actions on */ - if (sp->qemu_launcher && anjuta_launcher_is_busy (sp->qemu_launcher)) + if (beaver_target_get_state (sp->target) == TARGET_STATE_READY) { gtk_action_set_sensitive (sp->deploy_action, TRUE); } @@ -1524,12 +1403,69 @@ shell_session_save_cb (AnjutaShell *shell, AnjutaSessionPhase phase, sp->gdb_remote_command); } +static void +target_state_changed_cb (BeaverTarget *target, gpointer userdata) +{ + AnjutaPluginSdk *sp = (AnjutaPluginSdk *)userdata; + BeaverTargetState state; + + state = beaver_target_get_state (target); + + if (BEAVER_IS_TARGET_QEMU (target)) + { + switch (state) + { + case TARGET_STATE_UNKNOWN: + gtk_action_set_sensitive (sp->qemu_start_action, FALSE); + break; + case TARGET_STATE_STOPPED: + gtk_action_set_sensitive (sp->qemu_start_action, TRUE); + break; + case TARGET_STATE_READY: + gtk_action_set_sensitive (sp->qemu_start_action, FALSE); + gtk_action_set_sensitive (sp->qemu_shutdown_action, TRUE); + case TARGET_STATE_BUSY: + gtk_action_set_sensitive (sp->qemu_shutdown_action, FALSE); + default: + break; + } + } + + switch (state) + { + case TARGET_STATE_UNKNOWN: + case TARGET_STATE_STOPPED: + case TARGET_STATE_BUSY: + gtk_action_set_sensitive (sp->deploy_action, FALSE); + gtk_action_set_sensitive (sp->remote_profile_action, FALSE); + gtk_action_set_sensitive (sp->qemu_shutdown_action, FALSE); + gtk_action_set_sensitive (sp->remote_run_action, FALSE); + gtk_action_set_sensitive (sp->remote_debug_action, FALSE); + break; + case TARGET_STATE_READY: + /* Can only turn on if have a project */ + if (sp->project_root_uri) + gtk_action_set_sensitive (sp->deploy_action, TRUE); + + if (anjuta_util_prog_is_installed ("oprofile-viewer", FALSE)) + gtk_action_set_sensitive (sp->remote_profile_action, TRUE); + + gtk_action_set_sensitive (sp->qemu_shutdown_action, TRUE); + gtk_action_set_sensitive (sp->remote_run_action, TRUE); + gtk_action_set_sensitive (sp->remote_debug_action, TRUE); + break; + } +} + static gboolean anjuta_plugin_sdk_activate (AnjutaPlugin *plugin) { AnjutaPluginSdk *sp = (AnjutaPluginSdk *)plugin; AnjutaUI *ui; GError *error = NULL; + IAnjutaMessageManager *msg_manager; + gchar *kernel = NULL; + gchar *rootfs = NULL; ui = anjuta_shell_get_ui (ANJUTA_PLUGIN (plugin)->shell, NULL); @@ -1583,16 +1519,28 @@ anjuta_plugin_sdk_activate (AnjutaPlugin *plugin) sp->sdk_root = anjuta_preferences_get (sp->prefs, PREFS_PROP_SDK_ROOT); sp->triplet = anjuta_preferences_get (sp->prefs, PREFS_PROP_TRIPLET); - sp->kernel = anjuta_preferences_get (sp->prefs, PREFS_PROP_KERNEL); - sp->rootfs = anjuta_preferences_get (sp->prefs, PREFS_PROP_ROOTFS); + sp->poky_root = anjuta_preferences_get (sp->prefs, PREFS_PROP_POKY_ROOT); sp->poky_mode = anjuta_preferences_get_int (sp->prefs, PREFS_PROP_POKY_MODE); - if (sp->kernel == NULL || sp->rootfs == NULL) + msg_manager = anjuta_shell_get_interface (ANJUTA_PLUGIN (sp)->shell, + IAnjutaMessageManager, &error); + + if (!msg_manager) { - gtk_action_set_sensitive (sp->qemu_start_action, FALSE); + g_warning ("Error getting implementation of IAnjutaMessageManager: %s", + error->message); + g_clear_error (&error); } + sp->target = beaver_target_qemu_new (ANJUTA_PLUGIN (plugin)->shell); + g_signal_connect (sp->target, "state-changed", + (GCallback)target_state_changed_cb, sp); + + kernel = anjuta_preferences_get (sp->prefs, PREFS_PROP_KERNEL); + rootfs = anjuta_preferences_get (sp->prefs, PREFS_PROP_ROOTFS); + g_object_set (sp->target, "kernel", kernel, "rootfs", rootfs, NULL); + update_environment (sp); setup_buildable (sp); @@ -1630,19 +1578,12 @@ anjuta_plugin_sdk_deactivate (AnjutaPlugin *plugin) sp->deploy_msg_view = NULL; } - if (sp->qemu_msg_view) - { - ianjuta_message_manager_remove_view (msg_manager, sp->qemu_msg_view, NULL); - sp->qemu_msg_view = NULL; - } - if (sp->remote_msg_view) { ianjuta_message_manager_remove_view (msg_manager, sp->remote_msg_view, NULL); sp->remote_msg_view = NULL; } - if (sp->buildable) { ianjuta_buildable_reset_commands (sp->buildable, &error); @@ -1667,7 +1608,6 @@ anjuta_plugin_sdk_deactivate (AnjutaPlugin *plugin) g_signal_handlers_disconnect_by_func (plugin->shell, shell_session_load_cb, sp); g_signal_handlers_disconnect_by_func (plugin->shell, shell_session_save_cb, sp); - /* * Do lots of things you'd normally expect to see in a dispose/finalize, * i.e. to free up memory but because a plugin won't get disposed/finalized @@ -1680,12 +1620,6 @@ anjuta_plugin_sdk_deactivate (AnjutaPlugin *plugin) sp->deploy_launcher = NULL; } - if (sp->qemu_launcher) - { - g_object_unref (sp->qemu_launcher); - sp->qemu_launcher = NULL; - } - if (sp->remote_launcher) { g_object_unref (sp->remote_launcher); @@ -1710,6 +1644,12 @@ anjuta_plugin_sdk_deactivate (AnjutaPlugin *plugin) sp->prefs_icon = NULL; } + if (sp->target) + { + g_object_unref (sp->target); + sp->target = NULL; + } + /* * Must set these to NULL because the plugin object might get reused after * deactivation. diff --git a/src/plugin.h b/src/plugin.h index 07a8c95..fd0d0b2 100644 --- a/src/plugin.h +++ b/src/plugin.h @@ -23,6 +23,9 @@ #include <libanjuta/interfaces/ianjuta-buildable.h> #include <libanjuta/anjuta-launcher.h> +#include "beaver-target.h" +#include "beaver-target-qemu.h" + typedef struct _AnjutaPluginSdk AnjutaPluginSdk; typedef struct _AnjutaPluginSdkClass AnjutaPluginSdkClass; @@ -66,9 +69,6 @@ struct _AnjutaPluginSdk guint poky_root_notifyid; guint poky_mode_notifyid; - guint update_environment_idle; - guint qemu_settings_changed_idle; - guint remote_gdb_timeout; gchar *triplet; @@ -92,11 +92,9 @@ struct _AnjutaPluginSdk gchar *project_root_uri; IAnjutaMessageView *deploy_msg_view; - IAnjutaMessageView *qemu_msg_view; IAnjutaMessageView *remote_msg_view; AnjutaLauncher *deploy_launcher; - AnjutaLauncher *qemu_launcher; AnjutaLauncher *remote_launcher; AnjutaLauncher *remote_gdb_launcher; AnjutaLauncher *oprofileui_launcher; @@ -123,6 +121,8 @@ struct _AnjutaPluginSdk gchar *remote_command; IAnjutaBuildable *buildable; + + BeaverTarget *target; }; struct _AnjutaPluginSdkClass |