renew pui prototype
[platform/core/uifw/libpui.git] / src / PUI.c
1 #include "PUI.h"
2 #include "PUI_internal.h"
3 #include "PUI_backend.h"
4
5 #ifndef PUI_MODULE_DIR
6 #define PUI_MODULE_DIR "/usr/lib"
7 #endif
8
9 #define pui_err(msg, ...)                                                                               \
10         do {                                                                                                            \
11                 fprintf(stderr, "[ERROR][%s] " msg, __FUNCTION__, ##__VA_ARGS__);       \
12         } while(0)
13
14 #define pui_warn(msg, ...)                                                                              \
15                 do {                                                                                                    \
16                         fprintf(stderr, "[WARNING][%s] " msg, __FUNCTION__, ##__VA_ARGS__);     \
17                 } while(0)
18
19 #define pui_info(msg, ...)                                                                              \
20         do {                                                                                                            \
21                 fprintf(stdout, "[INFO][%s] " msg, __FUNCTION__, ##__VA_ARGS__);        \
22         } while(0)
23
24 static int _pui_init_count = 0;
25 static pui_module_data *pui_module = NUJLL;
26
27 EAPI int PUI_EVENT_ANI_STARTED = 0;
28 EAPI int PUI_EVENT_ANI_STOPPED = 0;
29 EAPI int PUI_EVENT_ANI_PAUSED = 0;
30 EAPI int PUI_EVENT_ANI_READY_TO_START = 0;
31 EAPI int PUI_EVENT_ANI_READY_TO_RESUME = 0;
32 EAPI int PUI_EVENT_ANI_FRAME_DONE = 0;
33 EAPI int PUI_EVENT_ANI_BUFFER_RELEASED = 0;
34
35 const pui_error_string
36 pui_error_to_string(pui_error e)
37 {
38         const pui_error_string str = NULL;
39
40         switch (e)
41         {
42                 case PUI_ERROR_NONE:
43                         str = "PUI_No_Error";
44                         break;
45
46                 case PUI_ERROR_INVALID_ANI_HANDLE:
47                         str = "PUI_Invalid_Animation_Handle";
48                         break;
49
50                 case PUI_ERROR_INVALID_ANI_CMD:
51                         str = "PUI_Invalid_Animation_Command";
52                         break;
53
54                 case PUI_ERROR_INVALID_ANI_OPT:
55                         str = "PUI_Invalid_Animation_Option";
56                         break;
57
58                 case PUI_ERROR_INTERNAL:
59                         str = "PUI_Internal_Error";
60                         break;
61
62                 default:
63                         str = "PUI_Unknown_Error";
64         }
65
66         return str;
67 }
68
69 static void
70 _pui_cb_frame(Ecore_Wl2_Window *win, uint32_t timestamp EINA_UNUSED, void *data)
71 {
72         pui_h handle = (pui_h) data;
73
74         TRACE("Frame done ! (window=%p)\n", win);
75
76         // TODO
77
78         return;
79 }
80
81 pui_h
82 pui_create(Ecore_Wl2_Window *win)
83 {
84         pui_h handle = NULL;
85         Ecore_Wl2_display *ewd = ecore_wl2_window_display_get(win);
86         struct wayland_tbm_client *wl_tbm_client = NULL;
87         Ecore_Wl2_Frame_Cb_Handle *frame_cb = NULL;
88
89         if (!win || !ewd)
90         {
91                 pui_err("Invalid window or display !");
92                 return NULL;
93         }
94
95         wl_tbm_client = wayland_tbm_client_init(ecore_wl2_display_get(ewd));
96
97         if (!wl_tbm_client)
98         {
99                 pui_err("Failed to init wayland_tbm_client !");
100                 return NULL;
101         }
102
103         handle = (pui_h)calloc(1, sizeof(pui_h));
104
105         if (!handle)
106                 return NULL;
107
108         handle->win = win;
109         handle->ewd = ewd;
110         handle->visibility = 0;
111         handle->wl_tbm_client = wl_tbm_client;
112         handle->ani_handles = NULL;
113         handle->backend_module_data = pui_module->backend_module_data;
114
115         handle->tbm_queue = wayland_tbm_client_create_surface_queue(handle->wl_tbm_client,
116                                                                 ecore_wl2_window_surface_get(handle->win),
117                                                                 2, 100, 100, TBM_FORMAT_ABGR8888);
118
119         if (!handle->tbm_queue)
120         {
121                 pui_err("Failed to create a surface queue !");
122                 goto err;
123         }
124
125         return handle;
126
127 err:
128         pui_destroy(handle);
129
130         return NULL;
131 }
132
133 void
134 pui_destroy(pui_h handle)
135 {
136         pui_ani_h *ani_h = NULL;
137
138         if (!handle)
139                 return;
140
141         EINA_LIST_FREE(handle->ani_handles, ani_h)
142         {
143                 pui_ani_destroy(ani_h);
144                 free(ani_h);
145         }
146
147         if (handle->tbm_queue)
148         {
149                 tbm_surface_queue_destroy(handle->tbm_queue);
150                 handle->tbm_queue = NULL;
151         }
152
153         if (handle->wl_tbm_client)
154         {
155                 wayland_tbm_client_deinit(handle->wl_tbm_client);
156                 handle->wl_tbm_client = NULL;
157         }
158
159         free(handle);
160 }
161
162 #define PREFIX_LIB    "libpui_"
163 #define SUFFIX_LIB    ".so"
164 #define DEFAULT_LIB   PREFIX_LIB"default"SUFFIX_LIB
165
166 static void
167 _pui_load_backend_module(void)
168 {
169         //char path[PATH_MAX] = {0, };
170         void *module_info = NULL;
171         pui_backend_module *backend_module_info = NULL;
172         int backend_module_major, backend_module_minor;
173         int pui_backend_major, pui_backend_minor;
174
175         pui_backend_module_data *backend_module_data = NULL;
176
177
178         module_info = dlopen(DEFAULT_LIB, RTLD_LAZY);
179
180         if (!module_info)
181         {
182                 pui_err("Failed to dlopen(error:%s, path:%s) !\n", dlerror(), DEFAULT_LIB);
183                 return;
184         }
185
186         backend_module_info = dlsym(module_info, "pui_backend_module_info");
187
188         if (!backend_module_info) {
189                 pui_err("Backend module(%s) doesn't have pui_backend_module_info !\n", DEFAULT_LIB);
190                 goto err;
191         }
192
193         pui_backend_major = PUI_BACKEND_GET_ABI_MAJOR(PUI_BACKEND_AB_VERSION_LAST);
194         pui_backend_minor = PUI_BACKEND_GET_ABI_MINOR(PUI_BACKEND_AB_VERSION_LAST);
195
196         backend_module_major = PUI_BACKEND_GET_ABI_MAJOR(backend_module_info->abi_version);
197         backend_module_minor = PUI_BACKEND_GET_ABI_MINOR(backend_module_info->abi_version);
198
199         if (backend_module_major > pui_backend_major) {
200                 TBM_ERR("PUI backend module ABI major ver(%d) is newer than the PUI's ver(%d)\n",
201                         backend_module_major, pui_backend_major);
202                 goto err;
203         } else if (backend_module_minor > pui_backend_minor) {
204                 TBM_ERR("PUI backend module ABI minor ver(%d) is newer than the PUI's ver(%d)\n",
205                         backend_module_minor, pui_backend_minor);
206                 goto err;
207         }
208
209         if (!backend_module_info->backend_init || !backend_module_info->backend_deinit)
210         {
211                 pui_err("Backend module doesn't have backend_init/backend_deinit function !\n");
212                 goto err;
213         }
214
215         backend_module_data = backend_module_info->backend_init();
216
217         if (!backend_module_data)
218         {
219                 pui_err("Failed to init module (%s) !\n", DEFAULT_LIB);
220                 goto err;
221         }
222
223         pui_module->module_info = module_info;
224         pui_module->backend_module_info = backend_module_info;
225         pui_module->backend_module_data = backend_module_data;
226
227         return;
228
229 err:
230         if (backend_module_info)
231                 backend_module_info->backend_deinit
232
233         if (module_info)
234                 dlclose(module_info);
235
236         return;
237 }
238
239 static void
240 _pui_unload_backend_module(void)
241 {
242         if (!pui_module)
243         {
244                 pui_err("Invalid pui module !\n");
245                 return;
246         }
247
248         if (pui_module->backend_module_info)
249         {
250                 pui_module->backend_module_info->backend_deinit(pui_module->backend_module_data);
251                 pui_module->backend_module_data = NULL;
252                 pui_module->backend_module_info = NULL;
253         }
254
255         if (pui_module->module_info)
256                 dlclose(pui_module->module_info);
257 }
258
259 static void
260 _pui_load(void)
261 {
262         _pui_load_backend_module();
263 }
264
265 static void
266 _pui_unload(void)
267 {
268         _pui_unload_backend_module();
269 }
270
271 static void
272 _pui_event_init(void)
273 {
274         PUI_EVENT_ANI_STARTED = ecore_event_type_new();
275         PUI_EVENT_ANI_STOPPED = ecore_event_type_new();
276         PUI_EVENT_ANI_PAUSED = ecore_event_type_new();
277         PUI_EVENT_ANI_READY_TO_START = ecore_event_type_new();
278         PUI_EVENT_ANI_READY_TO_RESUME = ecore_event_type_new();
279         PUI_EVENT_ANI_FRAME_DONE = ecore_event_type_new();
280         PUI_EVENT_ANI_BUFFER_RELEASED = ecore_event_type_new();
281 }
282
283 static void
284 _pui_event_shutdown(void)
285 {
286         ecore_event_type_flush(PUI_EVENT_ANI_STARTED,
287                                         PUI_EVENT_ANI_STOPPED,
288                                         PUI_EVENT_ANI_PAUSED,
289                                         PUI_EVENT_ANI_READY_TO_START,
290                                         PUI_EVENT_ANI_READY_TO_RESUME,
291                                         PUI_EVENT_ANI_FRAME_DONE,
292                                         PUI_EVENT_ANI_BUFFER_RELEASED);
293
294         PUI_EVENT_ANI_STARTED = -1;
295         PUI_EVENT_ANI_STOPPED = -1;
296         PUI_EVENT_ANI_PAUSED = -1;
297         PUI_EVENT_ANI_READY_TO_START = -1;
298         PUI_EVENT_ANI_READY_TO_RESUME = -1;
299         PUI_EVENT_ANI_FRAME_DONE = -1;
300         PUI_EVENT_ANI_BUFFER_RELEASED = -1;
301 }
302
303 int
304 pui_init(void)
305 {
306         if (++_pui_init_count != 1)
307           return _pui_init_count;
308
309         if (pui_module)
310         {
311                 pui_err("Invalid calling of pui_init() !\n");
312                 goto error;
313         }
314
315         pui_module = (pui_module_data *)calloc(1, sizeof(pui_module_data));
316
317         if (!pui_module)
318         {
319                 pui_err("Failed to allocate memory for pui module data !\n");
320                 goto error;
321         }
322
323         //TODO
324         ecore_wl2_init();
325
326         _pui_event_init();
327
328         _pui_load();
329
330         return _pui_init_count;
331
332 error:
333         return --_pui_init_count;
334 }
335
336 int
337 pui_shutdown(void)
338 {
339         if (_pui_init_count <= 0)
340         {
341                 pui_err("Invalid pui init count : %d\n", _pui_init_count);
342                 _pui_init_count = 0;
343                 return 0;
344         }
345
346         if (!pui_module)
347         {
348                 pui_err("Invalid pui module data !\n");
349                 return _pui_init_count;
350         }
351
352         _pui_init_count--;
353
354         //TODO
355         _pui_unload();
356
357         _pui_event_shutdown();
358
359         ecore_wl2_shutdown();
360
361         free(pui_module);
362
363         return _pui_init_count;
364 }
365