00001 #include <dbus/dbus-glib.h>
00002 #include <stdio.h>
00003 #include <stdlib.h>
00004
00005 #include "statemachine.h"
00006 #include "sm-marshal.h"
00007 #include "statemachine-server.h"
00008
00009 enum
00010 {
00011 PROP_O,
00012 PROP_BUS
00013 };
00014
00015 enum
00016 {
00017 MACHINE_CREATED,
00018 LAST_SIGNAL
00019 };
00020
00021 static guint sm_server_signals[LAST_SIGNAL] = { 0 };
00022
00023 static void sm_server_set_property (GObject *object,
00024 guint prop_id,
00025 const GValue *value,
00026 GParamSpec *pspec);
00027 static void sm_server_get_property (GObject *object,
00028 guint prop_id,
00029 GValue *value,
00030 GParamSpec *pspec);
00031
00032 G_DEFINE_TYPE(SMServer, sm_server, G_TYPE_OBJECT)
00033
00034 #include "statemachine-server-glue.h"
00035 #include "statemachine-glue.h"
00036
00037 static void
00038 sm_server_init (SMServer *obj)
00039 {
00040 obj->machines = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
00041 }
00042
00043 static void
00044 sm_server_class_init (SMServerClass *klass)
00045 {
00046 GObjectClass *object_class = G_OBJECT_CLASS (klass);
00047
00048 object_class->set_property = sm_server_set_property;
00049 object_class->get_property = sm_server_get_property;
00050
00051 g_object_class_install_property (object_class,
00052 PROP_BUS,
00053 g_param_spec_boxed ("bus",
00054 "bus",
00055 "bus",
00056 DBUS_TYPE_G_CONNECTION,
00057 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
00058
00059 sm_server_signals[MACHINE_CREATED] =
00060 g_signal_new ("machine-created",
00061 G_OBJECT_CLASS_TYPE (klass),
00062 G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
00063 0,
00064 NULL, NULL,
00065 sm_marshal_VOID__STRING_BOXED,
00066 G_TYPE_NONE, 2, G_TYPE_STRING, DBUS_TYPE_G_OBJECT_PATH);
00067 }
00068
00069 static void
00070 sm_server_set_property (GObject *object,
00071 guint prop_id,
00072 const GValue *value,
00073 GParamSpec *pspec)
00074 {
00075 SMServer *server = SM_SERVER (object);
00076
00077 switch (prop_id)
00078 {
00079 case PROP_BUS:
00080 server->bus = g_value_get_boxed (value);
00081 break;
00082 default:
00083 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
00084 break;
00085 }
00086 }
00087
00088 static void
00089 sm_server_get_property (GObject *object,
00090 guint prop_id,
00091 GValue *value,
00092 GParamSpec *pspec)
00093 {
00094 SMServer *server = SM_SERVER (object);
00095
00096 switch (prop_id)
00097 {
00098 case PROP_BUS:
00099 g_value_set_boxed (value, server->bus);
00100 break;
00101 default:
00102 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
00103 break;
00104 }
00105 }
00106
00107 static void
00108 machine_state_changed_cb (SMObject *obj, const char *state, gpointer data)
00109 {
00110 char *name;
00111
00112 g_object_get (obj, "name", &name, NULL);
00113 g_print ("Machine %s switching to state %s\n", name, state);
00114 g_free (name);
00115 }
00116
00117 static void
00118 machine_acquisition_changed_cb (SMObject *obj, gdouble progress, gpointer data)
00119 {
00120 char *name;
00121
00122 g_object_get (obj, "name", &name, NULL);
00123 g_print ("Machine %s got progress %f\n", name, progress);
00124 g_free (name);
00125 }
00126
00127 gboolean
00128 sm_server_create_machine (SMServer *server, const char *name, GError **error)
00129 {
00130 SMObject *machine;
00131 char *path;
00132
00133 machine = g_hash_table_lookup (server->machines, name);
00134 if (machine != NULL)
00135 {
00136 g_set_error (error,
00137 SM_ERROR,
00138 SM_ERROR_NAME_IN_USE,
00139 "Statemachine name \"%s\" is already in use",
00140 name);
00141 return FALSE;
00142 }
00143
00144 machine = g_object_new (SM_TYPE_OBJECT, "name", name, NULL);
00145
00146 path = g_strdup_printf ("/com/example/StateMachines/%s", name);
00147 dbus_g_connection_register_g_object (server->bus, path, G_OBJECT (machine));
00148
00149 g_hash_table_insert (server->machines, g_strdup (name), machine);
00150
00151 g_print ("Created state machine with name %s at %s\n", name, path);
00152
00153 g_signal_connect_object (machine, "state-changed",
00154 G_CALLBACK (machine_state_changed_cb),
00155 NULL, 0);
00156 g_signal_connect_object (machine, "acquisition-progress",
00157 G_CALLBACK (machine_acquisition_changed_cb),
00158 NULL, 0);
00159
00160 g_signal_emit (server, sm_server_signals[MACHINE_CREATED], 0, name, path);
00161
00162 return TRUE;
00163 }
00164
00165 static void
00166 add_machine_to_ptr_array (gpointer key, gpointer val, gpointer data)
00167 {
00168 const char *name = key;
00169
00170 GPtrArray *ptrarray = data;
00171
00172 g_ptr_array_add (ptrarray, g_strdup_printf ("/com/example/StateMachines/%s",
00173 name));
00174 }
00175
00176 gboolean
00177 sm_server_get_machines (SMServer *server, GPtrArray **machines, GError **error)
00178 {
00179 *machines = g_ptr_array_new ();
00180
00181 g_hash_table_foreach (server->machines, add_machine_to_ptr_array, *machines);
00182
00183 return TRUE;
00184 }
00185
00186 int
00187 main (int argc, char **argv)
00188 {
00189 DBusGConnection *bus;
00190 DBusGProxy *bus_proxy;
00191 GError *error = NULL;
00192 SMServer *server;
00193 GMainLoop *mainloop;
00194 guint request_name_result;
00195
00196 g_type_init ();
00197
00198 dbus_g_object_type_install_info (SM_TYPE_SERVER, &dbus_glib_sm_server_object_info);
00199 dbus_g_object_type_install_info (SM_TYPE_OBJECT, &dbus_glib_sm_object_object_info);
00200 dbus_g_error_domain_register (SM_ERROR, NULL, SM_TYPE_ERROR);
00201
00202 mainloop = g_main_loop_new (NULL, FALSE);
00203
00204 bus = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
00205 if (!bus)
00206 g_critical ("Couldn't connect to session bus: %s\n", error->message);
00207
00208 bus_proxy = dbus_g_proxy_new_for_name (bus, "org.freedesktop.DBus",
00209 "/org/freedesktop/DBus",
00210 "org.freedesktop.DBus");
00211
00212 if (!dbus_g_proxy_call (bus_proxy, "RequestName", &error,
00213 G_TYPE_STRING, "com.example.StateServer",
00214 G_TYPE_UINT, 0,
00215 G_TYPE_INVALID,
00216 G_TYPE_UINT, &request_name_result,
00217 G_TYPE_INVALID))
00218 g_critical ("Couldn't acquire com.example.StateServer: %s\n", error->message);
00219
00220 server = g_object_new (SM_TYPE_SERVER, "bus", bus, NULL);
00221
00222 dbus_g_connection_register_g_object (bus, "/com/example/StateServer", G_OBJECT (server));
00223
00224 g_print ("StateMachine server initialized\n");
00225
00226 g_main_loop_run (mainloop);
00227
00228 exit (0);
00229 }