4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
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
10 * http://www.apache.org/licenses/LICENSE-2.0
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.
20 #include "mm_camcorder_internal.h"
21 #include "mm_camcorder_resource.h"
22 #include <murphy/common/glib-glue.h>
24 #define MRP_APP_CLASS_FOR_CAMCORDER "media"
25 #define MRP_RESOURCE_TYPE_MANDATORY TRUE
26 #define MRP_RESOURCE_TYPE_EXCLUSIVE FALSE
28 const char* mm_camcorder_resource_str[MM_CAMCORDER_RESOURCE_MAX] = {
34 #define MMCAMCORDER_CHECK_RESOURCE_MANAGER_INSTANCE(x_camcorder_resource_manager) \
36 if (!x_camcorder_resource_manager) { \
37 _mmcam_dbg_err("no resource manager instance"); \
38 return MM_ERROR_INVALID_ARGUMENT; \
42 #define MMCAMCORDER_CHECK_CONNECTION_RESOURCE_MANAGER(x_camcorder_resource_manager) \
44 if (!x_camcorder_resource_manager) { \
45 _mmcam_dbg_err("no resource manager instance"); \
46 return MM_ERROR_INVALID_ARGUMENT; \
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; \
55 static char *__mmcamcorder_resource_state_to_str(mrp_res_resource_state_t st)
57 char *state = "unknown";
59 case MRP_RES_RESOURCE_ACQUIRED:
62 case MRP_RES_RESOURCE_LOST:
65 case MRP_RES_RESOURCE_AVAILABLE:
68 case MRP_RES_RESOURCE_PENDING:
71 case MRP_RES_RESOURCE_ABOUT_TO_LOOSE:
72 state = "about to loose";
78 static void __mmcamcorder_resource_state_callback(mrp_res_context_t *context, mrp_res_error_t err, void *user_data)
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;
86 mmf_return_if_fail(context);
87 mmf_return_if_fail(resource_manager);
89 hcamcorder = (mmf_camcorder_t *)resource_manager->hcamcorder;
91 mmf_return_if_fail(hcamcorder);
93 _mmcam_dbg_warn("enter - state %d", context->state);
95 _MMCAMCORDER_LOCK_RESOURCE(hcamcorder);
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);
108 for (i = 0; i < resource_names->num_strings; i++) {
109 resource = mrp_res_get_resource_by_name(rset, resource_names->strings[i]);
111 _mmcam_dbg_warn(" - available resource: %s", resource->name);
113 mrp_res_free_string_array(resource_names);
115 resource_manager->is_connected = TRUE;
116 _MMCAMCORDER_RESOURCE_SIGNAL(hcamcorder);
118 case MRP_RES_DISCONNECTED:
119 _mmcam_dbg_err(" - disconnected from Murphy : stop camcorder");
121 if (resource_manager->rset) {
122 mrp_res_delete_resource_set(resource_manager->rset);
123 resource_manager->rset = NULL;
126 if (resource_manager->context) {
127 mrp_res_destroy(resource_manager->context);
128 resource_manager->context = NULL;
129 resource_manager->is_connected = FALSE;
132 _MMCAMCORDER_UNLOCK_RESOURCE(hcamcorder);
134 _MMCAMCORDER_LOCK_ASM(hcamcorder);
136 /* Stop the camera */
137 __mmcamcorder_force_stop(hcamcorder, _MMCAMCORDER_STATE_CHANGE_BY_RM);
139 _MMCAMCORDER_UNLOCK_ASM(hcamcorder);
141 _MMCAMCORDER_LOCK_RESOURCE(hcamcorder);
145 _MMCAMCORDER_UNLOCK_RESOURCE(hcamcorder);
147 _mmcam_dbg_warn("leave");
153 static void __mmcamcorder_resource_set_state_callback(mrp_res_context_t *cx, const mrp_res_resource_set_t *rs, void *user_data)
156 mmf_camcorder_t *hcamcorder = NULL;
157 MMCamcorderResourceManager *resource_manager = (MMCamcorderResourceManager *)user_data;
158 mrp_res_resource_t *res = NULL;
160 mmf_return_if_fail(resource_manager && resource_manager->hcamcorder);
162 hcamcorder = (mmf_camcorder_t *)resource_manager->hcamcorder;
164 _mmcam_dbg_warn("start");
166 _MMCAMCORDER_LOCK_RESOURCE(hcamcorder);
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);
174 _mmcam_dbg_log(" - resource set state is changed to [%s]", __mmcamcorder_resource_state_to_str(rs->state));
176 for (i = 0; i < MM_CAMCORDER_RESOURCE_MAX; i++) {
177 res = mrp_res_get_resource_by_name(rs, mm_camcorder_resource_str[i]);
179 _mmcam_dbg_warn(" -- %s not present in resource set", mm_camcorder_resource_str[i]);
181 _mmcam_dbg_warn(" -- resource name [%s] -> [%s]",
182 res->name, __mmcamcorder_resource_state_to_str(res->state));
184 if (res->state == MRP_RES_RESOURCE_ACQUIRED) {
185 resource_manager->acquire_remain--;
187 if (resource_manager->acquire_remain <= 0) {
188 _mmcam_dbg_warn("send signal - resource acquire done");
189 _MMCAMCORDER_RESOURCE_SIGNAL(hcamcorder);
191 _mmcam_dbg_warn("remained acquire count %d",
192 resource_manager->acquire_remain);
194 } else if (res->state == MRP_RES_RESOURCE_LOST) {
195 resource_manager->acquire_remain++;
197 if (resource_manager->acquire_remain >= resource_manager->acquire_count) {
198 _mmcam_dbg_warn("resource release done");
200 if (hcamcorder->state > MM_CAMCORDER_STATE_NULL) {
201 _mmcam_dbg_warn("send resource signal");
202 _MMCAMCORDER_RESOURCE_SIGNAL(hcamcorder);
204 _mmcam_dbg_warn("skip resource signal - state %d", hcamcorder->state);
207 _mmcam_dbg_warn("acquired %d, lost %d",
208 resource_manager->acquire_count, resource_manager->acquire_remain);
214 mrp_res_delete_resource_set(resource_manager->rset);
215 resource_manager->rset = mrp_res_copy_resource_set(rs);
217 _MMCAMCORDER_UNLOCK_RESOURCE(hcamcorder);
219 _mmcam_dbg_warn("done");
225 static void __mmcamcorder_resource_release_cb(mrp_res_context_t *cx, const mrp_res_resource_set_t *rs, void *user_data)
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;
233 mmf_return_if_fail(resource_manager && resource_manager->hcamcorder);
235 hcamcorder = (mmf_camcorder_t *)resource_manager->hcamcorder;
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);
244 _mmcam_dbg_warn("enter");
246 _MMCAMCORDER_LOCK_RESOURCE(hcamcorder);
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);
254 /* set flag for resource release callback */
255 resource_manager->is_release_cb_calling = TRUE;
257 _mmcam_dbg_log(" - resource set state is changed to [%s]", __mmcamcorder_resource_state_to_str(rs->state));
259 for (i = 0; i < MM_CAMCORDER_RESOURCE_MAX; i++) {
260 res = mrp_res_get_resource_by_name(rs, mm_camcorder_resource_str[i]);
262 _mmcam_dbg_warn(" -- %s not present in resource set", mm_camcorder_resource_str[i]);
264 _mmcam_dbg_warn(" -- resource name [%s] -> [%s]", res->name, __mmcamcorder_resource_state_to_str(res->state));
268 _MMCAMCORDER_UNLOCK_RESOURCE(hcamcorder);
270 _MMCAMCORDER_LOCK_ASM(hcamcorder);
272 if (resource_manager->id == MM_CAMCORDER_RESOURCE_ID_MAIN) {
274 __mmcamcorder_force_stop(hcamcorder, _MMCAMCORDER_STATE_CHANGE_BY_RM);
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);
283 _MMCAMCORDER_UNLOCK_ASM(hcamcorder);
285 _MMCAMCORDER_LOCK_RESOURCE(hcamcorder);
287 /* restore flag for resource release callback */
288 resource_manager->is_release_cb_calling = FALSE;
290 _MMCAMCORDER_UNLOCK_RESOURCE(hcamcorder);
292 _mmcam_dbg_warn("leave");
297 int _mmcamcorder_resource_create_resource_set(MMCamcorderResourceManager *resource_manager)
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;
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);
308 if (resource_manager->rset == NULL) {
309 _mmcam_dbg_err(" - could not create resource set");
310 return MM_ERROR_RESOURCE_INTERNAL;
313 if (!mrp_res_set_autorelease(TRUE, resource_manager->rset))
314 _mmcam_dbg_warn(" - could not set autorelease flag!");
316 _mmcam_dbg_log("done");
318 return MM_ERROR_NONE;
321 static int __mmcamcorder_resource_include_resource(MMCamcorderResourceManager *resource_manager, const char *resource_name)
323 mrp_res_resource_t *resource = NULL;
324 resource = mrp_res_create_resource(resource_manager->rset,
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;
333 resource_manager->acquire_count++;
334 resource_manager->acquire_remain = resource_manager->acquire_count;
336 _mmcam_dbg_log(" - count[%d] include resource[%s]",
337 resource_manager->acquire_count, resource_name);
339 return MM_ERROR_NONE;
342 static int __mmcamcorder_resource_set_release_cb(MMCamcorderResourceManager *resource_manager)
344 int ret = MM_ERROR_NONE;
345 bool mrp_ret = FALSE;
347 if (resource_manager->rset) {
348 mrp_ret = mrp_res_set_release_callback(resource_manager->rset, __mmcamcorder_resource_release_cb, (void *)resource_manager);
350 _mmcam_dbg_err(" - could not set release callback");
351 ret = MM_ERROR_RESOURCE_INTERNAL;
354 _mmcam_dbg_err(" - resource set is null");
355 ret = MM_ERROR_RESOURCE_INVALID_STATE;
361 int _mmcamcorder_resource_manager_init(MMCamcorderResourceManager *resource_manager)
363 GMainContext *mrp_ctx = NULL;
364 GMainLoop *mrp_loop = NULL;
366 MMCAMCORDER_CHECK_RESOURCE_MANAGER_INSTANCE(resource_manager);
368 _mmcam_dbg_warn("start");
370 mrp_ctx = g_main_context_new();
372 _mmcam_dbg_err("failed to get create glib context for mrp");
373 return MM_ERROR_RESOURCE_INTERNAL;
376 mrp_loop = g_main_loop_new(mrp_ctx, TRUE);
378 g_main_context_unref(mrp_ctx);
382 _mmcam_dbg_err("failed to get create glib loop for mrp");
383 return MM_ERROR_RESOURCE_INTERNAL;
386 resource_manager->mloop = mrp_mainloop_glib_get(mrp_loop);
388 g_main_loop_unref(mrp_loop);
391 if (!resource_manager->mloop) {
392 _mmcam_dbg_err("failed to get mainloop for mrp");
393 return MM_ERROR_RESOURCE_INTERNAL;
396 _mmcam_dbg_warn("mloop %p", resource_manager->mloop);
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");
402 mrp_mainloop_destroy(resource_manager->mloop);
403 resource_manager->mloop = NULL;
405 return MM_ERROR_RESOURCE_INTERNAL;
408 _mmcam_dbg_log("done");
410 return MM_ERROR_NONE;
414 int _mmcamcorder_resource_wait_for_connection(MMCamcorderResourceManager *resource_manager)
416 int ret = MM_ERROR_NONE;
417 void *hcamcorder = NULL;
419 mmf_return_val_if_fail(resource_manager && resource_manager->hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
421 hcamcorder = resource_manager->hcamcorder;
423 _MMCAMCORDER_LOCK_RESOURCE(hcamcorder);
425 if (resource_manager->is_connected == FALSE) {
428 /* wait for resource manager connected */
429 _mmcam_dbg_warn("not connected. wait for signal...");
431 end_time = g_get_monotonic_time() + (__MMCAMCORDER_RESOURCE_WAIT_TIME * G_TIME_SPAN_SECOND);
433 if (_MMCAMCORDER_RESOURCE_WAIT_UNTIL(hcamcorder, end_time)) {
434 _mmcam_dbg_warn("signal received");
437 _mmcam_dbg_err("connection timeout");
438 ret = MM_ERROR_RESOURCE_INTERNAL;
441 _mmcam_dbg_warn("already connected [%d]", resource_manager->id);
444 _MMCAMCORDER_UNLOCK_RESOURCE(hcamcorder);
450 int _mmcamcorder_resource_check_connection(MMCamcorderResourceManager *resource_manager)
452 int ret = MM_ERROR_NONE;
454 mmf_return_val_if_fail(resource_manager, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
456 if (resource_manager->is_connected == FALSE) {
457 _mmcam_dbg_warn("resource manager[%d] disconnected before, try to reconnect", resource_manager->id);
459 /* release remained resource */
460 _mmcamcorder_resource_manager_deinit(resource_manager);
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);
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);
476 _mmcam_dbg_warn("done[%d]", resource_manager->id);
482 int _mmcamcorder_resource_manager_prepare(MMCamcorderResourceManager *resource_manager, MMCamcorderResourceType resource_type)
484 MMCAMCORDER_CHECK_RESOURCE_MANAGER_INSTANCE(resource_manager);
485 MMCAMCORDER_CHECK_CONNECTION_RESOURCE_MANAGER(resource_manager);
487 return __mmcamcorder_resource_include_resource(resource_manager, mm_camcorder_resource_str[resource_type]);
490 int _mmcamcorder_resource_manager_acquire(MMCamcorderResourceManager *resource_manager)
492 int ret = MM_ERROR_NONE;
493 MMCAMCORDER_CHECK_RESOURCE_MANAGER_INSTANCE(resource_manager);
494 MMCAMCORDER_CHECK_CONNECTION_RESOURCE_MANAGER(resource_manager);
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;
500 ret = __mmcamcorder_resource_set_release_cb(resource_manager);
502 _mmcam_dbg_err("- could not set resource release cb, ret(%d)", ret);
503 ret = MM_ERROR_RESOURCE_INTERNAL;
505 ret = mrp_res_acquire_resource_set(resource_manager->rset);
507 _mmcam_dbg_err("- could not acquire resource, ret(%d)", ret);
508 ret = MM_ERROR_RESOURCE_INTERNAL;
516 int _mmcamcorder_resource_manager_release(MMCamcorderResourceManager *resource_manager)
518 int ret = MM_ERROR_NONE;
519 MMCAMCORDER_CHECK_RESOURCE_MANAGER_INSTANCE(resource_manager);
520 MMCAMCORDER_CHECK_CONNECTION_RESOURCE_MANAGER(resource_manager);
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;
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;
531 ret = mrp_res_release_resource_set(resource_manager->rset);
533 _mmcam_dbg_err("- could not release resource, ret(%d)", ret);
534 ret = MM_ERROR_RESOURCE_INTERNAL;
536 _mmcam_dbg_log("resource release done");
545 int _mmcamcorder_resource_manager_deinit(MMCamcorderResourceManager *resource_manager)
547 MMCAMCORDER_CHECK_RESOURCE_MANAGER_INSTANCE(resource_manager);
549 _mmcam_dbg_warn("rset %p, context %p, mloop %p",
550 resource_manager->rset, resource_manager->context, resource_manager->mloop);
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");
559 _mmcam_dbg_warn("delete resource set");
561 mrp_res_delete_resource_set(resource_manager->rset);
562 resource_manager->rset = NULL;
565 if (resource_manager->context) {
566 _mmcam_dbg_warn("destroy resource context");
568 mrp_res_destroy(resource_manager->context);
569 resource_manager->context = NULL;
572 if (resource_manager->mloop) {
573 _mmcam_dbg_warn("destroy resource mainloop");
575 mrp_mainloop_quit(resource_manager->mloop, 0);
576 mrp_mainloop_destroy(resource_manager->mloop);
577 resource_manager->mloop = NULL;
580 _mmcam_dbg_warn("done");
582 return MM_ERROR_NONE;