2 * This file is part of buxton.
4 * Copyright (C) 2013 Intel Corporation
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice shall be
15 * included in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
21 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 #include <glib-unix.h>
32 #include "gtk_client.h"
34 /* BuxtonTest object */
39 GtkWidget *info_label;
41 GtkWidget *value_label;
47 /* BuxtonTest class definition */
48 struct _BuxtonTestClass {
49 GtkWindowClass parent_class;
52 G_DEFINE_TYPE(BuxtonTest, buxton_test, GTK_TYPE_WINDOW)
54 /* Boilerplate GObject code */
55 static void buxton_test_class_init(BuxtonTestClass *klass);
56 static void buxton_test_init(BuxtonTest *self);
57 static void buxton_test_dispose(GObject *object);
59 static void update_key(GtkWidget *self, gpointer userdata);
60 static void update_value(BuxtonTest *self);
61 static void report_error(BuxtonTest *self, gchar *error);
62 static void buxton_callback(BuxtonResponse response, gpointer userdata);
63 static gboolean buxton_update(gint fd, GIOCondition cond, gpointer userdata);
68 static gboolean buxton_init(BuxtonTest *self);
71 static void buxton_test_class_init(BuxtonTestClass *klass)
73 GObjectClass *g_object_class;
75 g_object_class = G_OBJECT_CLASS(klass);
76 g_object_class->dispose = &buxton_test_dispose;
79 static void buxton_test_init(BuxtonTest *self)
81 GtkWidget *info, *layout;
82 GtkWidget *label, *container, *box, *box2;
83 GtkWidget *entry, *button;
84 GtkStyleContext *style;
87 g_signal_connect(self, "destroy", gtk_main_quit, NULL);
88 gtk_window_set_default_size(GTK_WINDOW(self), 700, 300);
89 gtk_window_set_title(GTK_WINDOW(self), "BuxtonTest");
92 layout = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
93 gtk_container_add(GTK_CONTAINER(self), layout);
95 info = gtk_info_bar_new();
96 label = gtk_label_new("Connecting");
97 self->info_label = label;
99 container = gtk_info_bar_get_content_area(GTK_INFO_BAR(info));
100 gtk_container_add(GTK_CONTAINER(container), label);
101 gtk_box_pack_start(GTK_BOX(layout), info, FALSE, FALSE, 0);
104 label = gtk_label_new("<big>"
105 "Using the controls below, you can set a key within the\n"
106 "<b>user</b> layer. Open another instance of this client to\n"
107 "check notification support.</big>");
108 gtk_label_set_use_markup(GTK_LABEL(label), TRUE);
109 gtk_box_pack_start(GTK_BOX(layout), label, FALSE, FALSE, 10);
111 box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
112 gtk_widget_set_valign(box, GTK_ALIGN_CENTER);
113 gtk_widget_set_halign(box, GTK_ALIGN_CENTER);
114 gtk_box_pack_start(GTK_BOX(layout), box, TRUE, TRUE, 0);
116 /* Updated to key value */
117 label = gtk_label_new("<big>\'test\' value:</big>");
118 self->value_label = label;
119 gtk_label_set_use_markup(GTK_LABEL(label), TRUE);
120 gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 10);
122 box2 = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
123 style = gtk_widget_get_style_context(box2);
124 gtk_style_context_add_class(style, GTK_STYLE_CLASS_LINKED);
125 gtk_box_pack_start(GTK_BOX(box), box2, TRUE, TRUE, 0);
127 /* Give entry and button a linked effect */
128 entry = gtk_entry_new();
130 gtk_entry_set_placeholder_text(GTK_ENTRY(self->entry),
132 g_signal_connect(entry, "activate", G_CALLBACK(update_key), self);
133 gtk_box_pack_start(GTK_BOX(box2), entry, TRUE, TRUE, 0);
135 button = gtk_button_new_with_label("Update");
136 g_signal_connect(button, "clicked", G_CALLBACK(update_key), self);
137 gtk_box_pack_start(GTK_BOX(box2), button, FALSE, FALSE, 0);
139 gtk_widget_show_all(GTK_WIDGET(self));
140 gtk_widget_grab_focus(button);
143 self->setting = FALSE;
144 gtk_widget_hide(info);
146 /* Attempt connection to Buxton */
147 if (!buxton_init(self)) {
148 gtk_info_bar_set_message_type(GTK_INFO_BAR(info),
150 gtk_label_set_markup(GTK_LABEL(self->info_label), "No connection!");
151 gtk_widget_show(info);
157 static void buxton_test_dispose(GObject *object)
159 BuxtonTest *self = BUXTON_TEST(object);
161 g_source_remove(self->tag);
165 buxton_close(self->client);
169 G_OBJECT_CLASS (buxton_test_parent_class)->dispose (object);
172 /* Utility; return a new BuxtonTest */
173 GtkWidget* buxton_test_new(void)
177 self = g_object_new(BUXTON_TEST_TYPE, NULL);
178 return GTK_WIDGET(self);
180 static gboolean buxton_init(BuxtonTest *self)
185 /* Bail if initialized */
189 /* Stop probing Buxton */
191 g_source_remove(self->tag);
195 fd = buxton_open(&self->client);
201 /* Poll Buxton events on idle loop, Buxton will then dispatch them
202 * to appropriate callbacks */
203 self->tag = g_unix_fd_add(self->fd, G_IO_IN | G_IO_PRI | G_IO_HUP,
204 buxton_update, self->client);
206 /* Register primary key */
207 key = buxton_key_create(GROUP, PRIMARY_KEY, LAYER, STRING);
208 if (buxton_register_notification(self->client, key,
209 buxton_callback, self, false)) {
210 report_error(self, "Unable to register for notifications");
216 static void update_key(GtkWidget *widget, gpointer userdata)
218 BuxtonTest *self = BUXTON_TEST(userdata);
222 value = gtk_entry_get_text(GTK_ENTRY(self->entry));
223 if (strlen(value) == 0 || g_str_equal(value, "")) {
227 key = buxton_key_create(GROUP, PRIMARY_KEY, LAYER, STRING);
229 self->setting = TRUE;
230 if (buxton_set_value(self->client, key, (void*)value,
231 buxton_callback, self, false)) {
232 report_error(self, "Unable to set value!");
234 buxton_key_free(key);
237 static void update_value(BuxtonTest *self)
241 key = buxton_key_create(GROUP, PRIMARY_KEY, LAYER, STRING);
243 if (buxton_get_value(self->client, key,
244 buxton_callback, self, false)) {
245 /* Buxton disconnects us when this happens. ##FIXME##
246 * We force a reconnect */
247 report_error(self, "Cannot retrieve value");
248 buxton_close(self->client);
250 /* Just try reconnecting */
251 if (!buxton_init(self)) {
252 report_error(self, "Unable to connect");
257 buxton_key_free(key);
260 static void report_error(BuxtonTest *self, gchar *error)
263 printf("Error! %s\n", error);
264 gtk_label_set_markup(GTK_LABEL(self->info_label), error);
265 gtk_widget_show_all(GTK_WIDGET(self->info));
266 gtk_info_bar_set_message_type(GTK_INFO_BAR(self->info),
269 gtk_widget_hide(GTK_WIDGET(self->info));
273 static gboolean buxton_update(gint fd, GIOCondition cond, gpointer userdata)
275 BuxtonClient client = (BuxtonClient)userdata;
276 ssize_t handled = buxton_client_handle_response(client);
277 return (handled >= 0);
280 static void buxton_callback(BuxtonResponse response, gpointer userdata)
285 gchar *key_name = NULL;
286 self = BUXTON_TEST(userdata);
288 /* Handle all potential async cases we're utilizing */
289 if (buxton_response_status(response) != 0) {
290 switch (buxton_response_type(response)) {
291 case BUXTON_CONTROL_GET:
292 report_error(self, "Cannot retrieve value");
294 case BUXTON_CONTROL_SET:
295 self->setting = FALSE;
296 report_error(self, "Unable to set value");
298 case BUXTON_CONTROL_CHANGED:
299 report_error(self, "Unable to get notification value");
301 case BUXTON_CONTROL_NOTIFY:
302 report_error(self, "Unable to register for notification");
305 report_error(self, "Unhandled error!");
310 self->setting = FALSE;
314 key = buxton_response_key(response);
315 key_name = buxton_key_get_name(key);
316 value = buxton_response_value(response);
318 /* Handle PRIMARY_KEY (string) */
319 if (g_str_equal(key_name, PRIMARY_KEY) && buxton_key_get_type(key) == STRING) {
323 lab = g_strdup_printf("<big>\'%s\' unset</big>", key_name);
325 lab = g_strdup_printf("<big>\'%s\' value: %s</big>",
326 key_name, (gchar*)value);
329 gtk_label_set_markup(GTK_LABEL(self->value_label), lab);
335 buxton_key_free(key);
339 int main(int argc, char **argv)
341 __attribute__ ((unused)) GtkWidget *window = NULL;
343 gtk_init(&argc, &argv);
344 window = buxton_test_new();