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 #define RESOURCE_LOG_INFO(fmt, args...) \
57 _mmcam_dbg_log("[%p][ID:%d] "fmt, resource_manager, resource_manager->id, ##args); \
60 #define RESOURCE_LOG_WARN(fmt, args...) \
62 _mmcam_dbg_warn("[%p][ID:%d] "fmt, resource_manager, resource_manager->id, ##args); \
65 #define RESOURCE_LOG_ERR(fmt, args...) \
67 _mmcam_dbg_err("[%p][ID:%d] "fmt, resource_manager, resource_manager->id, ##args); \
70 static char *__mmcamcorder_resource_state_to_str(mrp_res_resource_state_t st)
72 char *state = "unknown";
74 case MRP_RES_RESOURCE_ACQUIRED:
77 case MRP_RES_RESOURCE_LOST:
80 case MRP_RES_RESOURCE_AVAILABLE:
83 case MRP_RES_RESOURCE_PENDING:
86 case MRP_RES_RESOURCE_ABOUT_TO_LOOSE:
87 state = "about to loose";
93 static void __mmcamcorder_resource_state_callback(mrp_res_context_t *context, mrp_res_error_t err, void *user_data)
96 const mrp_res_resource_set_t *rset;
97 mrp_res_resource_t *resource;
98 mmf_camcorder_t *hcamcorder = NULL;
99 MMCamcorderResourceManager *resource_manager = (MMCamcorderResourceManager *)user_data;
101 mmf_return_if_fail(context);
102 mmf_return_if_fail(resource_manager);
104 hcamcorder = (mmf_camcorder_t *)resource_manager->hcamcorder;
106 mmf_return_if_fail(hcamcorder);
108 RESOURCE_LOG_WARN("enter - state %d", context->state);
110 _MMCAMCORDER_LOCK_RESOURCE(hcamcorder);
112 switch (context->state) {
113 case MRP_RES_CONNECTED:
114 RESOURCE_LOG_WARN(" - connected to Murphy");
115 if ((rset = mrp_res_list_resources(context)) != NULL) {
116 mrp_res_string_array_t *resource_names;
117 resource_names = mrp_res_list_resource_names(rset);
118 if (!resource_names) {
119 RESOURCE_LOG_ERR(" - no resources available");
120 _MMCAMCORDER_UNLOCK_RESOURCE(hcamcorder);
123 for (i = 0; i < resource_names->num_strings; i++) {
124 resource = mrp_res_get_resource_by_name(rset, resource_names->strings[i]);
126 RESOURCE_LOG_WARN(" - available resource: %s", resource->name);
128 mrp_res_free_string_array(resource_names);
130 resource_manager->is_connected = TRUE;
131 _MMCAMCORDER_RESOURCE_SIGNAL(hcamcorder);
133 case MRP_RES_DISCONNECTED:
134 RESOURCE_LOG_ERR(" - disconnected from Murphy : stop camcorder");
136 if (resource_manager->rset) {
137 mrp_res_delete_resource_set(resource_manager->rset);
138 resource_manager->rset = NULL;
141 if (resource_manager->context) {
142 mrp_res_destroy(resource_manager->context);
143 resource_manager->context = NULL;
144 resource_manager->is_connected = FALSE;
147 _MMCAMCORDER_UNLOCK_RESOURCE(hcamcorder);
149 _MMCAMCORDER_LOCK_ASM(hcamcorder);
151 /* Stop the camera */
152 __mmcamcorder_force_stop(hcamcorder, _MMCAMCORDER_STATE_CHANGE_BY_RM);
154 _MMCAMCORDER_UNLOCK_ASM(hcamcorder);
156 _MMCAMCORDER_LOCK_RESOURCE(hcamcorder);
160 _MMCAMCORDER_UNLOCK_RESOURCE(hcamcorder);
162 RESOURCE_LOG_WARN("leave");
168 static void __mmcamcorder_resource_set_state_callback(mrp_res_context_t *cx, const mrp_res_resource_set_t *rs, void *user_data)
171 mmf_camcorder_t *hcamcorder = NULL;
172 MMCamcorderResourceManager *resource_manager = (MMCamcorderResourceManager *)user_data;
173 mrp_res_resource_t *res = NULL;
175 mmf_return_if_fail(resource_manager && resource_manager->hcamcorder);
177 hcamcorder = (mmf_camcorder_t *)resource_manager->hcamcorder;
179 RESOURCE_LOG_WARN("start");
181 _MMCAMCORDER_LOCK_RESOURCE(hcamcorder);
183 if (!mrp_res_equal_resource_set(rs, resource_manager->rset)) {
184 RESOURCE_LOG_WARN("- resource set(%p) is not same as this handle's(%p)", rs, resource_manager->rset);
185 _MMCAMCORDER_UNLOCK_RESOURCE(hcamcorder);
189 RESOURCE_LOG_INFO(" - resource set state is changed to [%s]", __mmcamcorder_resource_state_to_str(rs->state));
191 for (i = 0; i < MM_CAMCORDER_RESOURCE_MAX; i++) {
192 res = mrp_res_get_resource_by_name(rs, mm_camcorder_resource_str[i]);
194 RESOURCE_LOG_WARN(" -- %s not present in resource set", mm_camcorder_resource_str[i]);
196 RESOURCE_LOG_WARN(" -- resource name [%s] -> [%s]",
197 res->name, __mmcamcorder_resource_state_to_str(res->state));
199 if (res->state == MRP_RES_RESOURCE_ACQUIRED) {
200 resource_manager->acquire_remain--;
202 if (resource_manager->acquire_remain <= 0) {
203 RESOURCE_LOG_WARN("send signal - resource acquire done");
204 _MMCAMCORDER_RESOURCE_SIGNAL(hcamcorder);
206 RESOURCE_LOG_WARN("remained acquire count %d",
207 resource_manager->acquire_remain);
209 } else if (res->state == MRP_RES_RESOURCE_LOST) {
210 resource_manager->acquire_remain++;
212 if (resource_manager->acquire_remain >= resource_manager->acquire_count) {
213 RESOURCE_LOG_WARN("resource release done");
215 if (hcamcorder->state > MM_CAMCORDER_STATE_NULL) {
216 RESOURCE_LOG_WARN("send resource signal");
217 _MMCAMCORDER_RESOURCE_SIGNAL(hcamcorder);
219 RESOURCE_LOG_WARN("skip resource signal - state %d", hcamcorder->state);
222 RESOURCE_LOG_WARN("acquired %d, lost %d",
223 resource_manager->acquire_count, resource_manager->acquire_remain);
229 mrp_res_delete_resource_set(resource_manager->rset);
230 resource_manager->rset = mrp_res_copy_resource_set(rs);
232 _MMCAMCORDER_UNLOCK_RESOURCE(hcamcorder);
234 RESOURCE_LOG_WARN("done");
240 static void __mmcamcorder_resource_release_cb(mrp_res_context_t *cx, const mrp_res_resource_set_t *rs, void *user_data)
243 int current_state = MM_CAMCORDER_STATE_NONE;
244 mmf_camcorder_t *hcamcorder = NULL;
245 MMCamcorderResourceManager *resource_manager = (MMCamcorderResourceManager *)user_data;
246 mrp_res_resource_t *res = NULL;
248 mmf_return_if_fail(resource_manager && resource_manager->hcamcorder);
250 hcamcorder = (mmf_camcorder_t *)resource_manager->hcamcorder;
252 current_state = _mmcamcorder_get_state((MMHandleType)hcamcorder);
253 if (current_state <= MM_CAMCORDER_STATE_NONE ||
254 current_state >= MM_CAMCORDER_STATE_NUM) {
255 RESOURCE_LOG_ERR("Abnormal state %d", current_state);
259 RESOURCE_LOG_WARN("enter");
261 _MMCAMCORDER_LOCK_RESOURCE(hcamcorder);
263 if (!mrp_res_equal_resource_set(rs, resource_manager->rset)) {
264 _MMCAMCORDER_UNLOCK_RESOURCE(hcamcorder);
265 RESOURCE_LOG_WARN("- resource set(%p) is not same as this handle's(%p)", rs, resource_manager->rset);
269 /* set flag for resource release callback */
270 resource_manager->is_release_cb_calling = TRUE;
272 RESOURCE_LOG_INFO(" - resource set state is changed to [%s]", __mmcamcorder_resource_state_to_str(rs->state));
274 for (i = 0; i < MM_CAMCORDER_RESOURCE_MAX; i++) {
275 res = mrp_res_get_resource_by_name(rs, mm_camcorder_resource_str[i]);
277 RESOURCE_LOG_WARN(" -- resource name [%s] -> [%s]",
278 res->name, __mmcamcorder_resource_state_to_str(res->state));
280 RESOURCE_LOG_WARN(" -- %s not present in resource set", mm_camcorder_resource_str[i]);
284 _MMCAMCORDER_UNLOCK_RESOURCE(hcamcorder);
286 _MMCAMCORDER_LOCK_ASM(hcamcorder);
288 if (resource_manager->id == MM_CAMCORDER_RESOURCE_ID_MAIN) {
290 __mmcamcorder_force_stop(hcamcorder, _MMCAMCORDER_STATE_CHANGE_BY_RM);
292 /* Stop video recording */
293 if (_mmcamcorder_commit((MMHandleType)hcamcorder) != MM_ERROR_NONE) {
294 RESOURCE_LOG_ERR("commit failed, cancel it");
295 _mmcamcorder_cancel((MMHandleType)hcamcorder);
299 _MMCAMCORDER_UNLOCK_ASM(hcamcorder);
301 _MMCAMCORDER_LOCK_RESOURCE(hcamcorder);
303 /* restore flag for resource release callback */
304 resource_manager->is_release_cb_calling = FALSE;
306 _MMCAMCORDER_UNLOCK_RESOURCE(hcamcorder);
308 RESOURCE_LOG_WARN("leave");
313 int _mmcamcorder_resource_create_resource_set(MMCamcorderResourceManager *resource_manager)
315 if (resource_manager->rset) {
316 RESOURCE_LOG_WARN(" - resource set was already created, delete it");
317 mrp_res_delete_resource_set(resource_manager->rset);
318 resource_manager->rset = NULL;
321 resource_manager->rset = mrp_res_create_resource_set(resource_manager->context,
322 MRP_APP_CLASS_FOR_CAMCORDER, __mmcamcorder_resource_set_state_callback, (void *)resource_manager);
324 if (resource_manager->rset == NULL) {
325 RESOURCE_LOG_ERR(" - could not create resource set");
326 return MM_ERROR_RESOURCE_INTERNAL;
329 if (!mrp_res_set_autorelease(TRUE, resource_manager->rset))
330 RESOURCE_LOG_WARN(" - could not set autorelease flag!");
332 RESOURCE_LOG_INFO("done");
334 return MM_ERROR_NONE;
337 static int __mmcamcorder_resource_include_resource(MMCamcorderResourceManager *resource_manager, const char *resource_name)
339 mrp_res_resource_t *resource = NULL;
340 resource = mrp_res_create_resource(resource_manager->rset,
342 MRP_RESOURCE_TYPE_MANDATORY,
343 MRP_RESOURCE_TYPE_EXCLUSIVE);
344 if (resource == NULL) {
345 RESOURCE_LOG_ERR(" - could not include resource[%s]", resource_name);
346 return MM_ERROR_RESOURCE_INTERNAL;
349 resource_manager->acquire_count++;
350 resource_manager->acquire_remain = resource_manager->acquire_count;
352 RESOURCE_LOG_INFO(" - count[%d] include resource[%s]",
353 resource_manager->acquire_count, resource_name);
355 return MM_ERROR_NONE;
358 static int __mmcamcorder_resource_set_release_cb(MMCamcorderResourceManager *resource_manager)
360 int ret = MM_ERROR_NONE;
361 bool mrp_ret = FALSE;
363 if (resource_manager->rset) {
364 mrp_ret = mrp_res_set_release_callback(resource_manager->rset, __mmcamcorder_resource_release_cb, (void *)resource_manager);
366 RESOURCE_LOG_ERR(" - could not set release callback");
367 ret = MM_ERROR_RESOURCE_INTERNAL;
370 RESOURCE_LOG_ERR(" - resource set is null");
371 ret = MM_ERROR_RESOURCE_INVALID_STATE;
377 int _mmcamcorder_resource_manager_init(MMCamcorderResourceManager *resource_manager)
379 GMainContext *mrp_ctx = NULL;
380 GMainLoop *mrp_loop = NULL;
382 MMCAMCORDER_CHECK_RESOURCE_MANAGER_INSTANCE(resource_manager);
384 RESOURCE_LOG_WARN("start");
386 mrp_ctx = g_main_context_new();
388 RESOURCE_LOG_ERR("failed to get create glib context for mrp");
389 return MM_ERROR_RESOURCE_INTERNAL;
392 mrp_loop = g_main_loop_new(mrp_ctx, TRUE);
394 g_main_context_unref(mrp_ctx);
398 RESOURCE_LOG_ERR("failed to get create glib loop for mrp");
399 return MM_ERROR_RESOURCE_INTERNAL;
402 resource_manager->mloop = mrp_mainloop_glib_get(mrp_loop);
404 g_main_loop_unref(mrp_loop);
407 if (!resource_manager->mloop) {
408 RESOURCE_LOG_ERR("failed to get mainloop for mrp");
409 return MM_ERROR_RESOURCE_INTERNAL;
412 RESOURCE_LOG_WARN("mloop %p", resource_manager->mloop);
414 resource_manager->context = mrp_res_create(resource_manager->mloop, __mmcamcorder_resource_state_callback, (void *)resource_manager);
415 if (!resource_manager->context) {
416 RESOURCE_LOG_ERR("could not get context for mrp");
418 mrp_mainloop_destroy(resource_manager->mloop);
419 resource_manager->mloop = NULL;
421 return MM_ERROR_RESOURCE_INTERNAL;
424 RESOURCE_LOG_INFO("done");
426 return MM_ERROR_NONE;
430 int _mmcamcorder_resource_wait_for_connection(MMCamcorderResourceManager *resource_manager)
432 int ret = MM_ERROR_NONE;
433 void *hcamcorder = NULL;
435 mmf_return_val_if_fail(resource_manager && resource_manager->hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
437 hcamcorder = resource_manager->hcamcorder;
439 _MMCAMCORDER_LOCK_RESOURCE(hcamcorder);
441 if (resource_manager->is_connected == FALSE) {
444 /* wait for resource manager connected */
445 RESOURCE_LOG_WARN("not connected. wait for signal...");
447 end_time = g_get_monotonic_time() + (__MMCAMCORDER_RESOURCE_WAIT_TIME * G_TIME_SPAN_SECOND);
449 if (_MMCAMCORDER_RESOURCE_WAIT_UNTIL(hcamcorder, end_time)) {
450 RESOURCE_LOG_WARN("signal received");
453 RESOURCE_LOG_ERR("connection timeout");
454 ret = MM_ERROR_RESOURCE_INTERNAL;
457 RESOURCE_LOG_WARN("already connected");
460 _MMCAMCORDER_UNLOCK_RESOURCE(hcamcorder);
466 int _mmcamcorder_resource_check_connection(MMCamcorderResourceManager *resource_manager)
468 int ret = MM_ERROR_NONE;
470 mmf_return_val_if_fail(resource_manager, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
472 if (resource_manager->is_connected == FALSE) {
473 RESOURCE_LOG_WARN("resource manager disconnected before, try to reconnect");
475 /* release remained resource */
476 _mmcamcorder_resource_manager_deinit(resource_manager);
478 /* init resource manager and wait for connection */
479 ret = _mmcamcorder_resource_manager_init(resource_manager);
480 if (ret != MM_ERROR_NONE) {
481 RESOURCE_LOG_ERR("failed to initialize resource manager");
485 ret = _mmcamcorder_resource_wait_for_connection(resource_manager);
486 if (ret != MM_ERROR_NONE) {
487 RESOURCE_LOG_ERR("failed to connect resource manager");
492 RESOURCE_LOG_WARN("done");
498 int _mmcamcorder_resource_manager_prepare(MMCamcorderResourceManager *resource_manager, MMCamcorderResourceType resource_type)
500 MMCAMCORDER_CHECK_RESOURCE_MANAGER_INSTANCE(resource_manager);
501 MMCAMCORDER_CHECK_CONNECTION_RESOURCE_MANAGER(resource_manager);
503 return __mmcamcorder_resource_include_resource(resource_manager, mm_camcorder_resource_str[resource_type]);
506 int _mmcamcorder_resource_manager_acquire(MMCamcorderResourceManager *resource_manager)
508 int ret = MM_ERROR_NONE;
509 MMCAMCORDER_CHECK_RESOURCE_MANAGER_INSTANCE(resource_manager);
510 MMCAMCORDER_CHECK_CONNECTION_RESOURCE_MANAGER(resource_manager);
512 if (resource_manager->rset == NULL) {
513 RESOURCE_LOG_ERR("- could not acquire resource, resource set is null");
514 ret = MM_ERROR_RESOURCE_INVALID_STATE;
516 ret = __mmcamcorder_resource_set_release_cb(resource_manager);
518 RESOURCE_LOG_ERR("- could not set resource release cb, ret(%d)", ret);
519 ret = MM_ERROR_RESOURCE_INTERNAL;
521 ret = mrp_res_acquire_resource_set(resource_manager->rset);
523 RESOURCE_LOG_ERR("- could not acquire resource, ret(%d)", ret);
524 ret = MM_ERROR_RESOURCE_INTERNAL;
532 int _mmcamcorder_resource_manager_release(MMCamcorderResourceManager *resource_manager)
534 int ret = MM_ERROR_NONE;
535 MMCAMCORDER_CHECK_RESOURCE_MANAGER_INSTANCE(resource_manager);
536 MMCAMCORDER_CHECK_CONNECTION_RESOURCE_MANAGER(resource_manager);
538 if (resource_manager->rset == NULL) {
539 RESOURCE_LOG_ERR("- could not release resource, resource set is null");
540 ret = MM_ERROR_RESOURCE_INVALID_STATE;
542 if (resource_manager->rset->state != MRP_RES_RESOURCE_ACQUIRED) {
543 RESOURCE_LOG_ERR("- could not release resource, resource set state is [%s]",
544 __mmcamcorder_resource_state_to_str(resource_manager->rset->state));
545 ret = MM_ERROR_RESOURCE_INVALID_STATE;
547 ret = mrp_res_release_resource_set(resource_manager->rset);
549 RESOURCE_LOG_ERR("- could not release resource, ret(%d)", ret);
550 ret = MM_ERROR_RESOURCE_INTERNAL;
552 RESOURCE_LOG_INFO("resource release done");
561 int _mmcamcorder_resource_manager_deinit(MMCamcorderResourceManager *resource_manager)
563 MMCAMCORDER_CHECK_RESOURCE_MANAGER_INSTANCE(resource_manager);
565 RESOURCE_LOG_WARN("rset %p, context %p, mloop %p",
566 resource_manager->rset, resource_manager->context, resource_manager->mloop);
568 if (resource_manager->rset) {
569 if (resource_manager->rset->state == MRP_RES_RESOURCE_ACQUIRED) {
570 RESOURCE_LOG_WARN("resource is still acquired. release...");
571 if (mrp_res_release_resource_set(resource_manager->rset))
572 RESOURCE_LOG_ERR("- could not release resource");
575 RESOURCE_LOG_WARN("delete resource set");
577 mrp_res_delete_resource_set(resource_manager->rset);
578 resource_manager->rset = NULL;
581 if (resource_manager->context) {
582 RESOURCE_LOG_WARN("destroy resource context");
584 mrp_res_destroy(resource_manager->context);
585 resource_manager->context = NULL;
588 if (resource_manager->mloop) {
589 RESOURCE_LOG_WARN("destroy resource mainloop");
591 mrp_mainloop_quit(resource_manager->mloop, 0);
592 mrp_mainloop_destroy(resource_manager->mloop);
593 resource_manager->mloop = NULL;
596 RESOURCE_LOG_WARN("done");
598 return MM_ERROR_NONE;