Add new function to get old state
[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         camcorder = (mmf_camcorder_t*)user_data;
85
86         mmf_return_if_fail((MMHandleType)camcorder);
87         mmf_return_if_fail(context);
88
89         _mmcam_dbg_warn("enter - state %d", context->state);
90
91         _MMCAMCORDER_LOCK_RESOURCE(camcorder);
92
93         switch (context->state) {
94         case MRP_RES_CONNECTED:
95                 _mmcam_dbg_warn(" - connected to Murphy");
96                 if ((rset = mrp_res_list_resources(context)) != NULL) {
97                         mrp_res_string_array_t *resource_names;
98                         resource_names = mrp_res_list_resource_names(rset);
99                         if (!resource_names) {
100                                 _mmcam_dbg_err(" - no resources available");
101                                 _MMCAMCORDER_UNLOCK_RESOURCE(camcorder);
102                                 return;
103                         }
104                         for (i = 0; i < resource_names->num_strings; i++) {
105                                 resource = mrp_res_get_resource_by_name(rset, resource_names->strings[i]);
106                                 if (resource)
107                                         _mmcam_dbg_warn(" - available resource: %s", resource->name);
108                         }
109                         mrp_res_free_string_array(resource_names);
110                 }
111                 camcorder->resource_manager.is_connected = TRUE;
112                 _MMCAMCORDER_RESOURCE_SIGNAL(camcorder);
113                 break;
114         case MRP_RES_DISCONNECTED:
115                 _mmcam_dbg_err(" - disconnected from Murphy : stop camera");
116
117                 if (camcorder->resource_manager.rset) {
118                         mrp_res_delete_resource_set(camcorder->resource_manager.rset);
119                         camcorder->resource_manager.rset = NULL;
120                 }
121
122                 if (camcorder->resource_manager.context) {
123                         mrp_res_destroy(camcorder->resource_manager.context);
124                         camcorder->resource_manager.context = NULL;
125                         camcorder->resource_manager.is_connected = FALSE;
126                 }
127
128                 _MMCAMCORDER_UNLOCK_RESOURCE(camcorder);
129
130                 _MMCAMCORDER_LOCK_ASM(camcorder);
131
132                 /* set value to inform a status is changed by resource manaer */
133                 camcorder->state_change_by_system = _MMCAMCORDER_STATE_CHANGE_BY_RM;
134
135                 /* Stop the camera */
136                 __mmcamcorder_force_stop(camcorder);
137
138                 /* restore value */
139                 camcorder->state_change_by_system = _MMCAMCORDER_STATE_CHANGE_NORMAL;
140
141                 _MMCAMCORDER_UNLOCK_ASM(camcorder);
142
143                 _MMCAMCORDER_LOCK_RESOURCE(camcorder);
144                 break;
145         }
146
147         _MMCAMCORDER_UNLOCK_RESOURCE(camcorder);
148
149         _mmcam_dbg_warn("leave");
150
151         return;
152 }
153
154
155 static void __mmcamcorder_resource_set_state_callback(mrp_res_context_t *cx, const mrp_res_resource_set_t *rs, void *user_data)
156 {
157         int i = 0;
158         mmf_camcorder_t *camcorder = (mmf_camcorder_t *)user_data;
159         mrp_res_resource_t *res;
160
161         mmf_return_if_fail((MMHandleType)camcorder);
162
163         _MMCAMCORDER_LOCK_RESOURCE(camcorder);
164
165         if (!mrp_res_equal_resource_set(rs, camcorder->resource_manager.rset)) {
166                 _mmcam_dbg_warn("- resource set(%p) is not same as this camcorder handle's(%p)", rs, camcorder->resource_manager.rset);
167                 _MMCAMCORDER_UNLOCK_RESOURCE(camcorder);
168                 return;
169         }
170
171         _mmcam_dbg_log(" - resource set state of camcorder(%p) is changed to [%s]",
172                 camcorder, __mmcamcorder_resource_state_to_str(rs->state));
173
174         for (i = 0; i < MM_CAMCORDER_RESOURCE_MAX; i++) {
175                 res = mrp_res_get_resource_by_name(rs, mm_camcorder_resource_str[i]);
176                 if (res == NULL) {
177                         _mmcam_dbg_warn(" -- %s not present in resource set", mm_camcorder_resource_str[i]);
178                 } else {
179                         _mmcam_dbg_warn(" -- resource name [%s] -> [%s]",
180                                 res->name, __mmcamcorder_resource_state_to_str(res->state));
181
182                         if (res->state == MRP_RES_RESOURCE_ACQUIRED) {
183                                 camcorder->resource_manager.acquire_remain--;
184
185                                 if (camcorder->resource_manager.acquire_remain <= 0) {
186                                         _mmcam_dbg_warn("send signal - resource acquire done");
187                                         _MMCAMCORDER_RESOURCE_SIGNAL(camcorder);
188                                 } else {
189                                         _mmcam_dbg_warn("remained acquire count %d",
190                                                 camcorder->resource_manager.acquire_remain);
191                                 }
192                         } else if (res->state == MRP_RES_RESOURCE_LOST) {
193                                 camcorder->resource_manager.acquire_remain++;
194
195                                 if (camcorder->resource_manager.acquire_remain >= camcorder->resource_manager.acquire_count) {
196                                         _mmcam_dbg_warn("resource release done");
197
198                                         if (camcorder->state > MM_CAMCORDER_STATE_NULL) {
199                                                 _mmcam_dbg_warn("send resource signal");
200                                                 _MMCAMCORDER_RESOURCE_SIGNAL(camcorder);
201                                         } else {
202                                                 _mmcam_dbg_warn("skip resource signal - state %d", camcorder->state);
203                                         }
204                                 } else {
205                                         _mmcam_dbg_warn("acquired %d, lost %d",
206                                                 camcorder->resource_manager.acquire_count,
207                                                 camcorder->resource_manager.acquire_remain);
208                                 }
209                         }
210                 }
211         }
212
213         mrp_res_delete_resource_set(camcorder->resource_manager.rset);
214         camcorder->resource_manager.rset = mrp_res_copy_resource_set(rs);
215
216         _MMCAMCORDER_UNLOCK_RESOURCE(camcorder);
217
218         return;
219 }
220
221
222 static void __mmcamcorder_resource_release_cb(mrp_res_context_t *cx, const mrp_res_resource_set_t *rs, void *user_data)
223 {
224         int i = 0;
225         int current_state = MM_CAMCORDER_STATE_NONE;
226         mmf_camcorder_t* camcorder = (mmf_camcorder_t*)user_data;
227         mrp_res_resource_t *res;
228
229         mmf_return_if_fail((MMHandleType)camcorder);
230
231         current_state = _mmcamcorder_get_state((MMHandleType)camcorder);
232         if (current_state <= MM_CAMCORDER_STATE_NONE ||
233             current_state >= MM_CAMCORDER_STATE_NUM) {
234                 _mmcam_dbg_err("Abnormal state. Or null handle. (%p, %d)", camcorder, current_state);
235                 return;
236         }
237
238         _mmcam_dbg_warn("enter");
239
240         _MMCAMCORDER_LOCK_RESOURCE(camcorder);
241
242         if (!mrp_res_equal_resource_set(rs, camcorder->resource_manager.rset)) {
243                 _MMCAMCORDER_UNLOCK_RESOURCE(camcorder);
244                 _mmcam_dbg_warn("- resource set(%p) is not same as this camcorder handle's(%p)", rs, camcorder->resource_manager.rset);
245                 return;
246         }
247
248         /* set flag for resource release callback */
249         camcorder->resource_release_cb_calling = TRUE;
250
251         _mmcam_dbg_log(" - resource set state of camcorder(%p) is changed to [%s]",
252                 camcorder, __mmcamcorder_resource_state_to_str(rs->state));
253
254         for (i = 0; i < MM_CAMCORDER_RESOURCE_MAX; i++) {
255                 res = mrp_res_get_resource_by_name(rs, mm_camcorder_resource_str[i]);
256                 if (res == NULL) {
257                         _mmcam_dbg_warn(" -- %s not present in resource set", mm_camcorder_resource_str[i]);
258                 } else {
259                         _mmcam_dbg_warn(" -- resource name [%s] -> [%s]", res->name, __mmcamcorder_resource_state_to_str(res->state));
260                 }
261         }
262
263         _MMCAMCORDER_UNLOCK_RESOURCE(camcorder);
264
265         _MMCAMCORDER_LOCK_ASM(camcorder);
266
267         /* set value to inform a status is changed by resource manager */
268         camcorder->state_change_by_system = _MMCAMCORDER_STATE_CHANGE_BY_RM;
269
270         /* Stop the camera */
271         __mmcamcorder_force_stop(camcorder);
272
273         /* restore value */
274         camcorder->state_change_by_system = _MMCAMCORDER_STATE_CHANGE_NORMAL;
275
276         _MMCAMCORDER_UNLOCK_ASM(camcorder);
277
278         _MMCAMCORDER_LOCK_RESOURCE(camcorder);
279
280         /* restore flag for resource release callback */
281         camcorder->resource_release_cb_calling = FALSE;
282
283         _MMCAMCORDER_UNLOCK_RESOURCE(camcorder);
284
285         _mmcam_dbg_warn("leave");
286
287         return;
288 }
289
290 int _mmcamcorder_resource_create_resource_set(MMCamcorderResourceManager *resource_manager)
291 {
292         if (resource_manager->rset) {
293                 _mmcam_dbg_warn(" - resource set was already created, delete it");
294                 mrp_res_delete_resource_set(resource_manager->rset);
295                 resource_manager->rset = NULL;
296         }
297
298         resource_manager->rset = mrp_res_create_resource_set(resource_manager->context,
299                 MRP_APP_CLASS_FOR_CAMCORDER, __mmcamcorder_resource_set_state_callback, (void*)resource_manager->user_data);
300
301         if (resource_manager->rset == NULL) {
302                 _mmcam_dbg_err(" - could not create resource set");
303                 return MM_ERROR_RESOURCE_INTERNAL;
304         }
305
306         if (!mrp_res_set_autorelease(TRUE, resource_manager->rset))
307                 _mmcam_dbg_warn(" - could not set autorelease flag!");
308
309         _mmcam_dbg_log("done");
310
311         return MM_ERROR_NONE;
312 }
313
314 static int __mmcamcorder_resource_include_resource(MMCamcorderResourceManager *resource_manager, const char *resource_name)
315 {
316         mrp_res_resource_t *resource = NULL;
317         resource = mrp_res_create_resource(resource_manager->rset,
318                 resource_name,
319                 MRP_RESOURCE_TYPE_MANDATORY,
320                 MRP_RESOURCE_TYPE_EXCLUSIVE);
321         if (resource == NULL) {
322                 _mmcam_dbg_err(" - could not include resource[%s]", resource_name);
323                 return MM_ERROR_RESOURCE_INTERNAL;
324         }
325
326         resource_manager->acquire_count++;
327         resource_manager->acquire_remain = resource_manager->acquire_count;
328
329         _mmcam_dbg_log(" - count[%d] include resource[%s]",
330                 resource_manager->acquire_count, resource_name);
331
332         return MM_ERROR_NONE;
333 }
334
335 static int __mmcamcorder_resource_set_release_cb(MMCamcorderResourceManager *resource_manager)
336 {
337         int ret = MM_ERROR_NONE;
338         bool mrp_ret = FALSE;
339
340         if (resource_manager->rset) {
341                 mrp_ret = mrp_res_set_release_callback(resource_manager->rset, __mmcamcorder_resource_release_cb, resource_manager->user_data);
342                 if (!mrp_ret) {
343                         _mmcam_dbg_err(" - could not set release callback");
344                         ret = MM_ERROR_RESOURCE_INTERNAL;
345                 }
346         } else {
347                 _mmcam_dbg_err(" - resource set is null");
348                 ret = MM_ERROR_RESOURCE_INVALID_STATE;
349         }
350
351         return ret;
352 }
353
354 int _mmcamcorder_resource_manager_init(MMCamcorderResourceManager *resource_manager, void *user_data)
355 {
356         GMainContext *mrp_ctx = NULL;
357         GMainLoop *mrp_loop = NULL;
358
359         MMCAMCORDER_CHECK_RESOURCE_MANAGER_INSTANCE(resource_manager);
360
361         _mmcam_dbg_warn("start");
362
363         mrp_ctx = g_main_context_new();
364         if (!mrp_ctx) {
365                 _mmcam_dbg_err("failed to get create glib context for mrp");
366                 return MM_ERROR_RESOURCE_INTERNAL;
367         }
368
369         mrp_loop = g_main_loop_new(mrp_ctx, TRUE);
370
371         g_main_context_unref(mrp_ctx);
372         mrp_ctx = NULL;
373
374         if (!mrp_loop) {
375                 _mmcam_dbg_err("failed to get create glib loop for mrp");
376                 return MM_ERROR_RESOURCE_INTERNAL;
377         }
378
379         resource_manager->mloop = mrp_mainloop_glib_get(mrp_loop);
380
381         g_main_loop_unref(mrp_loop);
382         mrp_loop = NULL;
383
384         if (!resource_manager->mloop) {
385                 _mmcam_dbg_err("failed to get mainloop for mrp");
386                 return MM_ERROR_RESOURCE_INTERNAL;
387         }
388
389         _mmcam_dbg_warn("mloop %p", resource_manager->mloop);
390
391         resource_manager->context = mrp_res_create(resource_manager->mloop, __mmcamcorder_resource_state_callback, user_data);
392         if (!resource_manager->context) {
393                 _mmcam_dbg_err("could not get context for mrp");
394
395                 mrp_mainloop_destroy(resource_manager->mloop);
396                 resource_manager->mloop = NULL;
397
398                 return MM_ERROR_RESOURCE_INTERNAL;
399         }
400
401         resource_manager->user_data = user_data;
402
403         _mmcam_dbg_log("done");
404
405         return MM_ERROR_NONE;
406 }
407
408
409 int _mmcamcorder_resource_wait_for_connection(MMCamcorderResourceManager *resource_manager, void *hcamcorder)
410 {
411         int ret = MM_ERROR_NONE;
412
413         mmf_return_val_if_fail(resource_manager && hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
414
415         _MMCAMCORDER_LOCK_RESOURCE(hcamcorder);
416
417         if (resource_manager->is_connected == FALSE) {
418                 gint64 end_time = 0;
419
420                 /* wait for resource manager connected */
421                 _mmcam_dbg_warn("not connected. wait for signal...");
422
423                 end_time = g_get_monotonic_time() + (__MMCAMCORDER_RESOURCE_WAIT_TIME * G_TIME_SPAN_SECOND);
424
425                 if (_MMCAMCORDER_RESOURCE_WAIT_UNTIL(hcamcorder, end_time)) {
426                         _mmcam_dbg_warn("signal received");
427                         ret = MM_ERROR_NONE;
428                 } else {
429                         _mmcam_dbg_err("connection timeout");
430                         ret = MM_ERROR_RESOURCE_INTERNAL;
431                 }
432         } else {
433                 _mmcam_dbg_warn("already connected");
434         }
435
436         _MMCAMCORDER_UNLOCK_RESOURCE(hcamcorder);
437
438         return ret;
439 }
440
441
442 int _mmcamcorder_resource_manager_prepare(MMCamcorderResourceManager *resource_manager, MMCamcorderResourceType resource_type)
443 {
444         MMCAMCORDER_CHECK_RESOURCE_MANAGER_INSTANCE(resource_manager);
445         MMCAMCORDER_CHECK_CONNECTION_RESOURCE_MANAGER(resource_manager);
446
447         return __mmcamcorder_resource_include_resource(resource_manager, mm_camcorder_resource_str[resource_type]);
448 }
449
450 int _mmcamcorder_resource_manager_acquire(MMCamcorderResourceManager *resource_manager)
451 {
452         int ret = MM_ERROR_NONE;
453         MMCAMCORDER_CHECK_RESOURCE_MANAGER_INSTANCE(resource_manager);
454         MMCAMCORDER_CHECK_CONNECTION_RESOURCE_MANAGER(resource_manager);
455
456         if (resource_manager->rset == NULL) {
457                 _mmcam_dbg_err("- could not acquire resource, resource set is null");
458                 ret = MM_ERROR_RESOURCE_INVALID_STATE;
459         } else {
460                 ret = __mmcamcorder_resource_set_release_cb(resource_manager);
461                 if (ret) {
462                         _mmcam_dbg_err("- could not set resource release cb, ret(%d)", ret);
463                         ret = MM_ERROR_RESOURCE_INTERNAL;
464                 } else {
465                         ret = mrp_res_acquire_resource_set(resource_manager->rset);
466                         if (ret) {
467                                 _mmcam_dbg_err("- could not acquire resource, ret(%d)", ret);
468                                 ret = MM_ERROR_RESOURCE_INTERNAL;
469                         }
470                 }
471         }
472
473         return ret;
474 }
475
476 int _mmcamcorder_resource_manager_release(MMCamcorderResourceManager *resource_manager)
477 {
478         int ret = MM_ERROR_NONE;
479         MMCAMCORDER_CHECK_RESOURCE_MANAGER_INSTANCE(resource_manager);
480         MMCAMCORDER_CHECK_CONNECTION_RESOURCE_MANAGER(resource_manager);
481
482         if (resource_manager->rset == NULL) {
483                 _mmcam_dbg_err("- could not release resource, resource set is null");
484                 ret = MM_ERROR_RESOURCE_INVALID_STATE;
485         } else {
486                 if (resource_manager->rset->state != MRP_RES_RESOURCE_ACQUIRED) {
487                         _mmcam_dbg_err("- could not release resource, resource set state is [%s]",
488                                 __mmcamcorder_resource_state_to_str(resource_manager->rset->state));
489                         ret = MM_ERROR_RESOURCE_INVALID_STATE;
490                 } else {
491                         ret = mrp_res_release_resource_set(resource_manager->rset);
492                         if (ret) {
493                                 _mmcam_dbg_err("- could not release resource, ret(%d)", ret);
494                                 ret = MM_ERROR_RESOURCE_INTERNAL;
495                         } else {
496                                 _mmcam_dbg_log("resource release done");
497                         }
498                 }
499         }
500
501         return ret;
502 }
503
504
505 int _mmcamcorder_resource_manager_deinit(MMCamcorderResourceManager *resource_manager)
506 {
507         MMCAMCORDER_CHECK_RESOURCE_MANAGER_INSTANCE(resource_manager);
508
509         _mmcam_dbg_warn("rset %p, context %p, mloop %p",
510                 resource_manager->rset, resource_manager->context, resource_manager->mloop);
511
512         if (resource_manager->rset) {
513                 if (resource_manager->rset->state == MRP_RES_RESOURCE_ACQUIRED) {
514                         _mmcam_dbg_warn("resource is still acquired. release...");
515                         if (mrp_res_release_resource_set(resource_manager->rset))
516                                 _mmcam_dbg_err("- could not release resource");
517                 }
518
519                 _mmcam_dbg_warn("delete resource set");
520
521                 mrp_res_delete_resource_set(resource_manager->rset);
522                 resource_manager->rset = NULL;
523         }
524
525         if (resource_manager->context) {
526                 _mmcam_dbg_warn("destroy resource context");
527
528                 mrp_res_destroy(resource_manager->context);
529                 resource_manager->context = NULL;
530         }
531
532         if (resource_manager->mloop) {
533                 _mmcam_dbg_warn("destroy resource mainloop");
534
535                 mrp_mainloop_quit(resource_manager->mloop, 0);
536                 mrp_mainloop_destroy(resource_manager->mloop);
537                 resource_manager->mloop = NULL;
538         }
539
540         _mmcam_dbg_warn("done");
541
542         return MM_ERROR_NONE;
543 }