tizen 2.3.1 release
[external/buxton.git] / demo / gtk_client.c
1 /*
2  * This file is part of buxton.
3  *
4  * Copyright (C) 2013 Intel Corporation
5  *
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:
13  *
14  * The above copyright notice and this permission notice shall be
15  * included in all copies or substantial portions of the Software.
16  *
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.
24  *
25  */
26
27 #include <stdlib.h>
28 #include <string.h>
29 #include <glib-unix.h>
30
31 #include "buxton.h"
32 #include "gtk_client.h"
33
34 /* BuxtonTest object */
35 struct _BuxtonTest {
36         GtkWindow parent;
37         BuxtonClient client;
38         gint fd;
39         GtkWidget *info_label;
40         GtkWidget *info;
41         GtkWidget *value_label;
42         GtkWidget *entry;
43         guint tag;
44         gboolean setting;
45 };
46
47 /* BuxtonTest class definition */
48 struct _BuxtonTestClass {
49         GtkWindowClass parent_class;
50 };
51
52 G_DEFINE_TYPE(BuxtonTest, buxton_test, GTK_TYPE_WINDOW)
53
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);
58
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);
64
65 /**
66  * Initialise Buxton
67  */
68 static gboolean buxton_init(BuxtonTest *self);
69
70 /* Initialisation */
71 static void buxton_test_class_init(BuxtonTestClass *klass)
72 {
73         GObjectClass *g_object_class;
74
75         g_object_class = G_OBJECT_CLASS(klass);
76         g_object_class->dispose = &buxton_test_dispose;
77 }
78
79 static void buxton_test_init(BuxtonTest *self)
80 {
81         GtkWidget *info, *layout;
82         GtkWidget *label, *container, *box, *box2;
83         GtkWidget *entry, *button;
84         GtkStyleContext *style;
85
86         /* Window setup */
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");
90
91         /* layout */
92         layout = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
93         gtk_container_add(GTK_CONTAINER(self), layout);
94
95         info = gtk_info_bar_new();
96         label = gtk_label_new("Connecting");
97         self->info_label = label;
98         self->info = info;
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);
102
103         /* Help label */
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);
110
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);
115
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);
121
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);
126
127         /* Give entry and button a linked effect */
128         entry = gtk_entry_new();
129         self->entry = entry;
130         gtk_entry_set_placeholder_text(GTK_ENTRY(self->entry),
131                 "Type a new value");
132         g_signal_connect(entry, "activate", G_CALLBACK(update_key), self);
133         gtk_box_pack_start(GTK_BOX(box2), entry, TRUE, TRUE, 0);
134
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);
138
139         gtk_widget_show_all(GTK_WIDGET(self));
140         gtk_widget_grab_focus(button);
141
142         self->fd = -1;
143         self->setting = FALSE;
144         gtk_widget_hide(info);
145
146         /* Attempt connection to Buxton */
147         if (!buxton_init(self)) {
148                 gtk_info_bar_set_message_type(GTK_INFO_BAR(info),
149                         GTK_MESSAGE_ERROR);
150                 gtk_label_set_markup(GTK_LABEL(self->info_label), "No connection!");
151                 gtk_widget_show(info);
152         } else {
153                 update_value(self);
154         }
155 }
156
157 static void buxton_test_dispose(GObject *object)
158 {
159         BuxtonTest *self = BUXTON_TEST(object);
160         if (self->tag > 0) {
161                 g_source_remove(self->tag);
162                 self->tag = 0;
163         }
164         if (self->client) {
165                 buxton_close(self->client);
166                 self->client = NULL;
167         }
168         /* Destruct */
169         G_OBJECT_CLASS (buxton_test_parent_class)->dispose (object);
170 }
171
172 /* Utility; return a new BuxtonTest */
173 GtkWidget* buxton_test_new(void)
174 {
175         BuxtonTest *self;
176
177         self = g_object_new(BUXTON_TEST_TYPE, NULL);
178         return GTK_WIDGET(self);
179 }
180 static gboolean buxton_init(BuxtonTest *self)
181 {
182         gint fd;
183         BuxtonKey key;
184
185         /* Bail if initialized */
186         if (self->fd > 0) {
187                 return TRUE;
188         }
189         /* Stop probing Buxton */
190         if (self->tag > 0) {
191                 g_source_remove(self->tag);
192                 self->tag = 0;
193         }
194
195         fd = buxton_open(&self->client);
196         if (fd <= 0) {
197                 return FALSE;
198         }
199         self->fd = fd;
200
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);
205
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");
211         }
212
213         return TRUE;
214 }
215
216 static void update_key(GtkWidget *widget, gpointer userdata)
217 {
218         BuxtonTest *self = BUXTON_TEST(userdata);
219         BuxtonKey key;
220         const gchar *value;
221
222         value = gtk_entry_get_text(GTK_ENTRY(self->entry));
223         if (strlen(value) == 0 || g_str_equal(value, "")) {
224                 return;
225         }
226
227         key = buxton_key_create(GROUP, PRIMARY_KEY, LAYER, STRING);
228
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!");
233         }
234         buxton_key_free(key);
235 }
236
237 static void update_value(BuxtonTest *self)
238 {
239         BuxtonKey key;
240
241         key = buxton_key_create(GROUP, PRIMARY_KEY, LAYER, STRING);
242
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);
249                 self->fd = -1;
250                 /* Just try reconnecting */
251                 if (!buxton_init(self)) {
252                         report_error(self, "Unable to connect");
253                 }
254         }
255
256
257         buxton_key_free(key);
258 }
259
260 static void report_error(BuxtonTest *self, gchar *error)
261 {
262         if (error != NULL) {
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),
267                         GTK_MESSAGE_ERROR);
268         } else {
269                 gtk_widget_hide(GTK_WIDGET(self->info));
270         }
271 }
272
273 static gboolean buxton_update(gint fd, GIOCondition cond, gpointer userdata)
274 {
275         BuxtonClient client = (BuxtonClient)userdata;
276         ssize_t handled = buxton_client_handle_response(client);
277         return (handled >= 0);
278 }
279
280 static void buxton_callback(BuxtonResponse response, gpointer userdata)
281 {
282         BuxtonKey key;
283         BuxtonTest *self;
284         void *value;
285         gchar *key_name = NULL;
286         self = BUXTON_TEST(userdata);
287
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");
293                                 return;
294                         case BUXTON_CONTROL_SET:
295                                 self->setting = FALSE;
296                                 report_error(self, "Unable to set value");
297                                 return;
298                         case BUXTON_CONTROL_CHANGED:
299                                 report_error(self, "Unable to get notification value");
300                                 return;
301                         case BUXTON_CONTROL_NOTIFY:
302                                 report_error(self, "Unable to register for notification");
303                                 return;
304                         default:
305                                 report_error(self, "Unhandled error!");
306                                 return;
307                 }
308         }
309         if (self->setting) {
310                 self->setting = FALSE;
311                 return;
312         }
313
314         key = buxton_response_key(response);
315         key_name = buxton_key_get_name(key);
316         value = buxton_response_value(response);
317
318         /* Handle PRIMARY_KEY (string) */
319         if (g_str_equal(key_name, PRIMARY_KEY) && buxton_key_get_type(key) == STRING) {
320                 gchar *lab;
321                 /* Key unset */
322                 if (!value) {
323                         lab = g_strdup_printf("<big>\'%s\' unset</big>", key_name);
324                 } else {
325                         lab = g_strdup_printf("<big>\'%s\' value: %s</big>",
326                                 key_name, (gchar*)value);
327                 }
328                 /* Update UI */
329                 gtk_label_set_markup(GTK_LABEL(self->value_label), lab);
330                 g_free(lab);
331         }
332
333         free(value);
334         free(key_name);
335         buxton_key_free(key);
336 }
337
338 /** Main entry */
339 int main(int argc, char **argv)
340 {
341         __attribute__ ((unused)) GtkWidget *window = NULL;
342
343         gtk_init(&argc, &argv);
344         window = buxton_test_new();
345         gtk_main();
346
347         return EXIT_SUCCESS;
348 }