packaging: fix to install headers properly
[platform/core/uifw/libpui.git] / samples / PUI_sample.c
1 /*
2  * Copyright © 2019 Samsung Electronics co., Ltd. All Rights Reserved.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining
5  * a copy of this software and associated documentation files (the
6  * "Software"), to deal in the Software without restriction, including
7  * without limitation the rights to use, copy, modify, merge, publish,
8  * distribute, sublicense, and/or sell copies of the Software, and to
9  * permit persons to whom the Software is furnished to do so, subject to
10  * the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the
13  * next paragraph) shall be included in all copies or substantial
14  * portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19  * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
20  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23  * SOFTWARE.
24  */
25
26 #include <stdio.h>
27 #include <unistd.h>
28
29 #define NUM_ECORE_EVENT_HANDLERS 7
30
31 /* pre-requisite to use ecore_wl2 APIs */
32 #define EFL_BETA_API_SUPPORT
33
34 #define MAX_STR 1024
35
36 #include <Ecore_Wl2.h>
37 #include <Ecore_Input.h>
38 #include <PUI.h>
39
40 int gpid;
41
42 #define debug_error(msg, ...)                                                                                   \
43         do {                                                                                                                            \
44                 fprintf(stderr, "[PUI sample][ERROR][PID:%d][%s] " msg, gpid, __FUNCTION__, ##__VA_ARGS__);     \
45         } while(0)
46
47 #define debug_info(msg, ...)                                                                                            \
48         do {                                                                                                                            \
49                 fprintf(stdout, "[PUI sample][INFO][PID:%d][%s] " msg, gpid, __FUNCTION__, ##__VA_ARGS__);      \
50         } while(0)
51
52 typedef struct _animation animation_t;
53 struct _animation
54 {
55         pui_id id;
56         pui_ani_cmd cmd;
57         int repeat;
58 };
59
60 typedef struct app_data app_data_t;
61 struct app_data
62 {
63         pui_h ph;
64         int ani_idx;
65         int n_animation;
66         int manual_idx;
67
68         Ecore_Wl2_Display *ewd;
69         Ecore_Wl2_Window *win;
70 };
71
72 static Eina_Array *_ecore_event_hdls = NULL;
73 static animation_t ani_collection[] = {
74         { "system/easy_setup", PUI_ANI_CMD_START, -1 },
75         { "system/processing", PUI_ANI_CMD_START, -1 },
76         { "system/sw_update_done", PUI_ANI_CMD_START, 1 },
77         { "system/mic_off", PUI_ANI_CMD_START, 1 },
78         { "voice/listening", PUI_ANI_CMD_START, 1 },
79         { "voice/streaming", PUI_ANI_CMD_START, -1 },
80         { "voice/processing", PUI_ANI_CMD_START, -1 },
81         { "voice/speaking", PUI_ANI_CMD_START, -1 },
82         { "voice/timeout", PUI_ANI_CMD_START, 1 },
83         { "notification/normal", PUI_ANI_CMD_START, 1 },
84         { "notification/emergency", PUI_ANI_CMD_START, -1 },
85         { "notification/network_error", PUI_ANI_CMD_START, -1 },
86         { "notification/error", PUI_ANI_CMD_START, -1 },
87         { "notification/alarm", PUI_ANI_CMD_START, 1 },
88         { "bt/pairing", PUI_ANI_CMD_START, -1 },
89         { "bt/connected", PUI_ANI_CMD_START, 3 }
90 };
91
92 pui_ani_h ani_handles[sizeof(ani_collection) / sizeof(animation_t)];
93
94 static void
95 ani_collection_play(app_data_t *app)
96 {
97         pui_error e = PUI_ERROR_NONE;
98         pui_ani_h ani_h = NULL;
99
100         if (!app->ph)
101         {
102                 debug_error("Invalid pui_h handle !\n");
103                 return;
104         }
105
106         while (!ani_handles[app->ani_idx])
107         {
108                 app->ani_idx++;
109
110                 if (++app->ani_idx >= app->n_animation)
111                         app->ani_idx = 0;
112         }
113
114         debug_info("Animation(%s) will be started !\n", pui_ani_get_id(ani_handles[app->ani_idx]));
115
116         /* play animation */
117         ani_h = ani_handles[app->ani_idx];
118         e = pui_ani_control(ani_h, PUI_ANI_CMD_START, ani_collection[app->ani_idx].repeat);
119
120         if (PUI_ERROR_NONE != e)
121         {
122                 debug_error("Failed on playing an animation ! (cmd:%d, repeat:%d)\n", PUI_ANI_CMD_START, ani_collection[app->ani_idx].repeat);
123                 return;
124         }
125
126         if (++app->ani_idx >= app->n_animation)
127                 app->ani_idx = 0;
128
129         return;
130 }
131
132 static Eina_Bool
133 _cb_key_up(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
134 {
135         app_data_t *app =  (app_data_t *)data;
136         Ecore_Event_Key *ev = event;
137
138         debug_info("KEY: name:%s, sym:%s, code:%d\n", ev->keyname, ev->key, ev->keycode);
139
140         ani_collection_play(app);
141
142         return ECORE_CALLBACK_PASS_ON;
143 }
144
145 static Eina_Bool
146 _cb_focus_in(void *data, int type EINA_UNUSED, void *event)
147 {
148         app_data_t *app =  (app_data_t *)data;
149         Ecore_Wl2_Event_Focus_In *ev = (Ecore_Wl2_Event_Focus_In *)event;
150
151         debug_info("\n");
152
153         /* TODO */
154         (void) app;
155         (void) ev;
156
157         return ECORE_CALLBACK_PASS_ON;
158 }
159
160 static Eina_Bool
161 _cb_focus_out(void *data, int type EINA_UNUSED, void *event)
162 {
163         app_data_t *app =  (app_data_t *)data;
164         Ecore_Wl2_Event_Focus_Out *ev = (Ecore_Wl2_Event_Focus_Out *)event;
165
166         debug_info("\n");
167
168         /* TODO */
169         (void) app;
170         (void) ev;
171
172         return ECORE_CALLBACK_PASS_ON;
173 }
174
175 static Eina_Bool
176 _cb_visibility_change(void *data, int type EINA_UNUSED, void *event)
177 {
178         app_data_t *app = (app_data_t *)data;
179         Ecore_Wl2_Event_Window_Visibility_Change *ev;
180
181         (void) app;
182         ev = event;
183         debug_info("Visibility change (window=0x%x, fully_obscured=%d)\n", ev->win, ev->fully_obscured);
184
185         return ECORE_CALLBACK_PASS_ON;
186 }
187
188 static Eina_Bool
189 _cb_ani_started(void *data, int type EINA_UNUSED, void *event)
190 {
191         app_data_t *app = (app_data_t *)data;
192         PUI_Event_Animation_Status *ev;
193
194         (void) app;
195         ev = event;
196         debug_info("[%s] ani id=%s, status=%d, window=0x%x\n", __FUNCTION__, pui_ani_get_id(ev->ani_h), ev->status, ev->win);
197
198         return ECORE_CALLBACK_PASS_ON;
199 }
200
201 static Eina_Bool
202 _cb_ani_stopped(void *data, int type EINA_UNUSED, void *event)
203 {
204         app_data_t *app = (app_data_t *)data;
205         PUI_Event_Animation_Status *ev;
206
207         (void) app;
208         ev = event;
209         debug_info("[%s] ani id=%s, status=%d, window=0x%x\n", __FUNCTION__, pui_ani_get_id(ev->ani_h), ev->status, ev->win);
210
211         /* decrease animation idx for starting from stopped animation */
212         //app->ani_idx--;
213
214         return ECORE_CALLBACK_PASS_ON;
215 }
216
217 static Eina_Bool
218 _cb_ani_ready_to_resume(void *data, int type EINA_UNUSED, void *event)
219 {
220         app_data_t *app = (app_data_t *)data;
221         PUI_Event_Animation_Status *ev;
222
223         (void) app;
224         ev = event;
225         debug_info("[%s] ani id=%s, status=%d, window=0x%x\n", __FUNCTION__, pui_ani_get_id(ev->ani_h), ev->status, ev->win);
226
227         /* resume animation */
228         app->ani_idx--;
229         ani_collection_play(app);
230
231         return ECORE_CALLBACK_PASS_ON;
232 }
233
234 static void
235 _ani_play(app_data_t *app, const char *ani_type, int repeat)
236 {
237         pui_error e = PUI_ERROR_NONE;
238         pui_ani_h ani_h = NULL;
239         int idx = -1;
240
241         if (!app->ph)
242         {
243                 debug_error("Invalid pui_h handle !\n");
244                 return;
245         }
246
247         for (int i = 0; i < app->n_animation; i++)
248         {
249                 if (!strncmp(ani_collection[i].id, ani_type, strlen(ani_type)))
250                 {
251                         idx = i;
252                         break;
253                 }
254         }
255         if (idx < 0)
256         {
257                 debug_error("%s is not supported animation id.\n", ani_type);
258                 return;
259         }
260
261         debug_info("Animation(%s) will be started !\n", pui_ani_get_id(ani_handles[idx]));
262
263         /* play animation */
264         ani_h = ani_handles[idx];
265         e = pui_ani_control(ani_h, PUI_ANI_CMD_START, repeat);
266
267         if (PUI_ERROR_NONE != e)
268         {
269                 debug_error("Failed on playing an animation ! (cmd:%d, repeat:%d)\n", PUI_ANI_CMD_START, repeat);
270                 return;
271         }
272
273         app->manual_idx = idx;
274 }
275
276 static void
277 _ani_stop(app_data_t *app)
278 {
279         pui_error e = PUI_ERROR_NONE;
280         pui_ani_h ani_h = NULL;
281
282         if (!app->ph)
283         {
284                 debug_error("Invalid pui_h handle !\n");
285                 return;
286         }
287
288         if (app->manual_idx < 0)
289         {
290                 debug_info("manual animation is not started\n");
291                 return;
292         }
293
294         debug_info("Animation(%s) will be stop !\n", pui_ani_get_id(ani_handles[app->manual_idx]));
295
296         /* play animation */
297         ani_h = ani_handles[app->manual_idx];
298         e = pui_ani_control(ani_h, PUI_ANI_CMD_STOP, -1);
299
300         if (PUI_ERROR_NONE != e)
301         {
302                 debug_error("Failed on stop an animation ! (cmd:%d)\n", PUI_ANI_CMD_STOP);
303         }
304
305         app->manual_idx = -1;
306 }
307
308
309 static void
310 _usage(void)
311 {
312         printf("  Supported commands:  help                   (Print this help text)\n");
313         printf("                    :  q/quit                 (Quit program)\n");
314         printf("                    :  play {ani_id} {repeat} (play manual animation)\n");
315         printf("                         ex> play system/processing 2\n");
316         printf("                    :  stop                   (stop manual animation)\n");
317         printf("\n");
318 }
319
320 static void
321 _process_options(app_data_t *app, char *options)
322 {
323         char *tmp, *buf_ptr;
324         int count = 0;
325         char ani_type[MAX_STR] = {0, };
326         int repeat = 0;
327
328         tmp = strtok_r(options, " ", &buf_ptr);
329         if (!tmp) return;
330
331         if (!strncmp(options, "q", MAX_STR) || !strncmp(options, "quit", MAX_STR)) {
332                 ecore_main_loop_quit();
333         }
334         else if (!strncmp(options, "help", MAX_STR)) {
335                 _usage();
336         }
337         else if (!strncmp(tmp, "play", sizeof("play"))) {
338                 while (tmp) {
339                         tmp = strtok_r(NULL, " ", &buf_ptr);
340                         if (tmp) {
341                                 switch (count) {
342                                         case 0:
343                                                 strncpy(ani_type, tmp, MAX_STR - 1);
344                                                 break;
345                                         case 1:
346                                                 repeat = atoi(tmp);
347                                                 break;
348                                         default:
349                                                 break;
350                                 }
351                         }
352                         count++;
353                 }
354                 if (strlen(ani_type) <= 0) {
355                         printf("Please input valid arguments for ani type\n");
356                         _usage();
357                 }
358                 else
359                         _ani_play(app, ani_type, repeat);
360         }
361         else if (!strncmp(tmp, "stop", sizeof("stop"))) {
362                 _ani_stop(app);
363         }
364         else {
365                 printf("Invalid arguments\n");
366                 _usage();
367         }
368 }
369
370 static Eina_Bool
371 _stdin_cb(void *data, Ecore_Fd_Handler *handler EINA_UNUSED)
372 {
373         app_data_t *app = (app_data_t *)data;
374         char c, buf[MAX_STR] = {0, };
375         int count = 0;
376
377         while ((c = getchar()) != EOF) {
378                 if (c == '\n') break;
379                 if (count >= MAX_STR) break;
380
381                 buf[count] = c;
382                 count++;
383         }
384
385         _process_options(app, buf);
386
387         return ECORE_CALLBACK_RENEW;
388 }
389
390
391 static void
392 event_handlers_init(app_data_t *app)
393 {
394         Ecore_Event_Handler *h = NULL;
395         _ecore_event_hdls = eina_array_new(NUM_ECORE_EVENT_HANDLERS);
396
397         h = ecore_event_handler_add(ECORE_EVENT_KEY_UP, _cb_key_up, app);
398         eina_array_push(_ecore_event_hdls, h);
399
400         h = ecore_event_handler_add(ECORE_WL2_EVENT_FOCUS_IN, _cb_focus_in, app);
401         eina_array_push(_ecore_event_hdls, h);
402
403         h = ecore_event_handler_add(ECORE_WL2_EVENT_FOCUS_OUT, _cb_focus_out, app);
404         eina_array_push(_ecore_event_hdls, h);
405
406         h = ecore_event_handler_add(ECORE_WL2_EVENT_WINDOW_VISIBILITY_CHANGE, _cb_visibility_change, app);
407         eina_array_push(_ecore_event_hdls, h);
408
409         h = ecore_event_handler_add(PUI_EVENT_ANI_STARTED, _cb_ani_started, app);
410         eina_array_push(_ecore_event_hdls, h);
411
412         h = ecore_event_handler_add(PUI_EVENT_ANI_STOPPED, _cb_ani_stopped, app);
413         eina_array_push(_ecore_event_hdls, h);
414
415         h = ecore_event_handler_add(PUI_EVENT_ANI_READY_TO_RESUME, _cb_ani_ready_to_resume, app);
416         eina_array_push(_ecore_event_hdls, h);
417 }
418
419 int main(int argc, char **argv)
420 {
421         app_data_t *app = NULL;
422         const char *socket_name = NULL;
423
424         gpid = getpid();
425
426         if (!ecore_wl2_init())
427         {
428                 debug_error("Failed to init ecore wl2 !\n");
429                 return EXIT_SUCCESS;
430         }
431
432         socket_name = getenv("WAYLAND_DISPLAY");
433
434         if (!socket_name)
435                 socket_name = "wayland-0";
436
437         app = (app_data_t *)calloc(1, sizeof(app_data_t));
438
439         if (!app)
440         {
441                 debug_error("Failed to allocate app data !\n");
442                 goto err;
443         }
444
445         app->ani_idx = 0;
446         app->manual_idx = -1;
447         app->ewd = ecore_wl2_display_connect(socket_name);
448
449         if (!app->ewd)
450         {
451                 debug_error("Failed to connect to display !\n");
452                 goto err;
453         }
454
455         app->win = ecore_wl2_window_new(app->ewd, NULL, 0, 0, 1, 1);
456
457         if (!app->win)
458         {
459                 debug_error("Failed to create a window !\n");
460                 goto err;
461         }
462
463         ecore_wl2_window_alpha_set(app->win, EINA_FALSE);
464         ecore_wl2_window_show(app->win);
465         ecore_wl2_window_commit(app->win, EINA_TRUE);
466         ecore_wl2_window_activate(app->win);
467
468         if (!pui_init())
469         {
470                 debug_error("Failed to init pui !\n");
471                 goto err;
472         }
473
474         app->ph = pui_create(app->win);
475
476         if (!app->ph)
477         {
478                 debug_error("Failed to create PUI handle !\n");
479                 goto err;
480         }
481
482         app->n_animation = sizeof(ani_collection) / sizeof(animation_t);
483
484         for(int i=0;i<app->n_animation;i++)
485         {
486                 ani_handles[i] = pui_ani_create(app->ph, ani_collection[i].id);
487
488                 if (!ani_handles[i])
489                         debug_error("Failed to create pui ani handle !(id:%s)\n", ani_collection[i].id);
490         }
491
492         event_handlers_init(app);
493         if (argc >= 2 && !strncmp(argv[1], "stdin", sizeof("stdin")))
494         {
495                 ecore_main_fd_handler_add(STDIN_FILENO, ECORE_FD_READ, _stdin_cb, app, NULL, NULL);
496         }
497
498         ecore_main_loop_begin();
499 err:
500         if (app->n_animation > 0)
501         {
502                 for(int i=0;i<app->n_animation;i++)
503                 {
504                         pui_ani_destroy(ani_handles[i]);
505                 }
506         }
507
508         if (app->ph)
509                 pui_destroy(app->ph);
510
511         pui_shutdown();
512         ecore_wl2_shutdown();
513
514         return EXIT_SUCCESS;
515 }