bda4b06fce1464000f7bf4a3cea520128ba54286
[apps/home/minicontrol.git] / src / minicontrol-provider.c
1 /*
2  * Copyright (c)  2013-2015 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <Elementary.h>
18
19 #include "minicontrol-error.h"
20 #include "minicontrol-type.h"
21 #include "minicontrol-internal.h"
22 #include "minicontrol-provider.h"
23 #include "minicontrol-log.h"
24 #include "minicontrol-handler.h"
25
26 #define MINICTRL_PRIORITY_SUFFIX_TOP "__minicontrol_top"
27 #define MINICTRL_PRIORITY_SUFFIX_LOW "__minicontrol_low"
28 #define MINICTRL_DATA_KEY "__minictrl_data_internal"
29
30 enum {
31         MINICTRL_STATE_READY =0,
32         MINICTRL_STATE_RUNNING,
33 };
34
35 struct _provider_data {
36         char *name;
37         int state;
38         minicontrol_priority_e priority;
39         Evas_Object *obj;
40         minictrl_sig_handle *sh;
41         minicontrol_h handler;
42 };
43
44 static void __provider_data_free(struct _provider_data *pd)
45 {
46         if (pd) {
47                 if (pd->name)
48                         free(pd->name);
49
50                 if (pd->sh)
51                         _minictrl_dbus_sig_handle_dettach(pd->sh);
52
53                 if (pd->handler)
54                         _minictrl_handler_destroy(pd->handler);
55
56                 free(pd);
57         }
58 }
59
60 static int __str_has_suffix(const char *str, const char *suffix)
61 {
62         int str_len;
63         int suffix_len;
64
65         if (!str)
66                 return -1;
67
68         if (!suffix)
69                 return -1;
70
71         str_len = strlen (str);
72         suffix_len = strlen (suffix);
73
74         if (str_len < suffix_len)
75                 return -1;
76
77         return strcmp(str + str_len - suffix_len, suffix);
78 }
79
80 static void _running_req_cb(void *data, DBusMessage *msg)
81 {
82         struct _provider_data *pd;
83
84         if (!data) {
85                 ERR("data is NULL");
86                 return;
87         }
88         pd = data;
89
90         if (pd->state == MINICTRL_STATE_RUNNING) {
91                 Evas_Coord w = 0;
92                 Evas_Coord h = 0;
93                 evas_object_geometry_get(pd->obj, NULL, NULL, &w, &h);
94                 _minictrl_provider_message_send(MINICTRL_DBUS_SIG_START,
95                                         pd->name, w, h, pd->priority, pd->handler);
96         }
97 }
98
99 static int minicontrol_win_start(Evas_Object *mincontrol)
100 {
101         struct _provider_data *pd;
102         int ret = MINICONTROL_ERROR_NONE;
103
104         if (!mincontrol) {
105                 ERR("mincontrol is NULL, invaild parameter");
106                 return MINICONTROL_ERROR_INVALID_PARAMETER;
107         }
108
109         pd = evas_object_data_get(mincontrol, MINICTRL_DATA_KEY);
110         if (!pd) {
111                 ERR("pd is NULL, invaild parameter");
112                 return MINICONTROL_ERROR_INVALID_PARAMETER;
113         }
114
115         if (!pd->name) {
116                 ERR("pd name is NULL, invaild parameter");
117                 return MINICONTROL_ERROR_INVALID_PARAMETER;
118         }
119
120         if (pd->state != MINICTRL_STATE_RUNNING) {
121                 Evas_Coord w = 0;
122                 Evas_Coord h = 0;
123                 pd->state = MINICTRL_STATE_RUNNING;
124
125                 evas_object_geometry_get(mincontrol, NULL, NULL, &w, &h);
126                 _minictrl_provider_proc_send(MINICONTROL_DBUS_PROC_EXCLUDE);
127                 ret = _minictrl_provider_message_send(MINICTRL_DBUS_SIG_START,
128                                         pd->name, w, h, pd->priority, pd->handler);
129         }
130
131         return ret;
132 }
133
134 static int minicontrol_win_realize(Evas_Object *mincontrol)
135 {
136         struct _provider_data *pd;
137         int ret = MINICONTROL_ERROR_NONE;
138
139         if (!mincontrol) {
140                 ERR("mincontrol is NULL, invaild parameter");
141                 return MINICONTROL_ERROR_INVALID_PARAMETER;
142         }
143
144         pd = evas_object_data_get(mincontrol, MINICTRL_DATA_KEY);
145         if (!pd) {
146                 ERR("pd is NULL, invaild parameter");
147                 return MINICONTROL_ERROR_INVALID_PARAMETER;
148         }
149
150         if (!pd->name) {
151                 ERR("pd name is NULL, invaild parameter");
152                 return MINICONTROL_ERROR_INVALID_PARAMETER;
153         }
154
155         Evas_Coord w = 0;
156         Evas_Coord h = 0;
157         if (pd->state != MINICTRL_STATE_RUNNING) {
158                 pd->state = MINICTRL_STATE_RUNNING;
159         }
160
161         evas_object_geometry_get(mincontrol, NULL, NULL, &w, &h);
162         ret = _minictrl_provider_message_send(MINICTRL_DBUS_SIG_REALIZE,
163                                 pd->name, w, h, pd->priority, pd->handler);
164
165         return ret;
166 }
167
168 static int minicontrol_win_stop(Evas_Object *mincontrol)
169 {
170         struct _provider_data *pd;
171         int ret = MINICONTROL_ERROR_NONE;
172
173         if (!mincontrol) {
174                 ERR("mincontrol is NULL, invaild parameter");
175                 return MINICONTROL_ERROR_INVALID_PARAMETER;
176         }
177
178         pd = evas_object_data_get(mincontrol, MINICTRL_DATA_KEY);
179         if (!pd) {
180                 ERR("pd is NULL, invaild parameter");
181                 return MINICONTROL_ERROR_INVALID_PARAMETER;
182         }
183
184         if (!pd->name) {
185                 ERR("pd name is NULL, invaild parameter");
186                 return MINICONTROL_ERROR_INVALID_PARAMETER;
187         }
188         if (pd->state != MINICTRL_STATE_READY) {
189                 pd->state = MINICTRL_STATE_READY;
190                 _minictrl_provider_proc_send(MINICONTROL_DBUS_PROC_INCLUDE);
191                 ret = _minictrl_provider_message_send(MINICTRL_DBUS_SIG_STOP,
192                                         pd->name, 0, 0, pd->priority, pd->handler);
193         }
194
195         return ret;
196 }
197
198 static void _minictrl_win_del(void *data, Evas *e,
199                         Evas_Object *obj, void *event_info)
200 {
201         struct _provider_data *pd = NULL;
202
203         minicontrol_win_stop(obj);
204
205         pd = evas_object_data_get(obj, MINICTRL_DATA_KEY);
206         __provider_data_free(pd);
207
208         evas_object_data_set(obj, MINICTRL_DATA_KEY, NULL);
209 }
210
211 static void _minictrl_win_hide(void *data, Evas *e,
212                         Evas_Object *obj, void *event_info)
213 {
214         minicontrol_win_stop(obj);
215 }
216
217 static void _minictrl_win_show(void *data, Evas *e,
218                         Evas_Object *obj, void *event_info)
219 {
220         minicontrol_win_start(obj);
221 }
222
223 static void _minictrl_win_realize(void *data, Evas *e,
224                         Evas_Object *obj, void *event_info)
225 {
226         struct _provider_data *pd;
227
228         if (!data) {
229                 ERR("data is NULL, invaild parameter");
230                 return;
231         }
232         pd = data;
233
234         if (!pd->obj) {
235                 ERR("minicontrol object is NULL, invalid parameter");
236                 return;
237         }
238
239         Evas *win_e = evas_object_evas_get(pd->obj);
240         if (win_e != NULL) {
241                 evas_event_callback_del(win_e, EVAS_CALLBACK_RENDER_POST,
242                                                 _minictrl_win_realize);
243         }
244
245         minicontrol_win_realize(pd->obj);
246
247         if (pd->handler != NULL) {
248                 _minictrl_handler_set_state(pd->handler, 1);
249         }
250 }
251
252 static void _minictrl_win_resize(void *data, Evas *e,
253                         Evas_Object *obj, void *event_info)
254 {
255         struct _provider_data *pd;
256
257         if (!data) {
258                 ERR("data is NULL, invaild parameter");
259                 return;
260         }
261         pd = data;
262
263         if (pd->state == MINICTRL_STATE_RUNNING) {
264                 Evas_Coord w = 0;
265                 Evas_Coord h = 0;
266
267                 evas_object_geometry_get(obj, NULL, NULL, &w, &h);
268                 _minictrl_provider_message_send(MINICTRL_DBUS_SIG_RESIZE,
269                                         pd->name, w, h, pd->priority, pd->handler);
270         }
271 }
272
273 static char *_minictrl_create_name(const char *name)
274 {
275         char *buf;
276         int size = 0;
277
278         if (!name) {
279                 ERR("name is NULL, invaild parameter");
280                 return NULL;
281         }
282
283         size = snprintf(NULL, 0, "[%s]", name) + 1;
284         buf = (char *)malloc(sizeof(char) * size);
285         if (!buf) {
286                ERR("fail to alloc buf");
287                return NULL;
288         }
289
290         snprintf(buf, size, "[%s]", name);
291
292         return buf;
293 }
294
295 static minicontrol_priority_e _minictrl_get_priroty_by_name(const char *name)
296 {
297         minicontrol_priority_e priority = MINICONTROL_PRIORITY_MIDDLE;
298
299         if (!__str_has_suffix(name, MINICTRL_PRIORITY_SUFFIX_TOP))
300                 priority = MINICONTROL_PRIORITY_TOP;
301         else if (!__str_has_suffix(name, MINICTRL_PRIORITY_SUFFIX_LOW))
302                 priority = MINICONTROL_PRIORITY_LOW;
303
304         return priority;
305 }
306
307 EXPORT_API Evas_Object *minicontrol_win_add(const char *name)
308 {
309         minicontrol_h handler = NULL;
310         Evas_Object *win = NULL;
311         
312         if (_minictrl_handler_create(&handler) == MINICONTROL_ERROR_NONE) {
313                 if (_minictrl_handler_set_service_name(handler, name) != MINICONTROL_ERROR_NONE) {
314                         ERR("failed to service name");
315                         _minictrl_handler_destroy(handler);
316                         return NULL;
317                 }
318                 if (_minictrl_handler_set_timestamp(handler, time(NULL)) != MINICONTROL_ERROR_NONE) {
319                         ERR("failed to set timestamp");
320                 }
321                 if (_minictrl_handler_set_priority(handler, MINICONTROL_HDL_PRIORITY_LV3) != MINICONTROL_ERROR_NONE) {
322                         ERR("failed to set priority");
323                 }
324         } else {
325                 ERR("Failed to create minicontrol handler");
326                 return NULL;
327         }
328
329         win = minicontrol_win_add_by_handler(handler);
330         _minictrl_handler_destroy(handler);
331
332         return win;
333 }
334
335 EXPORT_API Evas_Object *minicontrol_win_add_by_handler(minicontrol_h handler)
336 {
337         Evas_Object *win = NULL;
338         char *name = NULL;
339         char *name_inter = NULL;
340         char *priority = NULL;
341         struct _provider_data *pd;
342         time_t timestamp_value = 0;
343
344         if (_minictrl_handler_check_validation(handler) != MINICONTROL_ERROR_NONE) {
345                 ERR("handler is invalid, invaild parameter");
346                 return NULL;
347         }
348
349         _minictrl_handler_get_service_name(handler, &name);
350         if (name == NULL) {
351                 ERR("service name cannot be NULL");
352                 return NULL;
353         }
354         _minictrl_handler_get_timestamp(handler, &timestamp_value);
355         if (timestamp_value == 0) {
356                 if (_minictrl_handler_set_timestamp(handler, time(NULL)) != MINICONTROL_ERROR_NONE) {
357                         ERR("failed to set timestamp");
358                 }
359         }
360         _minictrl_handler_get_priority(handler, &priority);
361         if (priority == NULL) {
362                 if (_minictrl_handler_set_priority(handler, MINICONTROL_HDL_PRIORITY_LV3) != MINICONTROL_ERROR_NONE) {
363                         ERR("failed to set priority");
364                 }
365         } else {
366                 free(priority);
367         }
368
369         win = elm_win_add(NULL, "minicontrol", ELM_WIN_SOCKET_IMAGE);
370         if (!win) {
371                 free(name);
372                 return NULL;
373         }
374
375         name_inter = _minictrl_create_name(name);
376         if (!name_inter) {
377                 ERR("Fail to create name_inter for : %s", name);
378                 free(name);
379                 evas_object_del(win);
380                 return NULL;
381         }
382
383         if (!elm_win_socket_listen(win, name_inter, 0, EINA_TRUE)) {
384                 ERR("Fail to elm win socket listen");
385                 free(name);
386                 evas_object_del(win);
387                 free(name_inter);
388                 return NULL;
389         }
390
391         pd = malloc(sizeof(struct _provider_data));
392         if (!pd) {
393                 ERR("Fail to alloc memory");
394                 free(name);
395                 evas_object_del(win);
396                 free(name_inter);
397                 return NULL;
398
399         }
400         memset(pd, 0x00, sizeof(struct _provider_data));
401         pd->name = name_inter;
402         pd->state = MINICTRL_STATE_READY;
403         pd->obj = win;
404         pd->priority = _minictrl_get_priroty_by_name(name);
405
406         if (_minictrl_handler_clone(handler, &(pd->handler)) != MINICONTROL_ERROR_NONE) {
407                 ERR("Fail to clone handler");
408                 free(name);
409                 evas_object_del(win);
410                 free(name_inter);
411                 free(pd);
412                 return NULL;
413         }
414
415         evas_object_data_set(win ,MINICTRL_DATA_KEY,pd);
416
417         elm_win_autodel_set(win, EINA_TRUE);
418
419         evas_object_event_callback_add(win, EVAS_CALLBACK_DEL,
420                                         _minictrl_win_del, pd);
421
422         evas_object_event_callback_add(win, EVAS_CALLBACK_SHOW,
423                                         _minictrl_win_show, pd);
424
425         evas_object_event_callback_add(win, EVAS_CALLBACK_HIDE,
426                                         _minictrl_win_hide, pd);
427
428         evas_object_event_callback_add(win, EVAS_CALLBACK_RESIZE,
429                                         _minictrl_win_resize, pd);
430
431         Evas *win_e = evas_object_evas_get(win);
432         if (win_e != NULL) {
433                 evas_event_callback_add(win_e, EVAS_CALLBACK_RENDER_POST,
434                                                 _minictrl_win_realize, pd);
435         }
436
437         pd->sh = _minictrl_dbus_sig_handle_attach(MINICTRL_DBUS_SIG_RUNNING_REQ,
438                                         _running_req_cb, pd);
439
440         INFO("new minicontrol created - %s", pd->name);
441
442         free(name);
443
444         return win;
445 }
446
447 EXPORT_API minicontrol_error_e minicontrol_win_handler_get(Evas_Object *mincontrol, minicontrol_h *handler)
448 {
449         if (!mincontrol) {
450                 ERR("invaild mincontrol object");
451                 return MINICONTROL_ERROR_INVALID_PARAMETER;
452         }
453         if (!handler) {
454                 ERR("invaild mincontrol handler");
455                 return MINICONTROL_ERROR_INVALID_PARAMETER;
456         }
457
458         struct _provider_data *pd = evas_object_data_get(mincontrol, MINICTRL_DATA_KEY);
459         if (pd != NULL) {
460                 *handler = pd->handler;
461         } else {
462                 return MINICONTROL_ERROR_NO_DATA;
463         }
464
465         return MINICONTROL_ERROR_NONE;
466 }
467
468 EXPORT_API minicontrol_error_e minicontrol_win_handler_update(Evas_Object *mincontrol, minicontrol_h handler)
469 {
470         struct _provider_data *pd;
471         int ret = MINICONTROL_ERROR_NONE;
472
473         if (!mincontrol) {
474                 ERR("mincontrol is NULL, invaild parameter");
475                 return MINICONTROL_ERROR_INVALID_PARAMETER;
476         }
477         if (_minictrl_handler_check_validation(handler) != MINICONTROL_ERROR_NONE) {
478                 ERR("handler is invalid, invaild parameter");
479                 return MINICONTROL_ERROR_INVALID_PARAMETER;
480         }
481
482         pd = evas_object_data_get(mincontrol, MINICTRL_DATA_KEY);
483         if (!pd) {
484                 ERR("pd is NULL, invaild parameter");
485                 return MINICONTROL_ERROR_INVALID_PARAMETER;
486         }
487
488         if (!pd->name) {
489                 ERR("pd name is NULL, invaild parameter");
490                 return MINICONTROL_ERROR_INVALID_PARAMETER;
491         }
492
493         if (pd->handler != handler) {
494                 if (pd->handler != NULL) {
495                         _minictrl_handler_destroy(pd->handler);
496                         pd->handler = NULL;
497                 }
498                 if (_minictrl_handler_clone(handler, &(pd->handler)) != MINICONTROL_ERROR_NONE) {
499                         ERR("failed to clone a minicontrol handler");
500                         return MINICONTROL_ERROR_OUT_OF_MEMORY;
501                 }
502         }
503
504         if (pd->state == MINICTRL_STATE_RUNNING) {
505                 ret = _minictrl_provider_message_send(MINICTRL_DBUS_SIG_REQUEST,
506                                         pd->name, MINICONTROL_REQ_UPDATE_HANDLER, MINICONTROL_REQ_UPDATE_HANDLER
507                                         , pd->priority, pd->handler);
508         }
509
510         return ret;
511 }
512
513 EXPORT_API minicontrol_error_e minicontrol_request(Evas_Object *mincontrol, minicontrol_request_e request)
514 {
515         struct _provider_data *pd;
516         int ret = MINICONTROL_ERROR_NONE;
517
518         if (!mincontrol) {
519                 ERR("mincontrol is NULL, invaild parameter");
520                 return MINICONTROL_ERROR_INVALID_PARAMETER;
521         }
522
523         pd = evas_object_data_get(mincontrol, MINICTRL_DATA_KEY);
524         if (!pd) {
525                 ERR("pd is NULL, invaild parameter");
526                 return MINICONTROL_ERROR_INVALID_PARAMETER;
527         }
528
529         if (!pd->name) {
530                 ERR("pd name is NULL, invaild parameter");
531                 return MINICONTROL_ERROR_INVALID_PARAMETER;
532         }
533
534         if (pd->state == MINICTRL_STATE_RUNNING) {
535                 ret = _minictrl_provider_message_send(MINICTRL_DBUS_SIG_REQUEST,
536                                         pd->name, request, request, pd->priority, pd->handler);
537         }
538
539         return ret;
540 }