bf4e0637a013b750ca036b6b5e0049a546e13e95
[platform/core/multimedia/libmm-camcorder.git] / src / mm_camcorder_resource.c
1 /*
2  * libmm-camcorder
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19
20 #include "mm_camcorder_internal.h"
21 #include "mm_camcorder_resource.h"
22 #include <murphy/common/glib-glue.h>
23
24 #define MRP_APP_CLASS_FOR_CAMCORDER   "media"
25 #define MRP_RESOURCE_TYPE_MANDATORY TRUE
26 #define MRP_RESOURCE_TYPE_EXCLUSIVE FALSE
27
28 const char* mm_camcorder_resource_str[MM_CAMCORDER_RESOURCE_MAX] = {
29         "camera",
30         "video_overlay"
31 };
32
33 #define MMCAMCORDER_CHECK_RESOURCE_MANAGER_INSTANCE(x_camcorder_resource_manager) \
34 do { \
35         if (!x_camcorder_resource_manager) { \
36                 _mmcam_dbg_err("no resource manager instance"); \
37                 return MM_ERROR_INVALID_ARGUMENT; \
38         } \
39 } while (0);
40
41 #define MMCAMCORDER_CHECK_CONNECTION_RESOURCE_MANAGER(x_camcorder_resource_manager) \
42 do { \
43         if (!x_camcorder_resource_manager) { \
44                 _mmcam_dbg_err("no resource manager instance"); \
45                 return MM_ERROR_INVALID_ARGUMENT; \
46         } else { \
47                 if (!x_camcorder_resource_manager->is_connected) { \
48                         _mmcam_dbg_err("not connected to resource server yet"); \
49                         return MM_ERROR_RESOURCE_NOT_INITIALIZED; \
50                 } \
51         } \
52 } while (0);
53
54 static char *__mmcamcorder_resource_state_to_str(mrp_res_resource_state_t st)
55 {
56         char *state = "unknown";
57         switch (st) {
58         case MRP_RES_RESOURCE_ACQUIRED:
59                 state = "acquired";
60                 break;
61         case MRP_RES_RESOURCE_LOST:
62                 state = "lost";
63                 break;
64         case MRP_RES_RESOURCE_AVAILABLE:
65                 state = "available";
66                 break;
67         case MRP_RES_RESOURCE_PENDING:
68                 state = "pending";
69                 break;
70         case MRP_RES_RESOURCE_ABOUT_TO_LOOSE:
71                 state = "about to loose";
72                 break;
73         }
74         return state;
75 }
76
77 static void __mmcamcorder_resource_state_callback(mrp_res_context_t *context, mrp_res_error_t err, void *user_data)
78 {
79         int i = 0;
80         const mrp_res_resource_set_t *rset;
81         mrp_res_resource_t *resource;
82         mmf_camcorder_t* camcorder = NULL;
83
84         if (err != MRP_RES_ERROR_NONE) {
85                 _mmcam_dbg_err(" - error message received from Murphy, err(0x%x)", err);
86                 return;
87         }
88
89         camcorder = (mmf_camcorder_t*)user_data;
90
91         mmf_return_if_fail((MMHandleType)camcorder);
92
93         _mmcam_dbg_log("enter");
94
95         _MMCAMCORDER_LOCK_RESOURCE(camcorder);
96
97         switch (context->state) {
98         case MRP_RES_CONNECTED:
99                 _mmcam_dbg_log(" - connected to Murphy");
100                 if ((rset = mrp_res_list_resources(context)) != NULL) {
101                         mrp_res_string_array_t *resource_names;
102                         resource_names = mrp_res_list_resource_names(rset);
103                         if (!resource_names) {
104                                 _mmcam_dbg_err(" - no resources available");
105                                 _MMCAMCORDER_UNLOCK_RESOURCE(camcorder);
106                                 return;
107                         }
108                         for (i = 0; i < resource_names->num_strings; i++) {
109                                 resource = mrp_res_get_resource_by_name(rset, resource_names->strings[i]);
110                                 if (resource)
111                                         _mmcam_dbg_log(" - available resource: %s", resource->name);
112                         }
113                         mrp_res_free_string_array(resource_names);
114                 }
115                 camcorder->resource_manager.is_connected = TRUE;
116                 _MMCAMCORDER_RESOURCE_SIGNAL(camcorder);
117                 break;
118         case MRP_RES_DISCONNECTED:
119                 _mmcam_dbg_log(" - disconnected from Murphy");
120                 if (camcorder->resource_manager.rset) {
121                         mrp_res_delete_resource_set(camcorder->resource_manager.rset);
122                         camcorder->resource_manager.rset = NULL;
123                 }
124                 if (camcorder->resource_manager.context) {
125                         mrp_res_destroy(camcorder->resource_manager.context);
126                         camcorder->resource_manager.context = NULL;
127                         camcorder->resource_manager.is_connected = FALSE;
128                 }
129                 break;
130         }
131
132         _MMCAMCORDER_UNLOCK_RESOURCE(camcorder);
133
134         _mmcam_dbg_log("leave");
135
136         return;
137 }
138
139
140 static void __mmcamcorder_resource_set_state_callback(mrp_res_context_t *cx, const mrp_res_resource_set_t *rs, void *user_data)
141 {
142         int i = 0;
143         mmf_camcorder_t *camcorder = (mmf_camcorder_t *)user_data;
144         mrp_res_resource_t *res;
145
146         mmf_return_if_fail((MMHandleType)camcorder);
147
148         _MMCAMCORDER_LOCK_RESOURCE(camcorder);
149
150         if (!mrp_res_equal_resource_set(rs, camcorder->resource_manager.rset)) {
151                 _mmcam_dbg_warn("- resource set(%p) is not same as this camcorder handle's(%p)", rs, camcorder->resource_manager.rset);
152                 _MMCAMCORDER_UNLOCK_RESOURCE(camcorder);
153                 return;
154         }
155
156         _mmcam_dbg_log(" - resource set state of camcorder(%p) is changed to [%s]",
157                 camcorder, __mmcamcorder_resource_state_to_str(rs->state));
158
159         for (i = 0; i < MM_CAMCORDER_RESOURCE_MAX; i++) {
160                 res = mrp_res_get_resource_by_name(rs, mm_camcorder_resource_str[i]);
161                 if (res == NULL) {
162                         _mmcam_dbg_warn(" -- %s not present in resource set", mm_camcorder_resource_str[i]);
163                 } else {
164                         _mmcam_dbg_log(" -- resource name [%s] -> [%s]",
165                                 res->name, __mmcamcorder_resource_state_to_str(res->state));
166
167                         if (res->state == MRP_RES_RESOURCE_ACQUIRED) {
168                                 camcorder->resource_manager.acquire_remain--;
169
170                                 if (camcorder->resource_manager.acquire_remain <= 0) {
171                                         _mmcam_dbg_log("send signal - resource acquire done");
172                                         _MMCAMCORDER_RESOURCE_SIGNAL(camcorder);
173                                 } else {
174                                         _mmcam_dbg_warn("remained acquire count %d",
175                                                 camcorder->resource_manager.acquire_remain);
176                                 }
177                         } else if (res->state == MRP_RES_RESOURCE_LOST) {
178                                 camcorder->resource_manager.acquire_remain++;
179
180                                 if (camcorder->resource_manager.acquire_remain >= camcorder->resource_manager.acquire_count) {
181                                         _mmcam_dbg_log("resource release done");
182
183                                         if (camcorder->state > MM_CAMCORDER_STATE_NULL) {
184                                                 _mmcam_dbg_log("send resource signal");
185                                                 _MMCAMCORDER_RESOURCE_SIGNAL(camcorder);
186                                         } else {
187                                                 _mmcam_dbg_log("skip resource signal - state %d", camcorder->state);
188                                         }
189                                 } else {
190                                         _mmcam_dbg_warn("acquired %d, lost %d",
191                                                 camcorder->resource_manager.acquire_count,
192                                                 camcorder->resource_manager.acquire_remain);
193                                 }
194                         }
195                 }
196         }
197
198         mrp_res_delete_resource_set(camcorder->resource_manager.rset);
199         camcorder->resource_manager.rset = mrp_res_copy_resource_set(rs);
200
201         _MMCAMCORDER_UNLOCK_RESOURCE(camcorder);
202
203         return;
204 }
205
206
207 static void __mmcamcorder_resource_release_cb(mrp_res_context_t *cx, const mrp_res_resource_set_t *rs, void *user_data)
208 {
209         int i = 0;
210         int current_state = MM_CAMCORDER_STATE_NONE;
211         mmf_camcorder_t* camcorder = (mmf_camcorder_t*)user_data;
212         mrp_res_resource_t *res;
213
214         mmf_return_if_fail((MMHandleType)camcorder);
215
216         current_state = _mmcamcorder_get_state((MMHandleType)camcorder);
217         if (current_state <= MM_CAMCORDER_STATE_NONE ||
218             current_state >= MM_CAMCORDER_STATE_NUM) {
219                 _mmcam_dbg_err("Abnormal state. Or null handle. (%p, %d)", camcorder, current_state);
220                 return;
221         }
222
223         /* set value to inform a status is changed by resource manaer */
224         camcorder->state_change_by_system = _MMCAMCORDER_STATE_CHANGE_BY_RM;
225
226         _MMCAMCORDER_LOCK_ASM(camcorder);
227
228         if (!mrp_res_equal_resource_set(rs, camcorder->resource_manager.rset)) {
229                 _MMCAMCORDER_UNLOCK_ASM(camcorder);
230                 _mmcam_dbg_warn("- resource set(%p) is not same as this camcorder handle's(%p)", rs, camcorder->resource_manager.rset);
231                 return;
232         }
233
234         _mmcam_dbg_log(" - resource set state of camcorder(%p) is changed to [%s]",
235                 camcorder, __mmcamcorder_resource_state_to_str(rs->state));
236
237         for (i = 0; i < MM_CAMCORDER_RESOURCE_MAX; i++) {
238                 res = mrp_res_get_resource_by_name(rs, mm_camcorder_resource_str[i]);
239                 if (res == NULL) {
240                         _mmcam_dbg_warn(" -- %s not present in resource set", mm_camcorder_resource_str[i]);
241                 } else {
242                         _mmcam_dbg_log(" -- resource name [%s] -> [%s]", res->name, __mmcamcorder_resource_state_to_str(res->state));
243                 }
244         }
245
246         /* Stop the camera */
247         __mmcamcorder_force_stop(camcorder);
248
249         /* restore value */
250         camcorder->state_change_by_system = _MMCAMCORDER_STATE_CHANGE_NORMAL;
251
252         _MMCAMCORDER_UNLOCK_ASM(camcorder);
253
254         return;
255 }
256
257 int _mmcamcorder_resource_create_resource_set(MMCamcorderResourceManager *resource_manager)
258 {
259         if (resource_manager->rset) {
260                 _mmcam_dbg_warn(" - resource set was already created, delete it");
261                 mrp_res_delete_resource_set(resource_manager->rset);
262                 resource_manager->rset = NULL;
263         }
264
265         resource_manager->rset = mrp_res_create_resource_set(resource_manager->context,
266                 MRP_APP_CLASS_FOR_CAMCORDER, __mmcamcorder_resource_set_state_callback, (void*)resource_manager->user_data);
267
268         if (resource_manager->rset == NULL) {
269                 _mmcam_dbg_err(" - could not create resource set");
270                 return MM_ERROR_RESOURCE_INTERNAL;
271         }
272
273         if (!mrp_res_set_autorelease(TRUE, resource_manager->rset))
274                 _mmcam_dbg_warn(" - could not set autorelease flag!");
275
276         _mmcam_dbg_log("done");
277
278         return MM_ERROR_NONE;
279 }
280
281 static int __mmcamcorder_resource_include_resource(MMCamcorderResourceManager *resource_manager, const char *resource_name)
282 {
283         mrp_res_resource_t *resource = NULL;
284         resource = mrp_res_create_resource(resource_manager->rset,
285                 resource_name,
286                 MRP_RESOURCE_TYPE_MANDATORY,
287                 MRP_RESOURCE_TYPE_EXCLUSIVE);
288         if (resource == NULL) {
289                 _mmcam_dbg_err(" - could not include resource[%s]", resource_name);
290                 return MM_ERROR_RESOURCE_INTERNAL;
291         }
292
293         resource_manager->acquire_count++;
294         resource_manager->acquire_remain = resource_manager->acquire_count;
295
296         _mmcam_dbg_log(" - count[%d] include resource[%s]",
297                 resource_manager->acquire_count, resource_name);
298
299         return MM_ERROR_NONE;
300 }
301
302 static int __mmcamcorder_resource_set_release_cb(MMCamcorderResourceManager *resource_manager)
303 {
304         int ret = MM_ERROR_NONE;
305         bool mrp_ret = FALSE;
306
307         if (resource_manager->rset) {
308                 mrp_ret = mrp_res_set_release_callback(resource_manager->rset, __mmcamcorder_resource_release_cb, resource_manager->user_data);
309                 if (!mrp_ret) {
310                         _mmcam_dbg_err(" - could not set release callback");
311                         ret = MM_ERROR_RESOURCE_INTERNAL;
312                 }
313         } else {
314                 _mmcam_dbg_err(" - resource set is null");
315                 ret = MM_ERROR_RESOURCE_INVALID_STATE;
316         }
317
318         return ret;
319 }
320
321 int _mmcamcorder_resource_manager_init(MMCamcorderResourceManager *resource_manager, void *user_data)
322 {
323         GMainContext *mrp_ctx = NULL;
324         GMainLoop *mrp_loop = NULL;
325
326         MMCAMCORDER_CHECK_RESOURCE_MANAGER_INSTANCE(resource_manager);
327
328         _mmcam_dbg_warn("start");
329
330         mrp_ctx = g_main_context_new();
331         if (!mrp_ctx) {
332                 _mmcam_dbg_err("failed to get create glib context for mrp");
333                 return MM_ERROR_RESOURCE_INTERNAL;
334         }
335
336         mrp_loop = g_main_loop_new(mrp_ctx, TRUE);
337
338         g_main_context_unref(mrp_ctx);
339         mrp_ctx = NULL;
340
341         if (!mrp_loop) {
342                 _mmcam_dbg_err("failed to get create glib loop for mrp");
343                 return MM_ERROR_RESOURCE_INTERNAL;
344         }
345
346         resource_manager->mloop = mrp_mainloop_glib_get(mrp_loop);
347
348         g_main_loop_unref(mrp_loop);
349         mrp_loop = NULL;
350
351         if (!resource_manager->mloop) {
352                 _mmcam_dbg_err("failed to get mainloop for mrp");
353                 return MM_ERROR_RESOURCE_INTERNAL;
354         }
355
356         _mmcam_dbg_warn("mloop %p", resource_manager->mloop);
357
358         resource_manager->context = mrp_res_create(resource_manager->mloop, __mmcamcorder_resource_state_callback, user_data);
359         if (!resource_manager->context) {
360                 _mmcam_dbg_err("could not get context for mrp");
361
362                 mrp_mainloop_destroy(resource_manager->mloop);
363                 resource_manager->mloop = NULL;
364
365                 return MM_ERROR_RESOURCE_INTERNAL;
366         }
367
368         resource_manager->user_data = user_data;
369
370         _mmcam_dbg_log("done");
371
372         return MM_ERROR_NONE;
373 }
374
375 int _mmcamcorder_resource_manager_prepare(MMCamcorderResourceManager *resource_manager, MMCamcorderResourceType resource_type)
376 {
377         MMCAMCORDER_CHECK_RESOURCE_MANAGER_INSTANCE(resource_manager);
378         MMCAMCORDER_CHECK_CONNECTION_RESOURCE_MANAGER(resource_manager);
379
380         return __mmcamcorder_resource_include_resource(resource_manager, mm_camcorder_resource_str[resource_type]);
381 }
382
383 int _mmcamcorder_resource_manager_acquire(MMCamcorderResourceManager *resource_manager)
384 {
385         int ret = MM_ERROR_NONE;
386         MMCAMCORDER_CHECK_RESOURCE_MANAGER_INSTANCE(resource_manager);
387         MMCAMCORDER_CHECK_CONNECTION_RESOURCE_MANAGER(resource_manager);
388
389         if (resource_manager->rset == NULL) {
390                 _mmcam_dbg_err("- could not acquire resource, resource set is null");
391                 ret = MM_ERROR_RESOURCE_INVALID_STATE;
392         } else {
393                 ret = __mmcamcorder_resource_set_release_cb(resource_manager);
394                 if (ret) {
395                         _mmcam_dbg_err("- could not set resource release cb, ret(%d)", ret);
396                         ret = MM_ERROR_RESOURCE_INTERNAL;
397                 } else {
398                         ret = mrp_res_acquire_resource_set(resource_manager->rset);
399                         if (ret) {
400                                 _mmcam_dbg_err("- could not acquire resource, ret(%d)", ret);
401                                 ret = MM_ERROR_RESOURCE_INTERNAL;
402                         }
403                 }
404         }
405
406         return ret;
407 }
408
409 int _mmcamcorder_resource_manager_release(MMCamcorderResourceManager *resource_manager)
410 {
411         int ret = MM_ERROR_NONE;
412         MMCAMCORDER_CHECK_RESOURCE_MANAGER_INSTANCE(resource_manager);
413         MMCAMCORDER_CHECK_CONNECTION_RESOURCE_MANAGER(resource_manager);
414
415         if (resource_manager->rset == NULL) {
416                 _mmcam_dbg_err("- could not release resource, resource set is null");
417                 ret = MM_ERROR_RESOURCE_INVALID_STATE;
418         } else {
419                 if (resource_manager->rset->state != MRP_RES_RESOURCE_ACQUIRED) {
420                         _mmcam_dbg_err("- could not release resource, resource set state is [%s]",
421                                 __mmcamcorder_resource_state_to_str(resource_manager->rset->state));
422                         ret = MM_ERROR_RESOURCE_INVALID_STATE;
423                 } else {
424                         ret = mrp_res_release_resource_set(resource_manager->rset);
425                         if (ret) {
426                                 _mmcam_dbg_err("- could not release resource, ret(%d)", ret);
427                                 ret = MM_ERROR_RESOURCE_INTERNAL;
428                         } else {
429                                 _mmcam_dbg_log("resource release done");
430                         }
431                 }
432         }
433
434         return ret;
435 }
436
437
438 int _mmcamcorder_resource_manager_deinit(MMCamcorderResourceManager *resource_manager)
439 {
440         MMCAMCORDER_CHECK_RESOURCE_MANAGER_INSTANCE(resource_manager);
441
442         _mmcam_dbg_warn("rset %p, context %p, mloop %p",
443                 resource_manager->rset, resource_manager->context, resource_manager->mloop);
444
445         if (resource_manager->rset) {
446                 if (resource_manager->rset->state == MRP_RES_RESOURCE_ACQUIRED) {
447                         _mmcam_dbg_warn("resource is still acquired. release...");
448                         if (mrp_res_release_resource_set(resource_manager->rset))
449                                 _mmcam_dbg_err("- could not release resource");
450                 }
451
452                 _mmcam_dbg_warn("delete resource set");
453
454                 mrp_res_delete_resource_set(resource_manager->rset);
455                 resource_manager->rset = NULL;
456         }
457
458         if (resource_manager->context) {
459                 _mmcam_dbg_warn("destroy resource context");
460
461                 mrp_res_destroy(resource_manager->context);
462                 resource_manager->context = NULL;
463         }
464
465         if (resource_manager->mloop) {
466                 _mmcam_dbg_warn("destroy resource mainloop");
467
468                 mrp_mainloop_quit(resource_manager->mloop, 0);
469                 mrp_mainloop_destroy(resource_manager->mloop);
470                 resource_manager->mloop = NULL;
471         }
472
473         _mmcam_dbg_warn("done");
474
475         return MM_ERROR_NONE;
476 }