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