Remove build warning
[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         "video_encoder"
32 };
33
34 #define MMCAMCORDER_CHECK_RESOURCE_MANAGER_INSTANCE(x_camcorder_resource_manager) \
35 do { \
36         if (!x_camcorder_resource_manager) { \
37                 _mmcam_dbg_err("no resource manager instance"); \
38                 return MM_ERROR_INVALID_ARGUMENT; \
39         } \
40 } while (0);
41
42 #define MMCAMCORDER_CHECK_CONNECTION_RESOURCE_MANAGER(x_camcorder_resource_manager) \
43 do { \
44         if (!x_camcorder_resource_manager) { \
45                 _mmcam_dbg_err("no resource manager instance"); \
46                 return MM_ERROR_INVALID_ARGUMENT; \
47         } else { \
48                 if (!x_camcorder_resource_manager->is_connected) { \
49                         _mmcam_dbg_err("not connected to resource server yet"); \
50                         return MM_ERROR_RESOURCE_NOT_INITIALIZED; \
51                 } \
52         } \
53 } while (0);
54
55 static char *__mmcamcorder_resource_state_to_str(mrp_res_resource_state_t st)
56 {
57         char *state = "unknown";
58         switch (st) {
59         case MRP_RES_RESOURCE_ACQUIRED:
60                 state = "acquired";
61                 break;
62         case MRP_RES_RESOURCE_LOST:
63                 state = "lost";
64                 break;
65         case MRP_RES_RESOURCE_AVAILABLE:
66                 state = "available";
67                 break;
68         case MRP_RES_RESOURCE_PENDING:
69                 state = "pending";
70                 break;
71         case MRP_RES_RESOURCE_ABOUT_TO_LOOSE:
72                 state = "about to loose";
73                 break;
74         }
75         return state;
76 }
77
78 static void __mmcamcorder_resource_state_callback(mrp_res_context_t *context, mrp_res_error_t err, void *user_data)
79 {
80         int i = 0;
81         const mrp_res_resource_set_t *rset;
82         mrp_res_resource_t *resource;
83         mmf_camcorder_t *hcamcorder = NULL;
84         MMCamcorderResourceManager *resource_manager = (MMCamcorderResourceManager *)user_data;
85
86         mmf_return_if_fail(context);
87         mmf_return_if_fail(resource_manager);
88
89         hcamcorder = (mmf_camcorder_t *)resource_manager->hcamcorder;
90
91         mmf_return_if_fail(hcamcorder);
92
93         _mmcam_dbg_warn("enter - state %d", context->state);
94
95         _MMCAMCORDER_LOCK_RESOURCE(hcamcorder);
96
97         switch (context->state) {
98         case MRP_RES_CONNECTED:
99                 _mmcam_dbg_warn(" - 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(hcamcorder);
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_warn(" - available resource: %s", resource->name);
112                         }
113                         mrp_res_free_string_array(resource_names);
114                 }
115                 resource_manager->is_connected = TRUE;
116                 _MMCAMCORDER_RESOURCE_SIGNAL(hcamcorder);
117                 break;
118         case MRP_RES_DISCONNECTED:
119                 _mmcam_dbg_err(" - disconnected from Murphy : stop camcorder");
120
121                 if (resource_manager->rset) {
122                         mrp_res_delete_resource_set(resource_manager->rset);
123                         resource_manager->rset = NULL;
124                 }
125
126                 if (resource_manager->context) {
127                         mrp_res_destroy(resource_manager->context);
128                         resource_manager->context = NULL;
129                         resource_manager->is_connected = FALSE;
130                 }
131
132                 _MMCAMCORDER_UNLOCK_RESOURCE(hcamcorder);
133
134                 _MMCAMCORDER_LOCK_ASM(hcamcorder);
135
136                 /* Stop the camera */
137                 __mmcamcorder_force_stop(hcamcorder, _MMCAMCORDER_STATE_CHANGE_BY_RM);
138
139                 _MMCAMCORDER_UNLOCK_ASM(hcamcorder);
140
141                 _MMCAMCORDER_LOCK_RESOURCE(hcamcorder);
142                 break;
143         }
144
145         _MMCAMCORDER_UNLOCK_RESOURCE(hcamcorder);
146
147         _mmcam_dbg_warn("leave");
148
149         return;
150 }
151
152
153 static void __mmcamcorder_resource_set_state_callback(mrp_res_context_t *cx, const mrp_res_resource_set_t *rs, void *user_data)
154 {
155         int i = 0;
156         mmf_camcorder_t *hcamcorder = NULL;
157         MMCamcorderResourceManager *resource_manager = (MMCamcorderResourceManager *)user_data;
158         mrp_res_resource_t *res = NULL;
159
160         mmf_return_if_fail(resource_manager && resource_manager->hcamcorder);
161
162         hcamcorder = (mmf_camcorder_t *)resource_manager->hcamcorder;
163
164         _mmcam_dbg_warn("start");
165
166         _MMCAMCORDER_LOCK_RESOURCE(hcamcorder);
167
168         if (!mrp_res_equal_resource_set(rs, resource_manager->rset)) {
169                 _mmcam_dbg_warn("- resource set(%p) is not same as this handle's(%p)", rs, resource_manager->rset);
170                 _MMCAMCORDER_UNLOCK_RESOURCE(hcamcorder);
171                 return;
172         }
173
174         _mmcam_dbg_log(" - resource set state is changed to [%s]", __mmcamcorder_resource_state_to_str(rs->state));
175
176         for (i = 0; i < MM_CAMCORDER_RESOURCE_MAX; i++) {
177                 res = mrp_res_get_resource_by_name(rs, mm_camcorder_resource_str[i]);
178                 if (res == NULL) {
179                         _mmcam_dbg_warn(" -- %s not present in resource set", mm_camcorder_resource_str[i]);
180                 } else {
181                         _mmcam_dbg_warn(" -- resource name [%s] -> [%s]",
182                                 res->name, __mmcamcorder_resource_state_to_str(res->state));
183
184                         if (res->state == MRP_RES_RESOURCE_ACQUIRED) {
185                                 resource_manager->acquire_remain--;
186
187                                 if (resource_manager->acquire_remain <= 0) {
188                                         _mmcam_dbg_warn("send signal - resource acquire done");
189                                         _MMCAMCORDER_RESOURCE_SIGNAL(hcamcorder);
190                                 } else {
191                                         _mmcam_dbg_warn("remained acquire count %d",
192                                                 resource_manager->acquire_remain);
193                                 }
194                         } else if (res->state == MRP_RES_RESOURCE_LOST) {
195                                 resource_manager->acquire_remain++;
196
197                                 if (resource_manager->acquire_remain >= resource_manager->acquire_count) {
198                                         _mmcam_dbg_warn("resource release done");
199
200                                         if (hcamcorder->state > MM_CAMCORDER_STATE_NULL) {
201                                                 _mmcam_dbg_warn("send resource signal");
202                                                 _MMCAMCORDER_RESOURCE_SIGNAL(hcamcorder);
203                                         } else {
204                                                 _mmcam_dbg_warn("skip resource signal - state %d", hcamcorder->state);
205                                         }
206                                 } else {
207                                         _mmcam_dbg_warn("acquired %d, lost %d",
208                                                 resource_manager->acquire_count, resource_manager->acquire_remain);
209                                 }
210                         }
211                 }
212         }
213
214         mrp_res_delete_resource_set(resource_manager->rset);
215         resource_manager->rset = mrp_res_copy_resource_set(rs);
216
217         _MMCAMCORDER_UNLOCK_RESOURCE(hcamcorder);
218
219         _mmcam_dbg_warn("done");
220
221         return;
222 }
223
224
225 static void __mmcamcorder_resource_release_cb(mrp_res_context_t *cx, const mrp_res_resource_set_t *rs, void *user_data)
226 {
227         int i = 0;
228         int current_state = MM_CAMCORDER_STATE_NONE;
229         mmf_camcorder_t *hcamcorder = NULL;
230         MMCamcorderResourceManager *resource_manager = (MMCamcorderResourceManager *)user_data;
231         mrp_res_resource_t *res = NULL;
232
233         mmf_return_if_fail(resource_manager && resource_manager->hcamcorder);
234
235         hcamcorder = (mmf_camcorder_t *)resource_manager->hcamcorder;
236
237         current_state = _mmcamcorder_get_state((MMHandleType)hcamcorder);
238         if (current_state <= MM_CAMCORDER_STATE_NONE ||
239             current_state >= MM_CAMCORDER_STATE_NUM) {
240                 _mmcam_dbg_err("Abnormal state %d", current_state);
241                 return;
242         }
243
244         _mmcam_dbg_warn("enter");
245
246         _MMCAMCORDER_LOCK_RESOURCE(hcamcorder);
247
248         if (!mrp_res_equal_resource_set(rs, resource_manager->rset)) {
249                 _MMCAMCORDER_UNLOCK_RESOURCE(hcamcorder);
250                 _mmcam_dbg_warn("- resource set(%p) is not same as this handle's(%p)", rs, resource_manager->rset);
251                 return;
252         }
253
254         /* set flag for resource release callback */
255         resource_manager->is_release_cb_calling = TRUE;
256
257         _mmcam_dbg_log(" - resource set state is changed to [%s]", __mmcamcorder_resource_state_to_str(rs->state));
258
259         for (i = 0; i < MM_CAMCORDER_RESOURCE_MAX; i++) {
260                 res = mrp_res_get_resource_by_name(rs, mm_camcorder_resource_str[i]);
261                 if (res == NULL) {
262                         _mmcam_dbg_warn(" -- %s not present in resource set", mm_camcorder_resource_str[i]);
263                 } else {
264                         _mmcam_dbg_warn(" -- resource name [%s] -> [%s]", res->name, __mmcamcorder_resource_state_to_str(res->state));
265                 }
266         }
267
268         _MMCAMCORDER_UNLOCK_RESOURCE(hcamcorder);
269
270         _MMCAMCORDER_LOCK_ASM(hcamcorder);
271
272         if (resource_manager->id == MM_CAMCORDER_RESOURCE_ID_MAIN) {
273                 /* Stop camera */
274                 __mmcamcorder_force_stop(hcamcorder, _MMCAMCORDER_STATE_CHANGE_BY_RM);
275         } else {
276                 /* Stop video recording */
277                 if (_mmcamcorder_commit((MMHandleType)hcamcorder) != MM_ERROR_NONE) {
278                         _mmcam_dbg_err("commit failed, cancel it");
279                         _mmcamcorder_cancel((MMHandleType)hcamcorder);
280                 }
281         }
282
283         _MMCAMCORDER_UNLOCK_ASM(hcamcorder);
284
285         _MMCAMCORDER_LOCK_RESOURCE(hcamcorder);
286
287         /* restore flag for resource release callback */
288         resource_manager->is_release_cb_calling = FALSE;
289
290         _MMCAMCORDER_UNLOCK_RESOURCE(hcamcorder);
291
292         _mmcam_dbg_warn("leave");
293
294         return;
295 }
296
297 int _mmcamcorder_resource_create_resource_set(MMCamcorderResourceManager *resource_manager)
298 {
299         if (resource_manager->rset) {
300                 _mmcam_dbg_warn(" - resource set was already created, delete it");
301                 mrp_res_delete_resource_set(resource_manager->rset);
302                 resource_manager->rset = NULL;
303         }
304
305         resource_manager->rset = mrp_res_create_resource_set(resource_manager->context,
306                 MRP_APP_CLASS_FOR_CAMCORDER, __mmcamcorder_resource_set_state_callback, (void *)resource_manager);
307
308         if (resource_manager->rset == NULL) {
309                 _mmcam_dbg_err(" - could not create resource set");
310                 return MM_ERROR_RESOURCE_INTERNAL;
311         }
312
313         if (!mrp_res_set_autorelease(TRUE, resource_manager->rset))
314                 _mmcam_dbg_warn(" - could not set autorelease flag!");
315
316         _mmcam_dbg_log("done");
317
318         return MM_ERROR_NONE;
319 }
320
321 static int __mmcamcorder_resource_include_resource(MMCamcorderResourceManager *resource_manager, const char *resource_name)
322 {
323         mrp_res_resource_t *resource = NULL;
324         resource = mrp_res_create_resource(resource_manager->rset,
325                 resource_name,
326                 MRP_RESOURCE_TYPE_MANDATORY,
327                 MRP_RESOURCE_TYPE_EXCLUSIVE);
328         if (resource == NULL) {
329                 _mmcam_dbg_err(" - could not include resource[%s]", resource_name);
330                 return MM_ERROR_RESOURCE_INTERNAL;
331         }
332
333         resource_manager->acquire_count++;
334         resource_manager->acquire_remain = resource_manager->acquire_count;
335
336         _mmcam_dbg_log(" - count[%d] include resource[%s]",
337                 resource_manager->acquire_count, resource_name);
338
339         return MM_ERROR_NONE;
340 }
341
342 static int __mmcamcorder_resource_set_release_cb(MMCamcorderResourceManager *resource_manager)
343 {
344         int ret = MM_ERROR_NONE;
345         bool mrp_ret = FALSE;
346
347         if (resource_manager->rset) {
348                 mrp_ret = mrp_res_set_release_callback(resource_manager->rset, __mmcamcorder_resource_release_cb, (void *)resource_manager);
349                 if (!mrp_ret) {
350                         _mmcam_dbg_err(" - could not set release callback");
351                         ret = MM_ERROR_RESOURCE_INTERNAL;
352                 }
353         } else {
354                 _mmcam_dbg_err(" - resource set is null");
355                 ret = MM_ERROR_RESOURCE_INVALID_STATE;
356         }
357
358         return ret;
359 }
360
361 int _mmcamcorder_resource_manager_init(MMCamcorderResourceManager *resource_manager)
362 {
363         GMainContext *mrp_ctx = NULL;
364         GMainLoop *mrp_loop = NULL;
365
366         MMCAMCORDER_CHECK_RESOURCE_MANAGER_INSTANCE(resource_manager);
367
368         _mmcam_dbg_warn("start");
369
370         mrp_ctx = g_main_context_new();
371         if (!mrp_ctx) {
372                 _mmcam_dbg_err("failed to get create glib context for mrp");
373                 return MM_ERROR_RESOURCE_INTERNAL;
374         }
375
376         mrp_loop = g_main_loop_new(mrp_ctx, TRUE);
377
378         g_main_context_unref(mrp_ctx);
379         mrp_ctx = NULL;
380
381         if (!mrp_loop) {
382                 _mmcam_dbg_err("failed to get create glib loop for mrp");
383                 return MM_ERROR_RESOURCE_INTERNAL;
384         }
385
386         resource_manager->mloop = mrp_mainloop_glib_get(mrp_loop);
387
388         g_main_loop_unref(mrp_loop);
389         mrp_loop = NULL;
390
391         if (!resource_manager->mloop) {
392                 _mmcam_dbg_err("failed to get mainloop for mrp");
393                 return MM_ERROR_RESOURCE_INTERNAL;
394         }
395
396         _mmcam_dbg_warn("mloop %p", resource_manager->mloop);
397
398         resource_manager->context = mrp_res_create(resource_manager->mloop, __mmcamcorder_resource_state_callback, (void *)resource_manager);
399         if (!resource_manager->context) {
400                 _mmcam_dbg_err("could not get context for mrp");
401
402                 mrp_mainloop_destroy(resource_manager->mloop);
403                 resource_manager->mloop = NULL;
404
405                 return MM_ERROR_RESOURCE_INTERNAL;
406         }
407
408         _mmcam_dbg_log("done");
409
410         return MM_ERROR_NONE;
411 }
412
413
414 int _mmcamcorder_resource_wait_for_connection(MMCamcorderResourceManager *resource_manager)
415 {
416         int ret = MM_ERROR_NONE;
417         void *hcamcorder = NULL;
418
419         mmf_return_val_if_fail(resource_manager && resource_manager->hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
420
421         hcamcorder = resource_manager->hcamcorder;
422
423         _MMCAMCORDER_LOCK_RESOURCE(hcamcorder);
424
425         if (resource_manager->is_connected == FALSE) {
426                 gint64 end_time = 0;
427
428                 /* wait for resource manager connected */
429                 _mmcam_dbg_warn("not connected. wait for signal...");
430
431                 end_time = g_get_monotonic_time() + (__MMCAMCORDER_RESOURCE_WAIT_TIME * G_TIME_SPAN_SECOND);
432
433                 if (_MMCAMCORDER_RESOURCE_WAIT_UNTIL(hcamcorder, end_time)) {
434                         _mmcam_dbg_warn("signal received");
435                         ret = MM_ERROR_NONE;
436                 } else {
437                         _mmcam_dbg_err("connection timeout");
438                         ret = MM_ERROR_RESOURCE_INTERNAL;
439                 }
440         } else {
441                 _mmcam_dbg_warn("already connected [%d]", resource_manager->id);
442         }
443
444         _MMCAMCORDER_UNLOCK_RESOURCE(hcamcorder);
445
446         return ret;
447 }
448
449
450 int _mmcamcorder_resource_check_connection(MMCamcorderResourceManager *resource_manager)
451 {
452         int ret = MM_ERROR_NONE;
453
454         mmf_return_val_if_fail(resource_manager, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
455
456         if (resource_manager->is_connected == FALSE) {
457                 _mmcam_dbg_warn("resource manager[%d] disconnected before, try to reconnect", resource_manager->id);
458
459                 /* release remained resource */
460                 _mmcamcorder_resource_manager_deinit(resource_manager);
461
462                 /* init resource manager and wait for connection */
463                 ret = _mmcamcorder_resource_manager_init(resource_manager);
464                 if (ret != MM_ERROR_NONE) {
465                         _mmcam_dbg_err("failed to initialize resource manager[%d]", resource_manager->id);
466                         return ret;
467                 }
468
469                 ret = _mmcamcorder_resource_wait_for_connection(resource_manager);
470                 if (ret != MM_ERROR_NONE) {
471                         _mmcam_dbg_err("failed to connect resource manager[%d]", resource_manager->id);
472                         return ret;
473                 }
474         }
475
476         _mmcam_dbg_warn("done[%d]", resource_manager->id);
477
478         return ret;
479 }
480
481
482 int _mmcamcorder_resource_manager_prepare(MMCamcorderResourceManager *resource_manager, MMCamcorderResourceType resource_type)
483 {
484         MMCAMCORDER_CHECK_RESOURCE_MANAGER_INSTANCE(resource_manager);
485         MMCAMCORDER_CHECK_CONNECTION_RESOURCE_MANAGER(resource_manager);
486
487         return __mmcamcorder_resource_include_resource(resource_manager, mm_camcorder_resource_str[resource_type]);
488 }
489
490 int _mmcamcorder_resource_manager_acquire(MMCamcorderResourceManager *resource_manager)
491 {
492         int ret = MM_ERROR_NONE;
493         MMCAMCORDER_CHECK_RESOURCE_MANAGER_INSTANCE(resource_manager);
494         MMCAMCORDER_CHECK_CONNECTION_RESOURCE_MANAGER(resource_manager);
495
496         if (resource_manager->rset == NULL) {
497                 _mmcam_dbg_err("- could not acquire resource, resource set is null");
498                 ret = MM_ERROR_RESOURCE_INVALID_STATE;
499         } else {
500                 ret = __mmcamcorder_resource_set_release_cb(resource_manager);
501                 if (ret) {
502                         _mmcam_dbg_err("- could not set resource release cb, ret(%d)", ret);
503                         ret = MM_ERROR_RESOURCE_INTERNAL;
504                 } else {
505                         ret = mrp_res_acquire_resource_set(resource_manager->rset);
506                         if (ret) {
507                                 _mmcam_dbg_err("- could not acquire resource, ret(%d)", ret);
508                                 ret = MM_ERROR_RESOURCE_INTERNAL;
509                         }
510                 }
511         }
512
513         return ret;
514 }
515
516 int _mmcamcorder_resource_manager_release(MMCamcorderResourceManager *resource_manager)
517 {
518         int ret = MM_ERROR_NONE;
519         MMCAMCORDER_CHECK_RESOURCE_MANAGER_INSTANCE(resource_manager);
520         MMCAMCORDER_CHECK_CONNECTION_RESOURCE_MANAGER(resource_manager);
521
522         if (resource_manager->rset == NULL) {
523                 _mmcam_dbg_err("- could not release resource, resource set is null");
524                 ret = MM_ERROR_RESOURCE_INVALID_STATE;
525         } else {
526                 if (resource_manager->rset->state != MRP_RES_RESOURCE_ACQUIRED) {
527                         _mmcam_dbg_err("- could not release resource, resource set state is [%s]",
528                                 __mmcamcorder_resource_state_to_str(resource_manager->rset->state));
529                         ret = MM_ERROR_RESOURCE_INVALID_STATE;
530                 } else {
531                         ret = mrp_res_release_resource_set(resource_manager->rset);
532                         if (ret) {
533                                 _mmcam_dbg_err("- could not release resource, ret(%d)", ret);
534                                 ret = MM_ERROR_RESOURCE_INTERNAL;
535                         } else {
536                                 _mmcam_dbg_log("resource release done");
537                         }
538                 }
539         }
540
541         return ret;
542 }
543
544
545 int _mmcamcorder_resource_manager_deinit(MMCamcorderResourceManager *resource_manager)
546 {
547         MMCAMCORDER_CHECK_RESOURCE_MANAGER_INSTANCE(resource_manager);
548
549         _mmcam_dbg_warn("rset %p, context %p, mloop %p",
550                 resource_manager->rset, resource_manager->context, resource_manager->mloop);
551
552         if (resource_manager->rset) {
553                 if (resource_manager->rset->state == MRP_RES_RESOURCE_ACQUIRED) {
554                         _mmcam_dbg_warn("resource is still acquired. release...");
555                         if (mrp_res_release_resource_set(resource_manager->rset))
556                                 _mmcam_dbg_err("- could not release resource");
557                 }
558
559                 _mmcam_dbg_warn("delete resource set");
560
561                 mrp_res_delete_resource_set(resource_manager->rset);
562                 resource_manager->rset = NULL;
563         }
564
565         if (resource_manager->context) {
566                 _mmcam_dbg_warn("destroy resource context");
567
568                 mrp_res_destroy(resource_manager->context);
569                 resource_manager->context = NULL;
570         }
571
572         if (resource_manager->mloop) {
573                 _mmcam_dbg_warn("destroy resource mainloop");
574
575                 mrp_mainloop_quit(resource_manager->mloop, 0);
576                 mrp_mainloop_destroy(resource_manager->mloop);
577                 resource_manager->mloop = NULL;
578         }
579
580         _mmcam_dbg_warn("done");
581
582         return MM_ERROR_NONE;
583 }