8b363d0306ddf7b92991716078321bac8c469250
[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 enum {
29         MRP_RESOURCE_FOR_VIDEO_OVERLAY,
30         MRP_RESOURCE_FOR_CAMERA,
31         MRP_RESOURCE_MAX,
32 };
33 const char* resource_str[MRP_RESOURCE_MAX] = {
34     "video_overlay",
35     "camera",
36 };
37
38 #define MMCAMCORDER_CHECK_RESOURCE_MANAGER_INSTANCE(x_camcorder_resource_manager) \
39 do { \
40         if (!x_camcorder_resource_manager) { \
41                 _mmcam_dbg_err("no resource manager instance"); \
42                 return MM_ERROR_INVALID_ARGUMENT; \
43         } \
44 } while(0);
45
46 #define MMCAMCORDER_CHECK_CONNECTION_RESOURCE_MANAGER(x_camcorder_resource_manager) \
47 do { \
48         if (!x_camcorder_resource_manager) { \
49                 _mmcam_dbg_err("no resource manager instance"); \
50                 return MM_ERROR_INVALID_ARGUMENT; \
51         } else { \
52                 if (!x_camcorder_resource_manager->is_connected) { \
53                         _mmcam_dbg_err("not connected to resource server yet"); \
54                         return MM_ERROR_RESOURCE_NOT_INITIALIZED; \
55                 } \
56         } \
57 } while(0);
58
59 static char *state_to_str(mrp_res_resource_state_t st)
60 {
61         char *state = "unknown";
62         switch (st) {
63         case MRP_RES_RESOURCE_ACQUIRED:
64                 state = "acquired";
65                 break;
66         case MRP_RES_RESOURCE_LOST:
67                 state = "lost";
68                 break;
69         case MRP_RES_RESOURCE_AVAILABLE:
70                 state = "available";
71                 break;
72         case MRP_RES_RESOURCE_PENDING:
73                 state = "pending";
74                 break;
75         case MRP_RES_RESOURCE_ABOUT_TO_LOOSE:
76                 state = "about to loose";
77                 break;
78         }
79         return state;
80 }
81
82 static void mrp_state_callback(mrp_res_context_t *context, mrp_res_error_t err, void *user_data)
83 {
84         int i = 0;
85         const mrp_res_resource_set_t *rset;
86         mrp_res_resource_t *resource;
87         mmf_camcorder_t* camcorder = NULL;
88
89         if (err != MRP_RES_ERROR_NONE) {
90                 _mmcam_dbg_err(" - error message received from Murphy, err(0x%x)", err);
91                 return;
92         }
93
94         camcorder = (mmf_camcorder_t*)user_data;
95
96         mmf_return_if_fail((MMHandleType)camcorder);
97
98         switch (context->state) {
99         case MRP_RES_CONNECTED:
100                 _mmcam_dbg_log(" - connected to Murphy");
101                 if ((rset = mrp_res_list_resources(context)) != NULL) {
102                         mrp_res_string_array_t *resource_names;
103                         resource_names = mrp_res_list_resource_names(rset);
104                         if (!resource_names) {
105                                 _mmcam_dbg_err(" - no resources available");
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_log(" - available resource: %s", resource->name);
112                                 }
113                         }
114                         mrp_res_free_string_array(resource_names);
115                 }
116                 camcorder->resource_manager.is_connected = TRUE;
117                 break;
118         case MRP_RES_DISCONNECTED:
119                 _mmcam_dbg_log(" - disconnected from Murphy");
120                 if (camcorder->resource_manager.rset) {
121                         mrp_res_delete_resource_set(camcorder->resource_manager.rset);
122                         camcorder->resource_manager.rset = NULL;
123                 }
124                 if (camcorder->resource_manager.context) {
125                         mrp_res_destroy(camcorder->resource_manager.context);
126                         camcorder->resource_manager.context = NULL;
127                         camcorder->resource_manager.is_connected = FALSE;
128                 }
129                 break;
130         }
131
132         return;
133 }
134
135
136 static void mrp_rset_state_callback(mrp_res_context_t *cx, const mrp_res_resource_set_t *rs, void *user_data)
137 {
138         int i = 0;
139         mmf_camcorder_t *camcorder = (mmf_camcorder_t *)user_data;
140         mrp_res_resource_t *res;
141
142         mmf_return_if_fail((MMHandleType)camcorder);
143
144         if (!mrp_res_equal_resource_set(rs, camcorder->resource_manager.rset)) {
145                 _mmcam_dbg_warn("- resource set(%p) is not same as this camcorder handle's(%p)", rs, camcorder->resource_manager.rset);
146                 return;
147         }
148
149         _mmcam_dbg_log(" - resource set state of camcorder(%p) is changed to [%s]", camcorder, state_to_str(rs->state));
150         for (i = 0; i < MRP_RESOURCE_MAX; i++) {
151                 res = mrp_res_get_resource_by_name(rs, resource_str[i]);
152                 if (res == NULL) {
153                         _mmcam_dbg_warn(" -- %s not present in resource set", resource_str[i]);
154                 } else {
155                         _mmcam_dbg_log(" -- resource name [%s] -> [%s]", res->name, state_to_str(res->state));
156                 }
157         }
158
159         mrp_res_delete_resource_set(camcorder->resource_manager.rset);
160         camcorder->resource_manager.rset = mrp_res_copy_resource_set(rs);
161
162         return;
163 }
164
165
166 static void mrp_resource_release_cb (mrp_res_context_t *cx, const mrp_res_resource_set_t *rs, void *user_data)
167 {
168         int i = 0;
169         int current_state = MM_CAMCORDER_STATE_NONE;
170         mmf_camcorder_t* camcorder = (mmf_camcorder_t*)user_data;
171         mrp_res_resource_t *res;
172
173         mmf_return_if_fail((MMHandleType)camcorder);
174
175         current_state = _mmcamcorder_get_state((MMHandleType)camcorder);
176         if (current_state <= MM_CAMCORDER_STATE_NONE ||
177             current_state >= MM_CAMCORDER_STATE_NUM) {
178                 _mmcam_dbg_err("Abnormal state. Or null handle. (%p, %d)", camcorder, current_state);
179                 return;
180         }
181
182         /* set value to inform a status is changed by resource manaer */
183         camcorder->state_change_by_system = _MMCAMCORDER_STATE_CHANGE_BY_RM;
184
185         _MMCAMCORDER_LOCK_ASM(camcorder);
186
187         if (!mrp_res_equal_resource_set(rs, camcorder->resource_manager.rset)) {
188                 _mmcam_dbg_warn("- resource set(%p) is not same as this camcorder handle's(%p)", rs, camcorder->resource_manager.rset);
189                 return;
190         }
191
192         _mmcam_dbg_log(" - resource set state of camcorder(%p) is changed to [%s]", camcorder, state_to_str(rs->state));
193         for (i = 0; i < MRP_RESOURCE_MAX; i++) {
194                 res = mrp_res_get_resource_by_name(rs, resource_str[i]);
195                 if (res == NULL) {
196                         _mmcam_dbg_warn(" -- %s not present in resource set", resource_str[i]);
197                 } else {
198                         _mmcam_dbg_log(" -- resource name [%s] -> [%s]", res->name, state_to_str(res->state));
199                 }
200         }
201
202         /* Stop the camera */
203         __mmcamcorder_force_stop(camcorder);
204
205         /* restore value */
206         camcorder->state_change_by_system = _MMCAMCORDER_STATE_CHANGE_NORMAL;
207
208         _MMCAMCORDER_UNLOCK_ASM(camcorder);
209
210         return;
211 }
212
213 static int create_rset(MMCamcorderResourceManager *resource_manager)
214 {
215         if (resource_manager->rset) {
216                 _mmcam_dbg_err(" - resource set was already created");
217                 return MM_ERROR_RESOURCE_INVALID_STATE;
218         }
219
220         resource_manager->rset = mrp_res_create_resource_set(resource_manager->context,
221                                 MRP_APP_CLASS_FOR_CAMCORDER,
222                                 mrp_rset_state_callback,
223                                 (void*)resource_manager->user_data);
224         if (resource_manager->rset == NULL) {
225                 _mmcam_dbg_err(" - could not create resource set");
226                 return MM_ERROR_RESOURCE_INTERNAL;
227         }
228
229         if (!mrp_res_set_autorelease(TRUE, resource_manager->rset)) {
230                 _mmcam_dbg_warn(" - could not set autorelease flag!");
231         }
232
233         return MM_ERROR_NONE;
234 }
235
236 static int include_resource(MMCamcorderResourceManager *resource_manager, const char *resource_name)
237 {
238         mrp_res_resource_t *resource = NULL;
239         resource = mrp_res_create_resource(resource_manager->rset,
240                                 resource_name,
241                                 MRP_RESOURCE_TYPE_MANDATORY,
242                                 MRP_RESOURCE_TYPE_EXCLUSIVE);
243         if (resource == NULL) {
244                 _mmcam_dbg_err(" - could not include resource[%s]", resource_name);
245                 return MM_ERROR_RESOURCE_INTERNAL;
246         }
247
248         _mmcam_dbg_log(" - include resource[%s]", resource_name);
249
250         return MM_ERROR_NONE;
251 }
252
253 static int set_resource_release_cb(MMCamcorderResourceManager *resource_manager)
254 {
255         int ret = MM_ERROR_NONE;
256         bool mrp_ret = FALSE;
257
258         if (resource_manager->rset) {
259                 mrp_ret = mrp_res_set_release_callback(resource_manager->rset, mrp_resource_release_cb, resource_manager->user_data);
260                 if (!mrp_ret) {
261                         _mmcam_dbg_err(" - could not set release callback");
262                         ret = MM_ERROR_RESOURCE_INTERNAL;
263                 }
264         } else {
265                 _mmcam_dbg_err(" - resource set is null");
266                 ret = MM_ERROR_RESOURCE_INVALID_STATE;
267         }
268
269         return ret;
270 }
271
272 int _mmcamcorder_resource_manager_init(MMCamcorderResourceManager *resource_manager, void *user_data)
273 {
274         MMCAMCORDER_CHECK_RESOURCE_MANAGER_INSTANCE(resource_manager);
275
276         resource_manager->mloop = mrp_mainloop_glib_get(g_main_loop_new(NULL, TRUE));
277         if (resource_manager->mloop) {
278                 resource_manager->context = mrp_res_create(resource_manager->mloop, mrp_state_callback, user_data);
279                 if (resource_manager->context == NULL) {
280                         _mmcam_dbg_err(" - could not get context for resource manager");
281                         mrp_mainloop_destroy(resource_manager->mloop);
282                         resource_manager->mloop = NULL;
283                         return MM_ERROR_RESOURCE_INTERNAL;
284                 }
285                 resource_manager->user_data = user_data;
286         } else {
287                 _mmcam_dbg_err("- could not get mainloop for resource manager");
288                 return MM_ERROR_RESOURCE_INTERNAL;
289         }
290
291         return MM_ERROR_NONE;
292 }
293
294 int _mmcamcorder_resource_manager_prepare(MMCamcorderResourceManager *resource_manager, MMCamcorderResourceType resource_type)
295 {
296         int ret = MM_ERROR_NONE;
297         MMCAMCORDER_CHECK_RESOURCE_MANAGER_INSTANCE(resource_manager);
298         MMCAMCORDER_CHECK_CONNECTION_RESOURCE_MANAGER(resource_manager);
299
300         if (!resource_manager->rset) {
301                 ret = create_rset(resource_manager);
302         }
303         if (ret == MM_ERROR_NONE) {
304                 switch (resource_type) {
305                 case RESOURCE_TYPE_VIDEO_OVERLAY:
306                         ret = include_resource(resource_manager, resource_str[MRP_RESOURCE_FOR_VIDEO_OVERLAY]);
307                         break;
308                 case RESOURCE_TYPE_CAMERA:
309                         ret = include_resource(resource_manager, resource_str[MRP_RESOURCE_FOR_CAMERA]);
310                         break;
311                 }
312         }
313
314         return ret;
315 }
316
317 int _mmcamcorder_resource_manager_acquire(MMCamcorderResourceManager *resource_manager)
318 {
319         int ret = MM_ERROR_NONE;
320         MMCAMCORDER_CHECK_RESOURCE_MANAGER_INSTANCE(resource_manager);
321         MMCAMCORDER_CHECK_CONNECTION_RESOURCE_MANAGER(resource_manager);
322
323         if (resource_manager->rset == NULL) {
324                 _mmcam_dbg_err("- could not acquire resource, resource set is null");
325                 ret = MM_ERROR_RESOURCE_INVALID_STATE;
326         } else {
327                 ret = set_resource_release_cb(resource_manager);
328                 if (ret) {
329                         _mmcam_dbg_err("- could not set resource release cb, ret(%d)", ret);
330                         ret = MM_ERROR_RESOURCE_INTERNAL;
331                 } else {
332                         ret = mrp_res_acquire_resource_set(resource_manager->rset);
333                         if (ret) {
334                                 _mmcam_dbg_err("- could not acquire resource, ret(%d)", ret);
335                                 ret = MM_ERROR_RESOURCE_INTERNAL;
336                         }
337                 }
338         }
339
340         return ret;
341 }
342
343 int _mmcamcorder_resource_manager_release(MMCamcorderResourceManager *resource_manager)
344 {
345         int ret = MM_ERROR_NONE;
346         MMCAMCORDER_CHECK_RESOURCE_MANAGER_INSTANCE(resource_manager);
347         MMCAMCORDER_CHECK_CONNECTION_RESOURCE_MANAGER(resource_manager);
348
349         if (resource_manager->rset == NULL) {
350                 _mmcam_dbg_err("- could not release resource, resource set is null");
351                 ret = MM_ERROR_RESOURCE_INVALID_STATE;
352         } else {
353                 if (resource_manager->rset->state != MRP_RES_RESOURCE_ACQUIRED) {
354                         _mmcam_dbg_err("- could not release resource, resource set state is [%s]", state_to_str(resource_manager->rset->state));
355                         ret = MM_ERROR_RESOURCE_INVALID_STATE;
356                 } else {
357                         ret = mrp_res_release_resource_set(resource_manager->rset);
358                         if (ret) {
359                                 _mmcam_dbg_err("- could not release resource, ret(%d)", ret);
360                                 ret = MM_ERROR_RESOURCE_INTERNAL;
361                         } else {
362                                 _mmcam_dbg_log("resource release done");
363                         }
364                 }
365         }
366
367         return ret;
368 }
369
370 int _mmcamcorder_resource_manager_unprepare(MMCamcorderResourceManager *resource_manager)
371 {
372         int ret = MM_ERROR_NONE;
373         MMCAMCORDER_CHECK_RESOURCE_MANAGER_INSTANCE(resource_manager);
374         MMCAMCORDER_CHECK_CONNECTION_RESOURCE_MANAGER(resource_manager);
375
376         if (resource_manager->rset == NULL) {
377                 _mmcam_dbg_err("- could not unprepare for resource_manager, _mmcamcorder_resource_manager_prepare() first");
378                 ret = MM_ERROR_RESOURCE_INVALID_STATE;
379         } else {
380                 mrp_res_delete_resource_set(resource_manager->rset);
381                 resource_manager->rset = NULL;
382                 _mmcam_dbg_log("delete resource set done");
383         }
384
385         return ret;
386 }
387
388 int _mmcamcorder_resource_manager_deinit(MMCamcorderResourceManager *resource_manager)
389 {
390         MMCAMCORDER_CHECK_RESOURCE_MANAGER_INSTANCE(resource_manager);
391         MMCAMCORDER_CHECK_CONNECTION_RESOURCE_MANAGER(resource_manager);
392
393         if (resource_manager->rset) {
394                 if (resource_manager->rset->state == MRP_RES_RESOURCE_ACQUIRED) {
395                         _mmcam_dbg_warn("resource is still acquired. release...");
396                         if (mrp_res_release_resource_set(resource_manager->rset))
397                                 _mmcam_dbg_err("- could not release resource");
398                 }
399                 _mmcam_dbg_log("delete resource set");
400                 mrp_res_delete_resource_set(resource_manager->rset);
401                 resource_manager->rset = NULL;
402         }
403         if (resource_manager->context) {
404                 _mmcam_dbg_log("destroy resource context");
405                 mrp_res_destroy(resource_manager->context);
406                 resource_manager->context = NULL;
407         }
408         if (resource_manager->mloop) {
409                 _mmcam_dbg_log("destroy resource mainloop");
410                 mrp_mainloop_destroy(resource_manager->mloop);
411                 resource_manager->mloop = NULL;
412         }
413
414         return MM_ERROR_NONE;
415 }