75708544779fe7ef7acfdadfdddad42e2c01af2c
[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         if (err != MRP_RES_ERROR_NONE) {
85                 _mmcam_dbg_err(" - error message received from Murphy, err(0x%x)", err);
86                 return;
87         }
88
89         camcorder = (mmf_camcorder_t*)user_data;
90
91         mmf_return_if_fail((MMHandleType)camcorder);
92
93         switch (context->state) {
94         case MRP_RES_CONNECTED:
95                 _mmcam_dbg_log(" - 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                                 return;
102                         }
103                         for (i = 0; i < resource_names->num_strings; i++) {
104                                 resource = mrp_res_get_resource_by_name(rset, resource_names->strings[i]);
105                                 if (resource) {
106                                         _mmcam_dbg_log(" - available resource: %s", resource->name);
107                                 }
108                         }
109                         mrp_res_free_string_array(resource_names);
110                 }
111                 camcorder->resource_manager.is_connected = TRUE;
112                 break;
113         case MRP_RES_DISCONNECTED:
114                 _mmcam_dbg_log(" - disconnected from Murphy");
115                 if (camcorder->resource_manager.rset) {
116                         mrp_res_delete_resource_set(camcorder->resource_manager.rset);
117                         camcorder->resource_manager.rset = NULL;
118                 }
119                 if (camcorder->resource_manager.context) {
120                         mrp_res_destroy(camcorder->resource_manager.context);
121                         camcorder->resource_manager.context = NULL;
122                         camcorder->resource_manager.is_connected = FALSE;
123                 }
124                 break;
125         }
126
127         return;
128 }
129
130
131 static void __mmcamcorder_resource_set_state_callback(mrp_res_context_t *cx, const mrp_res_resource_set_t *rs, void *user_data)
132 {
133         int i = 0;
134         mmf_camcorder_t *camcorder = (mmf_camcorder_t *)user_data;
135         mrp_res_resource_t *res;
136
137         mmf_return_if_fail((MMHandleType)camcorder);
138
139         _MMCAMCORDER_LOCK_RESOURCE(camcorder);
140
141         if (!mrp_res_equal_resource_set(rs, camcorder->resource_manager.rset)) {
142                 _mmcam_dbg_warn("- resource set(%p) is not same as this camcorder handle's(%p)", rs, camcorder->resource_manager.rset);
143                 _MMCAMCORDER_UNLOCK_RESOURCE(camcorder);
144                 return;
145         }
146
147         _mmcam_dbg_log(" - resource set state of camcorder(%p) is changed to [%s]",
148                 camcorder, __mmcamcorder_resource_state_to_str(rs->state));
149
150         for (i = 0; i < MM_CAMCORDER_RESOURCE_MAX; i++) {
151                 res = mrp_res_get_resource_by_name(rs, mm_camcorder_resource_str[i]);
152                 if (res == NULL) {
153                         _mmcam_dbg_warn(" -- %s not present in resource set", mm_camcorder_resource_str[i]);
154                 } else {
155                         _mmcam_dbg_log(" -- resource name [%s] -> [%s]",
156                                 res->name, __mmcamcorder_resource_state_to_str(res->state));
157
158                         if (res->state == MRP_RES_RESOURCE_ACQUIRED) {
159                                 camcorder->resource_manager.acquire_count--;
160
161                                 if (camcorder->resource_manager.acquire_count <= 0) {
162                                         _mmcam_dbg_log("send signal - resource acquire done");
163                                         _MMCAMCORDER_RESOURCE_SIGNAL(camcorder);
164                                 } else {
165                                         _mmcam_dbg_warn("remained acquire count %d",
166                                                 camcorder->resource_manager.acquire_count);
167                                 }
168                         }
169                 }
170         }
171
172         mrp_res_delete_resource_set(camcorder->resource_manager.rset);
173         camcorder->resource_manager.rset = mrp_res_copy_resource_set(rs);
174
175         _MMCAMCORDER_UNLOCK_RESOURCE(camcorder);
176
177         return;
178 }
179
180
181 static void __mmcamcorder_resource_release_cb(mrp_res_context_t *cx, const mrp_res_resource_set_t *rs, void *user_data)
182 {
183         int i = 0;
184         int current_state = MM_CAMCORDER_STATE_NONE;
185         mmf_camcorder_t* camcorder = (mmf_camcorder_t*)user_data;
186         mrp_res_resource_t *res;
187
188         mmf_return_if_fail((MMHandleType)camcorder);
189
190         current_state = _mmcamcorder_get_state((MMHandleType)camcorder);
191         if (current_state <= MM_CAMCORDER_STATE_NONE ||
192             current_state >= MM_CAMCORDER_STATE_NUM) {
193                 _mmcam_dbg_err("Abnormal state. Or null handle. (%p, %d)", camcorder, current_state);
194                 return;
195         }
196
197         /* set value to inform a status is changed by resource manaer */
198         camcorder->state_change_by_system = _MMCAMCORDER_STATE_CHANGE_BY_RM;
199
200         _MMCAMCORDER_LOCK_ASM(camcorder);
201
202         if (!mrp_res_equal_resource_set(rs, camcorder->resource_manager.rset)) {
203                 _MMCAMCORDER_UNLOCK_ASM(camcorder);
204                 _mmcam_dbg_warn("- resource set(%p) is not same as this camcorder handle's(%p)", rs, camcorder->resource_manager.rset);
205                 return;
206         }
207
208         _mmcam_dbg_log(" - resource set state of camcorder(%p) is changed to [%s]",
209                 camcorder, __mmcamcorder_resource_state_to_str(rs->state));
210
211         for (i = 0; i < MM_CAMCORDER_RESOURCE_MAX; i++) {
212                 res = mrp_res_get_resource_by_name(rs, mm_camcorder_resource_str[i]);
213                 if (res == NULL) {
214                         _mmcam_dbg_warn(" -- %s not present in resource set", mm_camcorder_resource_str[i]);
215                 } else {
216                         _mmcam_dbg_log(" -- resource name [%s] -> [%s]",
217                                 res->name, __mmcamcorder_resource_state_to_str(res->state));
218                 }
219         }
220
221         /* Stop the camera */
222         __mmcamcorder_force_stop(camcorder);
223
224         /* restore value */
225         camcorder->state_change_by_system = _MMCAMCORDER_STATE_CHANGE_NORMAL;
226
227         _MMCAMCORDER_UNLOCK_ASM(camcorder);
228
229         return;
230 }
231
232 static int __mmcamcorder_resource_create_resource_set(MMCamcorderResourceManager *resource_manager)
233 {
234         if (resource_manager->rset) {
235                 _mmcam_dbg_err(" - resource set was already created");
236                 return MM_ERROR_RESOURCE_INVALID_STATE;
237         }
238
239         resource_manager->rset = mrp_res_create_resource_set(resource_manager->context,
240                 MRP_APP_CLASS_FOR_CAMCORDER, __mmcamcorder_resource_set_state_callback, (void*)resource_manager->user_data);
241
242         if (resource_manager->rset == NULL) {
243                 _mmcam_dbg_err(" - could not create resource set");
244                 return MM_ERROR_RESOURCE_INTERNAL;
245         }
246
247         if (!mrp_res_set_autorelease(TRUE, resource_manager->rset)) {
248                 _mmcam_dbg_warn(" - could not set autorelease flag!");
249         }
250
251         return MM_ERROR_NONE;
252 }
253
254 static int __mmcamcorder_resource_include_resource(MMCamcorderResourceManager *resource_manager, const char *resource_name)
255 {
256         mrp_res_resource_t *resource = NULL;
257         resource = mrp_res_create_resource(resource_manager->rset,
258                                 resource_name,
259                                 MRP_RESOURCE_TYPE_MANDATORY,
260                                 MRP_RESOURCE_TYPE_EXCLUSIVE);
261         if (resource == NULL) {
262                 _mmcam_dbg_err(" - could not include resource[%s]", resource_name);
263                 return MM_ERROR_RESOURCE_INTERNAL;
264         }
265
266         resource_manager->acquire_count++;
267
268         _mmcam_dbg_log(" - count[%d] include resource[%s]",
269                 resource_manager->acquire_count, resource_name);
270
271         return MM_ERROR_NONE;
272 }
273
274 static int __mmcamcorder_resource_set_release_cb(MMCamcorderResourceManager *resource_manager)
275 {
276         int ret = MM_ERROR_NONE;
277         bool mrp_ret = FALSE;
278
279         if (resource_manager->rset) {
280                 mrp_ret = mrp_res_set_release_callback(resource_manager->rset, __mmcamcorder_resource_release_cb, resource_manager->user_data);
281                 if (!mrp_ret) {
282                         _mmcam_dbg_err(" - could not set release callback");
283                         ret = MM_ERROR_RESOURCE_INTERNAL;
284                 }
285         } else {
286                 _mmcam_dbg_err(" - resource set is null");
287                 ret = MM_ERROR_RESOURCE_INVALID_STATE;
288         }
289
290         return ret;
291 }
292
293 int _mmcamcorder_resource_manager_init(MMCamcorderResourceManager *resource_manager, void *user_data)
294 {
295         MMCAMCORDER_CHECK_RESOURCE_MANAGER_INSTANCE(resource_manager);
296
297         resource_manager->mloop = mrp_mainloop_glib_get(g_main_loop_new(NULL, TRUE));
298         if (resource_manager->mloop) {
299                 resource_manager->context = mrp_res_create(resource_manager->mloop, __mmcamcorder_resource_state_callback, user_data);
300                 if (resource_manager->context == NULL) {
301                         _mmcam_dbg_err(" - could not get context for resource manager");
302                         mrp_mainloop_destroy(resource_manager->mloop);
303                         resource_manager->mloop = NULL;
304                         return MM_ERROR_RESOURCE_INTERNAL;
305                 }
306                 resource_manager->user_data = user_data;
307         } else {
308                 _mmcam_dbg_err("- could not get mainloop for resource manager");
309                 return MM_ERROR_RESOURCE_INTERNAL;
310         }
311
312         return MM_ERROR_NONE;
313 }
314
315 int _mmcamcorder_resource_manager_prepare(MMCamcorderResourceManager *resource_manager, MMCamcorderResourceType resource_type)
316 {
317         int ret = MM_ERROR_NONE;
318         MMCAMCORDER_CHECK_RESOURCE_MANAGER_INSTANCE(resource_manager);
319         MMCAMCORDER_CHECK_CONNECTION_RESOURCE_MANAGER(resource_manager);
320
321         if (!resource_manager->rset) {
322                 ret = __mmcamcorder_resource_create_resource_set(resource_manager);
323         }
324         if (ret == MM_ERROR_NONE) {
325                 ret = __mmcamcorder_resource_include_resource(resource_manager, mm_camcorder_resource_str[resource_type]);
326         } else {
327                 _mmcam_dbg_err("failed to create resource set 0x%x", ret);
328         }
329
330         return ret;
331 }
332
333 int _mmcamcorder_resource_manager_acquire(MMCamcorderResourceManager *resource_manager)
334 {
335         int ret = MM_ERROR_NONE;
336         MMCAMCORDER_CHECK_RESOURCE_MANAGER_INSTANCE(resource_manager);
337         MMCAMCORDER_CHECK_CONNECTION_RESOURCE_MANAGER(resource_manager);
338
339         if (resource_manager->rset == NULL) {
340                 _mmcam_dbg_err("- could not acquire resource, resource set is null");
341                 ret = MM_ERROR_RESOURCE_INVALID_STATE;
342         } else {
343                 ret = __mmcamcorder_resource_set_release_cb(resource_manager);
344                 if (ret) {
345                         _mmcam_dbg_err("- could not set resource release cb, ret(%d)", ret);
346                         ret = MM_ERROR_RESOURCE_INTERNAL;
347                 } else {
348                         ret = mrp_res_acquire_resource_set(resource_manager->rset);
349                         if (ret) {
350                                 _mmcam_dbg_err("- could not acquire resource, ret(%d)", ret);
351                                 ret = MM_ERROR_RESOURCE_INTERNAL;
352                         }
353                 }
354         }
355
356         return ret;
357 }
358
359 int _mmcamcorder_resource_manager_release(MMCamcorderResourceManager *resource_manager)
360 {
361         int ret = MM_ERROR_NONE;
362         MMCAMCORDER_CHECK_RESOURCE_MANAGER_INSTANCE(resource_manager);
363         MMCAMCORDER_CHECK_CONNECTION_RESOURCE_MANAGER(resource_manager);
364
365         if (resource_manager->rset == NULL) {
366                 _mmcam_dbg_err("- could not release resource, resource set is null");
367                 ret = MM_ERROR_RESOURCE_INVALID_STATE;
368         } else {
369                 if (resource_manager->rset->state != MRP_RES_RESOURCE_ACQUIRED) {
370                         _mmcam_dbg_err("- could not release resource, resource set state is [%s]",
371                                 __mmcamcorder_resource_state_to_str(resource_manager->rset->state));
372                         ret = MM_ERROR_RESOURCE_INVALID_STATE;
373                 } else {
374                         ret = mrp_res_release_resource_set(resource_manager->rset);
375                         if (ret) {
376                                 _mmcam_dbg_err("- could not release resource, ret(%d)", ret);
377                                 ret = MM_ERROR_RESOURCE_INTERNAL;
378                         } else {
379                                 _mmcam_dbg_log("resource release done");
380                         }
381                 }
382         }
383
384         return ret;
385 }
386
387 int _mmcamcorder_resource_manager_unprepare(MMCamcorderResourceManager *resource_manager)
388 {
389         int ret = MM_ERROR_NONE;
390         MMCAMCORDER_CHECK_RESOURCE_MANAGER_INSTANCE(resource_manager);
391         MMCAMCORDER_CHECK_CONNECTION_RESOURCE_MANAGER(resource_manager);
392
393         if (resource_manager->rset == NULL) {
394                 _mmcam_dbg_err("- could not unprepare for resource_manager, _mmcamcorder_resource_manager_prepare() first");
395                 ret = MM_ERROR_RESOURCE_INVALID_STATE;
396         } else {
397                 mrp_res_delete_resource_set(resource_manager->rset);
398                 resource_manager->rset = NULL;
399                 _mmcam_dbg_log("delete resource set done");
400         }
401
402         return ret;
403 }
404
405 int _mmcamcorder_resource_manager_deinit(MMCamcorderResourceManager *resource_manager)
406 {
407         MMCAMCORDER_CHECK_RESOURCE_MANAGER_INSTANCE(resource_manager);
408         MMCAMCORDER_CHECK_CONNECTION_RESOURCE_MANAGER(resource_manager);
409
410         if (resource_manager->rset) {
411                 if (resource_manager->rset->state == MRP_RES_RESOURCE_ACQUIRED) {
412                         _mmcam_dbg_warn("resource is still acquired. release...");
413                         if (mrp_res_release_resource_set(resource_manager->rset))
414                                 _mmcam_dbg_err("- could not release resource");
415                 }
416                 _mmcam_dbg_log("delete resource set");
417                 mrp_res_delete_resource_set(resource_manager->rset);
418                 resource_manager->rset = NULL;
419         }
420         if (resource_manager->context) {
421                 _mmcam_dbg_log("destroy resource context");
422                 mrp_res_destroy(resource_manager->context);
423                 resource_manager->context = NULL;
424         }
425         if (resource_manager->mloop) {
426                 _mmcam_dbg_log("destroy resource mainloop");
427                 mrp_mainloop_destroy(resource_manager->mloop);
428                 resource_manager->mloop = NULL;
429         }
430
431         return MM_ERROR_NONE;
432 }