From 0ccef79d7e9d1b19cdb10b3a147b64b41686905d Mon Sep 17 00:00:00 2001 From: Colin Walters Date: Sat, 9 Jul 2005 01:46:51 +0000 Subject: 2005-07-08 Colin Walters * test/glib/test-service-glib.xml: * test/glib/test-service-glib.c: * test/glib/test-dbus-glib.c: Test a{sv}. * glib/examples/statemachine/statemachine.c: * glib/examples/statemachine/statemachine-server.c: * glib/examples/statemachine/statemachine-client.c: Fix some bugs, add progress bar, etc. * glib/dbus-gvalue.c (register_array, register_dict): Delete; not needed anymore due to generic array/map marshalling. (dbus_g_value_types_init): Don't register basic arrays or the string/string hash. (dbus_gtype_from_signature_iter): Don't try to recurse into variants. (dbus_gtype_to_signature): Check collection/map before type metadata. (demarshal_garray_basic): Renamed to demarshal_collection_array. (demarshal_ghashtable): Renamed to demarshal_map; fix to use new generic map creation/append functions instead of hash table specifically. (get_type_demarshaller): Handle maps. (demarshal_collection): Dispatch on collection type to either demarshal_collection_ptrarray or demarshal_collection_array. (get_type_marshaller): Handle maps. (marshal_collection): Dispatch collection type to either marshal_collection_ptrarray or marshal_collection_array. (_dbus_gvalue_test): New test. * glib/dbus-gvalue-utils.c (unset_and_free_g_value): New function. (hash_free_from_gtype): Use it to free GValues. (hashtable_append): New function. (ptrarray_append): Fix prototype. (slist_append): Ditto. (_dbus_gvalue_utils_test): Extend tests. * glib/dbus-gtype-specialized.c (dbus_g_type_specialized_init_append): Renamed from dbus_g_type_specialized_collection_init_append. Remove const from value, since we steal it. (dbus_g_type_specialized_map_append): New function. * glib/dbus-gtype-specialized.h: Update prototypes. Add DBusGTypeSpecializedMapAppendFunc. * glib/dbus-gtest.c (dbus_glib_internal_do_not_use_run_tests): Run _dbus_gvalue_test. * glib/dbus-gtest.h: Prototype it. --- glib/examples/statemachine/statemachine-client.c | 192 ++++++++++++++++++----- glib/examples/statemachine/statemachine-server.c | 27 ++++ glib/examples/statemachine/statemachine.c | 44 +++--- 3 files changed, 207 insertions(+), 56 deletions(-) (limited to 'glib/examples') diff --git a/glib/examples/statemachine/statemachine-client.c b/glib/examples/statemachine/statemachine-client.c index 54c630ff..88b21847 100644 --- a/glib/examples/statemachine/statemachine-client.c +++ b/glib/examples/statemachine/statemachine-client.c @@ -59,8 +59,9 @@ typedef struct { char *name; char *state; + gdouble progress; DBusGProxy *proxy; - DBusGProxyCall *get_initial_state_call; + DBusGProxyCall *get_progress_call; } MachineInfo; typedef struct @@ -90,6 +91,15 @@ proxy_to_iter (GtkTreeModel *model, DBusGProxy *proxy, GtkTreeIter *iter) return FALSE; } +static void +signal_row_change (ClientState *state, GtkTreeIter *iter) +{ + GtkTreePath *path; + path = gtk_tree_model_get_path (state->store, iter); + gtk_tree_model_row_changed (state->store, path, iter); + gtk_tree_path_free (path); +} + static void get_machine_info_cb (DBusGProxy *proxy, DBusGProxyCall *call, @@ -115,13 +125,67 @@ get_machine_info_cb (DBusGProxy *proxy, info->name = name; g_free (info->state); info->state = statename; - { - GtkTreePath *path; - path = gtk_tree_model_get_path (state->store, &iter); - gtk_tree_model_row_changed (state->store, path, &iter); - gtk_tree_path_free (path); - } - info->get_initial_state_call = NULL; + signal_row_change (state, &iter); +} + +static void +set_proxy_acquisition_progress (ClientState *state, + DBusGProxy *proxy, + double progress) +{ + MachineInfo *info; + GtkTreeIter iter; + + if (!proxy_to_iter (state->store, proxy, &iter)) + g_assert_not_reached (); + gtk_tree_model_get (state->store, &iter, 0, &info, -1); + + /* Ignore machines in unknown state */ + if (!info->state) + return; + + if (strcmp (info->state, "Acquired")) + lose ("Got AcquisitionProgress signal in bad state %s", + info->state); + + g_print ("Got acquisition progress change for %p (%s) to %f\n", proxy, info->name ? info->name : "(unknown)", progress); + + info->progress = progress; + + signal_row_change (state, &iter); +} + +static void +proxy_acquisition_changed_cb (DBusGProxy *proxy, + double progress, + gpointer user_data) +{ + set_proxy_acquisition_progress (user_data, proxy, progress); +} + +static void +get_acquiring_progress_cb (DBusGProxy *proxy, + DBusGProxyCall *call, + gpointer user_data) +{ + GError *error = NULL; + MachineInfo *info; + GtkTreeIter iter; + ClientState *state = user_data; + gdouble progress; + + if (!proxy_to_iter (state->store, proxy, &iter)) + g_assert_not_reached (); + gtk_tree_model_get (state->store, &iter, 0, &info, -1); + + g_assert (info->get_progress_call == call); + + if (!dbus_g_proxy_end_call (proxy, call, &error, + G_TYPE_DOUBLE, &progress, G_TYPE_INVALID)) + lose_gerror ("Failed to complete GetAcquiringProgress call", error); + info->get_progress_call = NULL; + + set_proxy_acquisition_progress (state, proxy, progress); } static void @@ -139,25 +203,27 @@ proxy_state_changed_cb (DBusGProxy *proxy, g_print ("Got state change for %p (%s) to %s\n", proxy, info->name ? info->name : "(unknown)", statename); - /* If we got a signal for the state, we shouldn't update - * based on the (possibly stale) call - */ - if (info->get_initial_state_call != NULL) - { - g_print ("Cancelling outstanding GetInfo call for %p due to signal\n", proxy); - dbus_g_proxy_cancel_call (proxy, info->get_initial_state_call); - info->get_initial_state_call = NULL; - } - g_free (info->state); info->state = g_strdup (statename); - { - GtkTreePath *path; - path = gtk_tree_model_get_path (state->store, &iter); - gtk_tree_model_row_changed (state->store, path, &iter); - gtk_tree_path_free (path); - } + if (!strcmp (info->state, "Acquired")) + { + g_print ("Starting GetAcquiringProgress call for %p\n", info->proxy); + if (info->get_progress_call != NULL) + { + dbus_g_proxy_cancel_call (info->proxy, info->get_progress_call); + info->get_progress_call = NULL; + } + info->get_progress_call = + dbus_g_proxy_begin_call (info->proxy, "GetAcquiringProgress", + get_acquiring_progress_cb, + state, NULL, + G_TYPE_INVALID); + } + else + info->progress = 0.0; + + signal_row_change (state, &iter); } static void @@ -172,6 +238,7 @@ add_machine (ClientState *state, info = g_new0 (MachineInfo, 1); info->name = g_strdup (name); info->state = g_strdup (mstate); + info->progress = 0.0; info->proxy = dbus_g_proxy_new_for_name (state->bus, "com.example.StateServer", @@ -181,14 +248,11 @@ add_machine (ClientState *state, if (!info->state) { g_print ("Starting GetInfo call for %p\n", info->proxy); - info->get_initial_state_call - = dbus_g_proxy_begin_call (info->proxy, "GetInfo", - get_machine_info_cb, - state, NULL, - G_TYPE_INVALID); + dbus_g_proxy_begin_call (info->proxy, "GetInfo", + get_machine_info_cb, + state, NULL, + G_TYPE_INVALID); } - else - info->get_initial_state_call = NULL; /* Watch for state changes */ dbus_g_proxy_add_signal (info->proxy, "StateChanged", @@ -200,6 +264,15 @@ add_machine (ClientState *state, state, NULL); + dbus_g_proxy_add_signal (info->proxy, "AcquisitionProgress", + G_TYPE_DOUBLE, G_TYPE_INVALID); + + dbus_g_proxy_connect_signal (info->proxy, + "AcquisitionProgress", + G_CALLBACK (proxy_acquisition_changed_cb), + state, + NULL); + gtk_list_store_prepend (GTK_LIST_STORE (state->store), &iter); gtk_list_store_set (GTK_LIST_STORE (state->store), &iter, 0, info, -1); @@ -306,6 +379,12 @@ do_a_state_change (ClientState *state) g_print ("Sending Start request to machine %s\n", info->name); dbus_g_proxy_call_no_reply (info->proxy, "Start", G_TYPE_INVALID); } + else if (!strcmp (info->state, "Loading")) + { + + g_print ("Sending Reacquire request to machine %s\n", info->name); + dbus_g_proxy_call_no_reply (info->proxy, "Reacquire", G_TYPE_INVALID); + } else { g_print ("Sending Shutdown request to machine %s\n", info->name); @@ -318,7 +397,7 @@ do_something_random_2 (gpointer data) { ClientState *state = data; do_a_state_change (state); - g_timeout_add (g_random_int_range (500, 3000), do_something_random_2, state); + g_timeout_add (g_random_int_range (2000, 5000), do_something_random_2, state); return FALSE; } @@ -328,12 +407,13 @@ do_something_random (gpointer data) ClientState *state = data; gint n_children; - switch (g_random_int_range (0, 2)) + switch (g_random_int_range (0, 3)) { case 0: send_create_machine (state); break; case 1: + case 2: do_a_state_change (state); break; default: @@ -341,8 +421,11 @@ do_something_random (gpointer data) } n_children = gtk_tree_model_iter_n_children (state->store, NULL); - if (n_children >= 8) - g_timeout_add (g_random_int_range (500, 3000), do_something_random_2, state); + if (n_children >= 5) + { + g_print ("MAX children reached, switching to state changes only\n"); + g_timeout_add (g_random_int_range (500, 3000), do_something_random_2, state); + } else g_timeout_add (g_random_int_range (500, 3000), do_something_random, state); return FALSE; @@ -406,6 +489,34 @@ sort_by_state (GtkTreeModel *model, info_b ? info_b->state : ""); } +static void +set_cell_progress (GtkTreeViewColumn *tree_column, + GtkCellRenderer *cell, + GtkTreeModel *tree_model, + GtkTreeIter *iter, + gpointer data) +{ + MachineInfo *info; + + gtk_tree_model_get (tree_model, iter, 0, &info, -1); + + g_object_set (cell, "value", (int) (info->progress * 100), NULL); +} + +static gint +sort_by_progress (GtkTreeModel *model, + GtkTreeIter *a, + GtkTreeIter *b, + gpointer user_data) +{ + MachineInfo *info_a, *info_b; + + gtk_tree_model_get (model, a, 0, &info_a, -1); + gtk_tree_model_get (model, b, 0, &info_b, -1); + + return info_a->progress > info_b->progress ? 1 : -1; +} + static void get_machines_cb (DBusGProxy *proxy, DBusGProxyCall *call, gpointer data) { @@ -458,6 +569,17 @@ get_machines_cb (DBusGProxy *proxy, DBusGProxyCall *call, gpointer data) 0, sort_by_state, NULL, NULL); gtk_tree_view_column_set_sort_column_id (col, 0); gtk_tree_view_append_column (GTK_TREE_VIEW (state->view), col); + + rend = gtk_cell_renderer_progress_new (); + col = gtk_tree_view_column_new_with_attributes (_("Progress"), + rend, + NULL); + gtk_tree_view_column_set_cell_data_func (col, rend, set_cell_progress, NULL, NULL); + gtk_tree_view_column_set_resizable (col, TRUE); + gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (state->store), + 0, sort_by_progress, NULL, NULL); + gtk_tree_view_column_set_sort_column_id (col, 0); + gtk_tree_view_append_column (GTK_TREE_VIEW (state->view), col); for (i = 0; i < objs->len; i++) { diff --git a/glib/examples/statemachine/statemachine-server.c b/glib/examples/statemachine/statemachine-server.c index 7cadf1fe..2cbf39fe 100644 --- a/glib/examples/statemachine/statemachine-server.c +++ b/glib/examples/statemachine/statemachine-server.c @@ -104,6 +104,26 @@ sm_server_get_property (GObject *object, } } +static void +machine_state_changed_cb (SMObject *obj, const char *state, gpointer data) +{ + char *name; + + g_object_get (obj, "name", &name, NULL); + g_print ("Machine %s switching to state %s\n", name, state); + g_free (name); +} + +static void +machine_acquisition_changed_cb (SMObject *obj, gdouble progress, gpointer data) +{ + char *name; + + g_object_get (obj, "name", &name, NULL); + g_print ("Machine %s got progress %f\n", name, progress); + g_free (name); +} + gboolean sm_server_create_machine (SMServer *server, const char *name, GError **error) { @@ -130,6 +150,13 @@ sm_server_create_machine (SMServer *server, const char *name, GError **error) g_print ("Created state machine with name %s at %s\n", name, path); + g_signal_connect_object (machine, "state-changed", + G_CALLBACK (machine_state_changed_cb), + NULL, 0); + g_signal_connect_object (machine, "acquisition-progress", + G_CALLBACK (machine_acquisition_changed_cb), + NULL, 0); + g_signal_emit (server, sm_server_signals[MACHINE_CREATED], 0, name, path); return TRUE; diff --git a/glib/examples/statemachine/statemachine.c b/glib/examples/statemachine/statemachine.c index 2bde0058..c94e2945 100644 --- a/glib/examples/statemachine/statemachine.c +++ b/glib/examples/statemachine/statemachine.c @@ -103,8 +103,8 @@ sm_object_state_get_type (void) ENUM_ENTRY (SM_OBJECT_STATE_SHUTDOWN, "Shutdown"), ENUM_ENTRY (SM_OBJECT_STATE_INITIALIZED, "Loading"), - ENUM_ENTRY (SM_OBJECT_STATE_ACQUIRED, "Resource acquired"), - ENUM_ENTRY (SM_OBJECT_STATE_OPERATING, "Operating normally"), + ENUM_ENTRY (SM_OBJECT_STATE_ACQUIRED, "Acquired"), + ENUM_ENTRY (SM_OBJECT_STATE_OPERATING, "Operating"), { 0, 0, 0 } }; @@ -175,6 +175,21 @@ sm_object_get_property (GObject *object, } } +static const char * +state_to_string (SMObjectState state) +{ + GEnumValue *value; + GEnumClass *prop_class; + const char *ret; + + prop_class = g_type_class_ref (SM_TYPE_OBJECT_STATE); + value = g_enum_get_value (prop_class, state); + ret = value->value_nick; + + g_type_class_unref (prop_class); + return ret; +} + static void queue_task (SMObject *object, guint delay, GSourceFunc func) { @@ -188,6 +203,8 @@ idle_state_change (gpointer data) { SMObject *object = data; + g_print ("doing idle state change for %s to %s\n", + object->name, state_to_string (object->requested_state)); state_change (object, object->requested_state); return FALSE; } @@ -197,7 +214,8 @@ idle_further_acquire (gpointer data) { SMObject *object = data; - object->acquisition_progress += g_random_double_range (0.05, 0.5); + g_print ("doing idle acquisition for machine %s\n", object->name); + object->acquisition_progress += g_random_double_range (0.20, 0.7); if (object->acquisition_progress > 1.0) { object->acquisition_progress = 1.0; @@ -220,26 +238,10 @@ clear_pending_tasks (SMObject *object) object->pending_tasks = NULL; } -static const char * -state_to_string (SMObjectState state) -{ - GEnumValue *value; - GEnumClass *prop_class; - const char *ret; - - prop_class = g_type_class_ref (SM_TYPE_OBJECT_STATE); - value = g_enum_get_value (prop_class, state); - ret = value->value_nick; - - g_type_class_unref (prop_class); - return ret; -} - static void state_change (SMObject *object, SMObjectState new_state) { g_signal_emit (object, sm_object_signals[STATE_CHANGED], 0, - state_to_string (object->state), state_to_string (new_state)); clear_pending_tasks (object); @@ -288,7 +290,7 @@ sm_object_start (SMObject *object, GError **error) gboolean sm_object_shutdown (SMObject *object, GError **error) { - if (object->state != SM_OBJECT_STATE_INITIALIZED) + if (object->state == SM_OBJECT_STATE_SHUTDOWN) { g_set_error (error, SM_ERROR, @@ -321,7 +323,7 @@ sm_object_reinitialize (SMObject *object, GError **error) gboolean sm_object_reacquire (SMObject *object, GError **error) { - if (object->state != SM_OBJECT_STATE_ACQUIRED) + if (object->state == SM_OBJECT_STATE_ACQUIRED) { g_set_error (error, SM_ERROR, -- cgit