e13d4a76798bd5fe1b67fcf295380466ffc42cfc
[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         int idx = -1;
282
283         if (!app->ph)
284         {
285                 debug_error("Invalid pui_h handle !\n");
286                 return;
287         }
288
289         if (app->manual_idx < 0)
290         {
291                 debug_info("manual animation is not started\n");
292                 return;
293         }
294
295         debug_info("Animation(%s) will be stop !\n", pui_ani_get_id(ani_handles[app->manual_idx]));
296
297         /* play animation */
298         ani_h = ani_handles[app->manual_idx];
299         e = pui_ani_control(ani_h, PUI_ANI_CMD_STOP, -1);
300
301         if (PUI_ERROR_NONE != e)
302         {
303                 debug_error("Failed on stop an animation ! (cmd:%d)\n", PUI_ANI_CMD_STOP);
304         }
305
306         app->manual_idx = -1;
307 }
308
309
310 static void
311 _usage(void)
312 {
313         printf("  Supported commands:  help                   (Print this help text)\n");
314         printf("                    :  q/quit                 (Quit program)\n");
315         printf("                    :  play {ani_id} {repeat} (play manual animation)\n");
316         printf("                         ex> play system/processing 2\n");
317         printf("                    :  stop                   (stop manual animation)\n");
318         printf("\n");
319 }
320
321 static void
322 _process_options(app_data_t *app, char *options)
323 {
324         char *tmp, *buf_ptr;
325         int count = 0;
326         char ani_type[MAX_STR] = {0, };
327         int repeat = 0;
328
329         tmp = strtok_r(options, " ", &buf_ptr);
330         if (!tmp) return;
331
332         if (!strncmp(options, "q", MAX_STR) || !strncmp(options, "quit", MAX_STR)) {
333                 ecore_main_loop_quit();
334         }
335         else if (!strncmp(options, "help", MAX_STR)) {
336                 _usage();
337         }
338         else if (!strncmp(tmp, "play", sizeof("play"))) {
339                 while (tmp) {
340                         tmp = strtok_r(NULL, " ", &buf_ptr);
341                         if (tmp) {
342                                 switch (count) {
343                                         case 0:
344                                                 strncpy(ani_type, tmp, MAX_STR - 1);
345                                                 break;
346                                         case 1:
347                                                 repeat = atoi(tmp);
348                                                 break;
349                                         default:
350                                                 break;
351                                 }
352                         }
353                         count++;
354                 }
355                 if (strlen(ani_type) <= 0) {
356                         printf("Please input valid arguments for ani type\n");
357                         _usage();
358                 }
359                 else
360                         _ani_play(app, ani_type, repeat);
361         }
362         else if (!strncmp(tmp, "stop", sizeof("stop"))) {
363                 _ani_stop(app);
364         }
365         else {
366                 printf("Invalid arguments\n");
367                 _usage();
368         }
369 }
370
371 static Eina_Bool
372 _stdin_cb(void *data, Ecore_Fd_Handler *handler EINA_UNUSED)
373 {
374         app_data_t *app = (app_data_t *)data;
375         char c, buf[MAX_STR] = {0, };
376         int count = 0;
377
378         while ((c = getchar()) != EOF) {
379                 if (c == '\n') break;
380                 if (count >= MAX_STR) break;
381
382                 buf[count] = c;
383                 count++;
384         }
385
386         _process_options(app, buf);
387
388         return ECORE_CALLBACK_RENEW;
389 }
390
391
392 static void
393 event_handlers_init(app_data_t *app)
394 {
395         Ecore_Event_Handler *h = NULL;
396         _ecore_event_hdls = eina_array_new(NUM_ECORE_EVENT_HANDLERS);
397
398         h = ecore_event_handler_add(ECORE_EVENT_KEY_UP, _cb_key_up, app);
399         eina_array_push(_ecore_event_hdls, h);
400
401         h = ecore_event_handler_add(ECORE_WL2_EVENT_FOCUS_IN, _cb_focus_in, app);
402         eina_array_push(_ecore_event_hdls, h);
403
404         h = ecore_event_handler_add(ECORE_WL2_EVENT_FOCUS_OUT, _cb_focus_out, app);
405         eina_array_push(_ecore_event_hdls, h);
406
407         h = ecore_event_handler_add(ECORE_WL2_EVENT_WINDOW_VISIBILITY_CHANGE, _cb_visibility_change, app);
408         eina_array_push(_ecore_event_hdls, h);
409
410         h = ecore_event_handler_add(PUI_EVENT_ANI_STARTED, _cb_ani_started, app);
411         eina_array_push(_ecore_event_hdls, h);
412
413         h = ecore_event_handler_add(PUI_EVENT_ANI_STOPPED, _cb_ani_stopped, app);
414         eina_array_push(_ecore_event_hdls, h);
415
416         h = ecore_event_handler_add(PUI_EVENT_ANI_READY_TO_RESUME, _cb_ani_ready_to_resume, app);
417         eina_array_push(_ecore_event_hdls, h);
418 }
419
420 int main(int argc, char **argv)
421 {
422         app_data_t *app = NULL;
423         const char *socket_name = NULL;
424
425         gpid = getpid();
426
427         if (!ecore_wl2_init())
428         {
429                 debug_error("Failed to init ecore wl2 !\n");
430                 return EXIT_SUCCESS;
431         }
432
433         socket_name = getenv("WAYLAND_DISPLAY");
434
435         if (!socket_name)
436                 socket_name = "wayland-0";
437
438         app = (app_data_t *)calloc(1, sizeof(app_data_t));
439
440         if (!app)
441         {
442                 debug_error("Failed to allocate app data !\n");
443                 goto err;
444         }
445
446         app->ani_idx = 0;
447         app->manual_idx = -1;
448         app->ewd = ecore_wl2_display_connect(socket_name);
449
450         if (!app->ewd)
451         {
452                 debug_error("Failed to connect to display !\n");
453                 goto err;
454         }
455
456         app->win = ecore_wl2_window_new(app->ewd, NULL, 0, 0, 1, 1);
457
458         if (!app->win)
459         {
460                 debug_error("Failed to create a window !\n");
461                 goto err;
462         }
463
464         ecore_wl2_window_alpha_set(app->win, EINA_FALSE);
465         ecore_wl2_window_show(app->win);
466         ecore_wl2_window_commit(app->win, EINA_TRUE);
467         ecore_wl2_window_activate(app->win);
468
469         if (!pui_init())
470         {
471                 debug_error("Failed to init pui !\n");
472                 goto err;
473         }
474
475         app->ph = pui_create(app->win);
476
477         if (!app->ph)
478         {
479                 debug_error("Failed to create PUI handle !\n");
480                 goto err;
481         }
482
483         app->n_animation = sizeof(ani_collection) / sizeof(animation_t);
484
485         for(int i=0;i<app->n_animation;i++)
486         {
487                 ani_handles[i] = pui_ani_create(app->ph, ani_collection[i].id);
488
489                 if (!ani_handles[i])
490                         debug_error("Failed to create pui ani handle !(id:%s)\n", ani_collection[i].id);
491         }
492
493         event_handlers_init(app);
494         if (argc >= 2 && !strncmp(argv[1], "stdin", sizeof("stdin")))
495         {
496                 ecore_main_fd_handler_add(STDIN_FILENO, ECORE_FD_READ, _stdin_cb, app, NULL, NULL);
497         }
498
499         ecore_main_loop_begin();
500 err:
501         if (app->n_animation > 0)
502         {
503                 for(int i=0;i<app->n_animation;i++)
504                 {
505                         pui_ani_destroy(ani_handles[i]);
506                 }
507         }
508
509         if (app->ph)
510                 pui_destroy(app->ph);
511
512         pui_shutdown();
513         ecore_wl2_shutdown();
514
515         return EXIT_SUCCESS;
516 }