2044d8f162c20c0c91ee0b6d3783d9bf04ddc3c6
[platform/core/multimedia/libmm-camcorder.git] / src / mm_camcorder_client.c
1 /*
2  * libmm-camcorder
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Jeongmo Yang <jm80.yang@samsung.com>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21
22 /*===========================================================================================
23 |                                                                                                                                                                                       |
24 |  INCLUDE FILES                                                                                                                                                        |
25 |                                                                                                                                                                                       |
26 ========================================================================================== */
27 #include <gst/gst.h>
28 #include <gst/app/gstappsrc.h>
29 #include <gst/video/videooverlay.h>
30 #ifdef HAVE_WAYLAND
31 #include <gst/wayland/wayland.h>
32 #endif
33 #include <unistd.h>
34 #include <sys/stat.h>
35 #include <string.h>
36 #include <sys/time.h>
37 #include <stdlib.h>
38
39 #include <mm_error.h>
40 #include <mm_debug.h>
41
42 #include "mm_camcorder_client.h"
43 #include "mm_camcorder_internal.h"
44 #include <sched.h>
45
46 #include <storage.h>
47
48
49 static _MMCamcorderInfoConverting g_client_display_info[] = {
50         {
51                 CONFIGURE_TYPE_MAIN,
52                 CONFIGURE_CATEGORY_MAIN_VIDEO_OUTPUT,
53                 MM_CAM_CLIENT_DISPLAY_DEVICE,
54                 MM_CAMCORDER_ATTR_NONE,
55                 "DisplayDevice",
56                 MM_CAMCONVERT_TYPE_INT_ARRAY,
57                 NULL,
58         },
59         {
60                 CONFIGURE_TYPE_MAIN,
61                 CONFIGURE_CATEGORY_MAIN_VIDEO_OUTPUT,
62                 MM_CAM_CLIENT_DISPLAY_MODE,
63                 MM_CAMCORDER_ATTR_NONE,
64                 "DisplayMode",
65                 MM_CAMCONVERT_TYPE_INT_ARRAY,
66                 NULL,
67         },
68         {
69                 CONFIGURE_TYPE_MAIN,
70                 CONFIGURE_CATEGORY_MAIN_VIDEO_OUTPUT,
71                 MM_CAM_CLIENT_DISPLAY_SURFACE,
72                 MM_CAMCORDER_ATTR_NONE,
73                 "Videosink",
74                 MM_CAMCONVERT_TYPE_INT_ARRAY,
75                 NULL,
76         },
77 };
78
79
80 static int _storage_device_supported_cb(int storage_id, storage_type_e type, storage_state_e state, const char *path, void *user_data)
81 {
82         char **root_directory = (char **)user_data;
83
84         if (root_directory == NULL) {
85                 _mmcam_dbg_warn("user data is NULL");
86                 return FALSE;
87         }
88
89         _mmcam_dbg_log("storage id %d, type %d, state %d, path %s",
90                        storage_id, type, state, path ? path : "NULL");
91
92         if (type == STORAGE_TYPE_INTERNAL && path) {
93                 if (*root_directory) {
94                         free(*root_directory);
95                         *root_directory = NULL;
96                 }
97
98                 *root_directory = strdup(path);
99                 if (*root_directory) {
100                         _mmcam_dbg_log("get root directory %s", *root_directory);
101                         return FALSE;
102                 } else {
103                         _mmcam_dbg_warn("strdup %s failed");
104                 }
105         }
106
107         return TRUE;
108 }
109
110 bool _mmcamcorder_client_commit_display_handle(MMHandleType handle, int attr_idx, const mmf_value_t *value)
111 {
112         int current_state = MM_CAMCORDER_STATE_NONE;
113         const char *videosink_name = NULL;
114         void *p_handle = NULL;
115
116         mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
117         _MMCamcorderSubContext *sc = NULL;
118
119         mmf_return_val_if_fail(handle, FALSE);
120
121         /* check type */
122         if (hcamcorder->type == MM_CAMCORDER_MODE_AUDIO) {
123                 _mmcam_dbg_err("invalid mode %d", hcamcorder->type);
124                 return FALSE;
125         }
126
127         /* check current state */
128         current_state = _mmcamcorder_get_state(handle);
129         if (current_state < MM_CAMCORDER_STATE_READY) {
130                 _mmcam_dbg_log("NOT initialized. this will be applied later");
131                 return TRUE;
132         }
133
134         sc = MMF_CAMCORDER_SUBCONTEXT(handle);
135
136         p_handle = value->value.p_val;
137         if (p_handle) {
138                 /* get videosink name */
139                 _mmcamcorder_conf_get_value_element_name(sc->VideosinkElement, &videosink_name);
140                 if (videosink_name == NULL) {
141                         _mmcam_dbg_err("Please check videosink element in configuration file");
142                         return FALSE;
143                 }
144
145                 _mmcam_dbg_log("Commit : videosinkname[%s]", videosink_name);
146
147                 if (!strcmp(videosink_name, "xvimagesink") ||
148                     !strcmp(videosink_name, "ximagesink")) {
149                         _mmcam_dbg_log("Commit : Set XID[%x]", *(int*)(p_handle));
150                         gst_video_overlay_set_window_handle(GST_VIDEO_OVERLAY(sc->element[_MMCAMCORDER_CLIENT_VIDEOSINK_SINK].gst), *(int*)(p_handle));
151                 } else if (!strcmp(videosink_name, "evasimagesink") ||
152                            !strcmp(videosink_name, "evaspixmapsink")) {
153                         _mmcam_dbg_log("Commit : Set evas object [%p]", p_handle);
154                         MMCAMCORDER_G_OBJECT_SET_POINTER(sc->element[_MMCAMCORDER_CLIENT_VIDEOSINK_SINK].gst, "evas-object", p_handle);
155 #ifdef HAVE_WAYLAND
156                 } else if (!strcmp(videosink_name, "waylandsink")) {
157                         MMCamWaylandInfo *wl_info = (MMCamWaylandInfo *)p_handle;
158                         GstContext *context = NULL;
159
160                         context = gst_wayland_display_handle_context_new((struct wl_display *)wl_info->display);
161                         if (context) {
162                                 gst_element_set_context(sc->element[_MMCAMCORDER_CLIENT_VIDEOSINK_SINK].gst, context);
163                         } else {
164                                 _mmcam_dbg_warn("gst_wayland_display_handle_context_new failed");
165                         }
166
167                         gst_video_overlay_set_window_handle(GST_VIDEO_OVERLAY(sc->element[_MMCAMCORDER_CLIENT_VIDEOSINK_SINK].gst), (guintptr)wl_info->surface);
168                         gst_video_overlay_set_render_rectangle(GST_VIDEO_OVERLAY(sc->element[_MMCAMCORDER_CLIENT_VIDEOSINK_SINK].gst),
169                                                                wl_info->window_x,
170                                                                wl_info->window_y,
171                                                                wl_info->window_width,
172                                                                wl_info->window_height);
173 #endif /* HAVE_WAYLAND */
174                 } else {
175                         _mmcam_dbg_warn("Commit : Nothing to commit with this element[%s]", videosink_name);
176                         return FALSE;
177                 }
178         } else {
179                 _mmcam_dbg_warn("Display handle is NULL");
180                 return FALSE;
181         }
182
183         return TRUE;
184 }
185
186 bool _mmcamcorder_client_commit_display_rect(MMHandleType handle, int attr_idx, const mmf_value_t *value)
187 {
188         int current_state = MM_CAMCORDER_STATE_NONE;
189         int method = 0;
190         const char *videosink_name = NULL;
191
192         mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
193         _MMCamcorderSubContext *sc = NULL;
194
195         mmf_return_val_if_fail(handle, FALSE);
196
197         /* check type */
198         if (hcamcorder->type == MM_CAMCORDER_MODE_AUDIO) {
199                 _mmcam_dbg_err("invalid mode %d", hcamcorder->type);
200                 return FALSE;
201         }
202
203         /* check current state */
204         current_state = _mmcamcorder_get_state(handle);
205         if (current_state < MM_CAMCORDER_STATE_READY) {
206                 _mmcam_dbg_log("NOT initialized. this will be applied later");
207                 return TRUE;
208         }
209
210         sc = MMF_CAMCORDER_SUBCONTEXT(handle);
211
212         /* check current method */
213         mm_camcorder_get_attributes(handle, NULL,
214                                     MMCAM_DISPLAY_GEOMETRY_METHOD, &method,
215                                     NULL);
216         if (method != MM_DISPLAY_METHOD_CUSTOM_ROI) {
217                 _mmcam_dbg_log("current method[%d] is not supported rect", method);
218                 return FALSE;
219         }
220
221         /* Get videosink name */
222         _mmcamcorder_conf_get_value_element_name(sc->VideosinkElement, &videosink_name);
223         if (videosink_name == NULL) {
224                 _mmcam_dbg_err("Please check videosink element in configuration file");
225                 return FALSE;
226         }
227
228         if (!strcmp(videosink_name, "xvimagesink") ||
229             !strcmp(videosink_name, "evaspixmapsink")) {
230                 int rect_x = 0;
231                 int rect_y = 0;
232                 int rect_width = 0;
233                 int rect_height = 0;
234                 int flags = MM_ATTRS_FLAG_NONE;
235                 MMCamAttrsInfo info;
236
237                 mm_camcorder_get_attributes(handle, NULL,
238                                             MMCAM_DISPLAY_RECT_X, &rect_x,
239                                             MMCAM_DISPLAY_RECT_Y, &rect_y,
240                                             MMCAM_DISPLAY_RECT_WIDTH, &rect_width,
241                                             MMCAM_DISPLAY_RECT_HEIGHT, &rect_height,
242                                             NULL);
243                 switch (attr_idx) {
244                 case MM_CAM_CLIENT_DISPLAY_RECT_X:
245                         mm_camcorder_get_attribute_info(handle, MMCAM_DISPLAY_RECT_Y, &info);
246                         flags |= info.flag;
247                         memset(&info, 0x00, sizeof(info));
248                         mm_camcorder_get_attribute_info(handle, MMCAM_DISPLAY_RECT_WIDTH, &info);
249                         flags |= info.flag;
250                         memset(&info, 0x00, sizeof(info));
251                         mm_camcorder_get_attribute_info(handle, MMCAM_DISPLAY_RECT_HEIGHT, &info);
252                         flags |= info.flag;
253                         rect_x = value->value.i_val;
254                         break;
255                 case MM_CAM_CLIENT_DISPLAY_RECT_Y:
256                         mm_camcorder_get_attribute_info(handle, MMCAM_DISPLAY_RECT_WIDTH, &info);
257                         flags |= info.flag;
258                         memset(&info, 0x00, sizeof(info));
259                         mm_camcorder_get_attribute_info(handle, MMCAM_DISPLAY_RECT_HEIGHT, &info);
260                         flags |= info.flag;
261                         rect_y = value->value.i_val;
262                         break;
263                 case MM_CAM_CLIENT_DISPLAY_RECT_WIDTH:
264                         mm_camcorder_get_attribute_info(handle, MMCAM_DISPLAY_RECT_HEIGHT, &info);
265                         flags |= info.flag;
266                         rect_width = value->value.i_val;
267                         break;
268                 case MM_CAM_CLIENT_DISPLAY_RECT_HEIGHT:
269                         rect_height = value->value.i_val;
270                         break;
271                 default:
272                         _mmcam_dbg_err("Wrong attr_idx!");
273                         return FALSE;
274                 }
275
276                 if (!(flags & MM_ATTRS_FLAG_MODIFIED)) {
277                         _mmcam_dbg_log("RECT(x,y,w,h) = (%d,%d,%d,%d)",
278                                        rect_x, rect_y, rect_width, rect_height);
279                         g_object_set(sc->element[_MMCAMCORDER_CLIENT_VIDEOSINK_SINK].gst,
280                                      "dst-roi-x", rect_x,
281                                      "dst-roi-y", rect_y,
282                                      "dst-roi-w", rect_width,
283                                      "dst-roi-h", rect_height,
284                                      NULL);
285                 }
286
287                 return TRUE;
288         } else {
289                 _mmcam_dbg_warn("videosink[%s] does not support display rect.", videosink_name);
290                 return FALSE;
291         }
292 }
293
294 bool _mmcamcorder_client_commit_display_rotation(MMHandleType handle, int attr_idx, const mmf_value_t *value)
295 {
296         int current_state = MM_CAMCORDER_STATE_NONE;
297
298         mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
299
300         mmf_return_val_if_fail(handle, FALSE);
301
302         /* check type */
303         if (hcamcorder->type == MM_CAMCORDER_MODE_AUDIO) {
304                 _mmcam_dbg_err("invalid mode %d", hcamcorder->type);
305                 return FALSE;
306         }
307
308         /* check current state */
309         current_state = _mmcamcorder_get_state(handle);
310         if (current_state < MM_CAMCORDER_STATE_READY) {
311                 _mmcam_dbg_log("NOT initialized. this will be applied later [rotate:%d]", value->value.i_val);
312                 return TRUE;
313         }
314
315         return _mmcamcorder_set_display_rotation(handle, value->value.i_val, _MMCAMCORDER_CLIENT_VIDEOSINK_SINK);
316 }
317
318 bool _mmcamcorder_client_commit_display_visible(MMHandleType handle, int attr_idx, const mmf_value_t *value)
319 {
320         int current_state = MM_CAMCORDER_STATE_NONE;
321         const char *videosink_name = NULL;
322
323         mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
324         _MMCamcorderSubContext *sc = NULL;
325
326         mmf_return_val_if_fail(handle, FALSE);
327
328         /* check type */
329         if (hcamcorder->type == MM_CAMCORDER_MODE_AUDIO) {
330                 _mmcam_dbg_err("invalid mode %d", hcamcorder->type);
331                 return FALSE;
332         }
333
334         /* check current state */
335         current_state = _mmcamcorder_get_state(handle);
336         if (current_state < MM_CAMCORDER_STATE_READY) {
337                 _mmcam_dbg_log("NOT initialized. this will be applied later");
338                 return TRUE;
339         }
340
341         sc = MMF_CAMCORDER_SUBCONTEXT(handle);
342
343         /* Get videosink name */
344         _mmcamcorder_conf_get_value_element_name(sc->VideosinkElement, &videosink_name);
345         if (videosink_name == NULL) {
346                 _mmcam_dbg_err("Please check videosink element in configuration file");
347                 return FALSE;
348         }
349
350         if (!strcmp(videosink_name, "waylandsink") || !strcmp(videosink_name, "xvimagesink") ||
351                 !strcmp(videosink_name, "evasimagesink") || !strcmp(videosink_name, "evaspixmapsink")) {
352                 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_CLIENT_VIDEOSINK_SINK].gst, "visible", value->value.i_val);
353                 _mmcam_dbg_log("Set visible [%d] done.", value->value.i_val);
354                 return TRUE;
355         } else {
356                 _mmcam_dbg_warn("videosink[%s] does not support VISIBLE.", videosink_name);
357                 return FALSE;
358         }
359 }
360
361 bool _mmcamcorder_client_commit_display_geometry_method (MMHandleType handle, int attr_idx, const mmf_value_t *value)
362 {
363         int method = 0;
364         int current_state = MM_CAMCORDER_STATE_NONE;
365         const char *videosink_name = NULL;
366
367         mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
368         _MMCamcorderSubContext *sc = NULL;
369
370         mmf_return_val_if_fail(handle, FALSE);
371
372         /* check type */
373         if (hcamcorder->type == MM_CAMCORDER_MODE_AUDIO) {
374                 _mmcam_dbg_err("invalid mode %d", hcamcorder->type);
375                 return FALSE;
376         }
377
378         /* check current state */
379         current_state = _mmcamcorder_get_state(handle);
380         if (current_state < MM_CAMCORDER_STATE_READY) {
381                 _mmcam_dbg_log("NOT initialized. this will be applied later");
382                 return TRUE;
383         }
384
385         sc = MMF_CAMCORDER_SUBCONTEXT(handle);
386
387         /* Get videosink name */
388         _mmcamcorder_conf_get_value_element_name(sc->VideosinkElement, &videosink_name);
389         if (videosink_name == NULL) {
390                 _mmcam_dbg_err("Please check videosink element in configuration file");
391                 return FALSE;
392         }
393
394         if (!strcmp(videosink_name, "waylandsink") || !strcmp(videosink_name, "xvimagesink") ||
395                 !strcmp(videosink_name, "evasimagesink") || !strcmp(videosink_name, "evaspixmapsink")) {
396                 method = value->value.i_val;
397                 MMCAMCORDER_G_OBJECT_SET( sc->element[_MMCAMCORDER_CLIENT_VIDEOSINK_SINK].gst, "display-geometry-method", method);
398                 return TRUE;
399         } else {
400                 _mmcam_dbg_warn("videosink[%s] does not support geometry method.", videosink_name);
401                 return FALSE;
402         }
403 }
404
405 bool _mmcamcorder_client_commit_display_scale(MMHandleType handle, int attr_idx, const mmf_value_t *value)
406 {
407         int zoom = 0;
408         int current_state = MM_CAMCORDER_STATE_NONE;
409         const char *videosink_name = NULL;
410         GstElement *vs_element = NULL;
411
412         mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
413         _MMCamcorderSubContext *sc = NULL;
414
415         mmf_return_val_if_fail(handle, FALSE);
416
417         /* check type */
418         if (hcamcorder->type == MM_CAMCORDER_MODE_AUDIO) {
419                 _mmcam_dbg_err("invalid mode %d", hcamcorder->type);
420                 return FALSE;
421         }
422
423         /* check current state */
424         current_state = _mmcamcorder_get_state(handle);
425         if (current_state < MM_CAMCORDER_STATE_READY) {
426                 _mmcam_dbg_log("NOT initialized. this will be applied later");
427                 return TRUE;
428         }
429
430         sc = MMF_CAMCORDER_SUBCONTEXT(handle);
431
432         /* Get videosink name */
433         _mmcamcorder_conf_get_value_element_name(sc->VideosinkElement, &videosink_name);
434         if (videosink_name == NULL) {
435                 _mmcam_dbg_err("Please check videosink element in configuration file");
436                 return FALSE;
437         }
438
439         zoom = value->value.i_val;
440         if (!strcmp(videosink_name, "waylandsink") || !strcmp(videosink_name, "xvimagesink")) {
441                 vs_element = sc->element[_MMCAMCORDER_CLIENT_VIDEOSINK_SINK].gst;
442
443                 MMCAMCORDER_G_OBJECT_SET(vs_element, "zoom", (float)(zoom + 1));
444                 _mmcam_dbg_log("Set display zoom to %d", zoom + 1);
445
446                 return TRUE;
447         } else {
448                 _mmcam_dbg_warn("videosink[%s] does not support scale", videosink_name);
449                 return FALSE;
450         }
451 }
452
453 bool _mmcamcorder_client_commit_display_mode(MMHandleType handle, int attr_idx, const mmf_value_t *value)
454 {
455         int current_state = MM_CAMCORDER_STATE_NONE;
456         const char *videosink_name = NULL;
457
458         mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
459         _MMCamcorderSubContext *sc = NULL;
460
461         mmf_return_val_if_fail(handle, FALSE);
462
463         /* check type */
464         if (hcamcorder->type == MM_CAMCORDER_MODE_AUDIO) {
465                 _mmcam_dbg_err("invalid mode %d", hcamcorder->type);
466                 return FALSE;
467         }
468
469         /* check current state */
470         current_state = _mmcamcorder_get_state(handle);
471         if (current_state < MM_CAMCORDER_STATE_READY) {
472                 _mmcam_dbg_log("NOT initialized. this will be applied later");
473                 return TRUE;
474         }
475
476         sc = MMF_CAMCORDER_SUBCONTEXT(handle);
477
478         _mmcamcorder_conf_get_value_element_name(sc->VideosinkElement, &videosink_name);
479         if (videosink_name == NULL) {
480                 _mmcam_dbg_err("Please check videosink element in configuration file");
481                 return FALSE;
482         }
483
484         _mmcam_dbg_log("Commit : videosinkname[%s]", videosink_name);
485
486         if (!strcmp(videosink_name, "waylandsink") || !strcmp(videosink_name, "xvimagesink")) {
487                 _mmcam_dbg_log("Commit : display mode [%d]", value->value.i_val);
488                 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_CLIENT_VIDEOSINK_SINK].gst, "display-mode", value->value.i_val);
489                 return TRUE;
490         } else {
491                 _mmcam_dbg_warn("Commit : This element [%s] does not support display mode", videosink_name);
492                 return FALSE;
493         }
494 }
495
496 bool _mmcamcorder_client_commit_display_evas_do_scaling(MMHandleType handle, int attr_idx, const mmf_value_t *value)
497 {
498         int current_state = MM_CAMCORDER_STATE_NONE;
499         int do_scaling = 0;
500         const char *videosink_name = NULL;
501
502         mmf_camcorder_t *hcamcorder= MMF_CAMCORDER( handle);
503         _MMCamcorderSubContext *sc = NULL;
504
505         mmf_return_val_if_fail(handle, FALSE);
506
507         /* check type */
508         if (hcamcorder->type == MM_CAMCORDER_MODE_AUDIO) {
509                 _mmcam_dbg_err("invalid mode %d", hcamcorder->type);
510                 return FALSE;
511         }
512
513         /* check current state */
514         current_state = _mmcamcorder_get_state(handle);
515         if (current_state < MM_CAMCORDER_STATE_READY) {
516                 _mmcam_dbg_log("NOT initialized. this will be applied later");
517                 return TRUE;
518         }
519
520         sc = MMF_CAMCORDER_SUBCONTEXT(handle);
521
522         do_scaling = value->value.i_val;
523
524         /* Get videosink name */
525         _mmcamcorder_conf_get_value_element_name(sc->VideosinkElement, &videosink_name);
526         if (videosink_name == NULL) {
527                 _mmcam_dbg_err("Please check videosink element in configuration file");
528                 return FALSE;
529         }
530
531         if (!strcmp(videosink_name, "evaspixmapsink")) {
532                 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_CLIENT_VIDEOSINK_SINK].gst, "origin-size", !do_scaling);
533                 _mmcam_dbg_log("Set origin-size to %d", !(value->value.i_val));
534                 return TRUE;
535         } else {
536                 _mmcam_dbg_warn("videosink[%s] does not support scale", videosink_name);
537                 return FALSE;
538         }
539 }
540
541 bool _mmcamcorder_client_commit_display_flip(MMHandleType handle, int attr_idx, const mmf_value_t *value)
542 {
543         int current_state = MM_CAMCORDER_STATE_NONE;
544
545         mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
546
547         mmf_return_val_if_fail(handle, FALSE);
548
549         /* check type */
550         if (hcamcorder->type == MM_CAMCORDER_MODE_AUDIO) {
551                 _mmcam_dbg_err("invalid mode %d", hcamcorder->type);
552                 return FALSE;
553         }
554
555         /* check current state */
556         current_state = _mmcamcorder_get_state(handle);
557         if (current_state < MM_CAMCORDER_STATE_READY) {
558                 _mmcam_dbg_log("NOT initialized. this will be applied later [flip:%d]", value->value.i_val);
559                 return TRUE;
560         }
561
562         return _mmcamcorder_set_display_flip(handle, value->value.i_val, _MMCAMCORDER_CLIENT_VIDEOSINK_SINK);
563 }
564
565 int _mmcamcorder_client_videosink_window_set(MMHandleType handle, type_element* VideosinkElement)
566 {
567         int err = MM_ERROR_NONE;
568         int size = 0;
569         int retx = 0;
570         int rety = 0;
571         int retwidth = 0;
572         int retheight = 0;
573         int visible = 0;
574         int rotation = MM_DISPLAY_ROTATION_NONE;
575         int flip = MM_FLIP_NONE;
576         int display_mode = MM_DISPLAY_MODE_DEFAULT;
577         int display_geometry_method = MM_DISPLAY_METHOD_LETTER_BOX;
578         int origin_size = 0;
579         int zoom_attr = 0;
580         int zoom_level = 0;
581         int do_scaling = FALSE;
582         int *overlay = NULL;
583         gulong xid;
584         char *err_name = NULL;
585         const char *videosink_name = NULL;
586
587         GstElement *vsink = NULL;
588
589         mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
590         _MMCamcorderSubContext *sc = NULL;
591
592         mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
593         mmf_return_val_if_fail(VideosinkElement, MM_ERROR_CAMCORDER_INVALID_ARGUMENT);
594
595         _mmcam_dbg_log("");
596
597         sc = MMF_CAMCORDER_SUBCONTEXT(handle);
598         mmf_return_val_if_fail(sc, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
599         mmf_return_val_if_fail(sc->element, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
600         mmf_return_val_if_fail(sc->element[_MMCAMCORDER_CLIENT_VIDEOSINK_SINK].gst, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
601
602         vsink = sc->element[_MMCAMCORDER_CLIENT_VIDEOSINK_SINK].gst;
603
604         /* Get video display information */
605         err = mm_camcorder_get_attributes(handle, &err_name,
606                                           MMCAM_DISPLAY_RECT_X, &retx,
607                                           MMCAM_DISPLAY_RECT_Y, &rety,
608                                           MMCAM_DISPLAY_RECT_WIDTH, &retwidth,
609                                           MMCAM_DISPLAY_RECT_HEIGHT, &retheight,
610                                           MMCAM_DISPLAY_ROTATION, &rotation,
611                                           MMCAM_DISPLAY_FLIP, &flip,
612                                           MMCAM_DISPLAY_VISIBLE, &visible,
613                                           MMCAM_DISPLAY_HANDLE, (void**)&overlay, &size,
614                                           MMCAM_DISPLAY_MODE, &display_mode,
615                                           MMCAM_DISPLAY_GEOMETRY_METHOD, &display_geometry_method,
616                                           MMCAM_DISPLAY_SCALE, &zoom_attr,
617                                           MMCAM_DISPLAY_EVAS_DO_SCALING, &do_scaling,
618                                           NULL);
619         if (err != MM_ERROR_NONE) {
620                 if (err_name) {
621                         _mmcam_dbg_err("failed to get attributes [%s][0x%x]", err_name, err);
622                         free(err_name);
623                         err_name = NULL;
624                 } else {
625                         _mmcam_dbg_err("failed to get attributes [0x%x]", err);
626                 }
627
628                 return err;
629         }
630
631         _mmcam_dbg_log("(overlay=%p, size=%d)", overlay, size);
632
633         _mmcamcorder_conf_get_value_element_name(sc->VideosinkElement, &videosink_name);
634
635         if (videosink_name == NULL) {
636                 _mmcam_dbg_err("videosink_name is empty");
637                 return MM_ERROR_CAMCORDER_INVALID_CONDITION;
638         }
639
640
641         /* Set display handle */
642         if (!strcmp(videosink_name, "xvimagesink") ||
643             !strcmp(videosink_name, "ximagesink")) {
644                 if (overlay) {
645                         xid = *overlay;
646                         _mmcam_dbg_log("xid = %lu )", xid);
647                         gst_video_overlay_set_window_handle(GST_VIDEO_OVERLAY(vsink), xid);
648                 } else {
649                         _mmcam_dbg_warn("Handle is NULL. Set xid as 0.. but, it's not recommended.");
650                         gst_video_overlay_set_window_handle(GST_VIDEO_OVERLAY(vsink), 0);
651                 }
652         } else if (!strcmp(videosink_name, "evasimagesink") ||
653                    !strcmp(videosink_name, "evaspixmapsink")) {
654                 _mmcam_dbg_log("videosink : %s, handle : %p", videosink_name, overlay);
655                 if (overlay) {
656                         MMCAMCORDER_G_OBJECT_SET_POINTER(vsink, "evas-object", overlay);
657                         MMCAMCORDER_G_OBJECT_SET(vsink, "origin-size", !do_scaling);
658                 } else {
659                         _mmcam_dbg_err("display handle(eavs object) is NULL");
660                         return MM_ERROR_CAMCORDER_INVALID_ARGUMENT;
661                 }
662 #ifdef HAVE_WAYLAND
663         } else if (!strcmp(videosink_name, "waylandsink")) {
664                 MMCamWaylandInfo *wl_info = (MMCamWaylandInfo *)overlay;
665                 if (wl_info) {
666                         GstContext *context = NULL;
667
668                         context = gst_wayland_display_handle_context_new((struct wl_display *)wl_info->display);
669                         if (context) {
670                                 gst_element_set_context(vsink, context);
671                         } else {
672                                 _mmcam_dbg_warn("gst_wayland_display_handle_context_new failed");
673                         }
674
675                         gst_video_overlay_set_window_handle(GST_VIDEO_OVERLAY(vsink), (guintptr)wl_info->surface);
676                         gst_video_overlay_set_render_rectangle(GST_VIDEO_OVERLAY(vsink),
677                                                                wl_info->window_x,
678                                                                wl_info->window_y,
679                                                                wl_info->window_width,
680                                                                wl_info->window_height);
681                 } else {
682                         _mmcam_dbg_warn("Handle is NULL. skip setting.");
683                 }
684 #endif /* HAVE_WAYLAND */
685         } else {
686                 _mmcam_dbg_warn("Who are you?? (Videosink: %s)", videosink_name);
687         }
688
689         _mmcam_dbg_log("%s set: display_geometry_method[%d],origin-size[%d],visible[%d],rotate[%d],flip[%d]",
690                        videosink_name, display_geometry_method, origin_size, visible, rotation, flip);
691
692         /* Set attribute */
693         if (!strcmp(videosink_name, "waylandsink") || !strcmp(videosink_name, "xvimagesink") ||
694                 !strcmp(videosink_name, "evaspixmapsink")) {
695                 /* set rotation */
696                 MMCAMCORDER_G_OBJECT_SET(vsink, "rotate", rotation);
697
698                 /* set flip */
699                 MMCAMCORDER_G_OBJECT_SET(vsink, "flip", flip);
700
701                 switch (zoom_attr) {
702                 case MM_DISPLAY_SCALE_DEFAULT:
703                         zoom_level = 1;
704                         break;
705                 case MM_DISPLAY_SCALE_DOUBLE_LENGTH:
706                         zoom_level = 2;
707                         break;
708                 case MM_DISPLAY_SCALE_TRIPLE_LENGTH:
709                         zoom_level = 3;
710                         break;
711                 default:
712                         _mmcam_dbg_warn("Unsupported zoom value. set as default.");
713                         zoom_level = 1;
714                         break;
715                 }
716
717                 MMCAMCORDER_G_OBJECT_SET(vsink, "display-geometry-method", display_geometry_method);
718                 MMCAMCORDER_G_OBJECT_SET(vsink, "display-mode", display_mode);
719                 MMCAMCORDER_G_OBJECT_SET(vsink, "visible", visible);
720                 MMCAMCORDER_G_OBJECT_SET(vsink, "zoom", zoom_level);
721
722                 if (display_geometry_method == MM_DISPLAY_METHOD_CUSTOM_ROI) {
723                         g_object_set(vsink,
724                                      "dst-roi-x", retx,
725                                      "dst-roi-y", rety,
726                                      "dst-roi-w", retwidth,
727                                      "dst-roi-h", retheight,
728                                      NULL);
729                 }
730         } else {
731                 _mmcam_dbg_warn("unsupported videosink [%s]", videosink_name);
732         }
733
734         return MM_ERROR_NONE;
735 }
736
737 int _mmcamcorder_client_init_attr_from_configure(MMHandleType handle)
738 {
739         mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
740         _MMCamcorderInfoConverting *info = NULL;
741
742         int table_size = 0;
743         int ret = MM_ERROR_NONE;
744
745         mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
746
747         /* Initialize attribute related to display */
748         info = g_client_display_info;
749         table_size = sizeof(g_client_display_info) / sizeof(_MMCamcorderInfoConverting);
750         ret = __mmcamcorder_set_info_to_attr(handle, info, table_size);
751         if (ret != MM_ERROR_NONE) {
752                 _mmcam_dbg_err("display info set error : 0x%x", ret);
753                 return ret;
754         }
755
756         _mmcam_dbg_log("done");
757
758         return ret;
759 }
760
761 MMHandleType _mmcamcorder_client_alloc_attribute(MMHandleType handle)
762 {
763         _mmcam_dbg_log( "" );
764
765         mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
766         MMHandleType attrs = 0;
767         mmf_attrs_construct_info_t *attrs_const_info = NULL;
768         unsigned int attr_count = 0;
769         unsigned int idx;
770         static int visible_values[] = { 0, 1 }; /*0: off, 1:on*/
771
772         mmf_return_val_if_fail(hcamcorder, NULL);
773
774         /* Create attribute constructor */
775         _mmcam_dbg_log("start");
776
777         /* alloc 'mmf_attrs_construct_info_t' */
778         attr_count = MM_CAM_CLIENT_ATTRIBUTE_NUM;
779         attrs_const_info = malloc(attr_count * sizeof(mmf_attrs_construct_info_t));
780         if (!attrs_const_info) {
781                 _mmcam_dbg_err("Fail to alloc constructor.");
782                 return 0;
783         }
784
785         /* alloc default attribute info */
786         hcamcorder->cam_attrs_const_info = (mm_cam_attr_construct_info *)malloc(sizeof(mm_cam_attr_construct_info) * attr_count);
787         if (hcamcorder->cam_attrs_const_info == NULL) {
788                 _mmcam_dbg_err("failed to alloc default attribute info");
789                 free(attrs_const_info);
790                 attrs_const_info = NULL;
791                 return 0;
792         }
793
794         /* basic attributes' info */
795         mm_cam_attr_construct_info temp_info[] = {
796                 {
797                         MM_CAM_CLIENT_DISPLAY_SOCKET_PATH,
798                         MMCAM_DISPLAY_SOCKET_PATH,
799                         MMF_VALUE_TYPE_STRING,
800                         MM_ATTRS_FLAG_RW,
801                         {(void*)NULL},
802                         MM_ATTRS_VALID_TYPE_NONE,
803                         {0},
804                         {0},
805                         NULL,
806                 },
807                 {
808                         MM_CAM_CLIENT_DISPLAY_HANDLE,
809                         "display-handle",
810                         MMF_VALUE_TYPE_DATA,
811                         MM_ATTRS_FLAG_RW,
812                         {(void*)NULL},
813                         MM_ATTRS_VALID_TYPE_NONE,
814                         {0},
815                         {0},
816                         _mmcamcorder_client_commit_display_handle,
817                 },
818                 {
819                         MM_CAM_CLIENT_DISPLAY_DEVICE,
820                         "display-device",
821                         MMF_VALUE_TYPE_INT,
822                         MM_ATTRS_FLAG_RW,
823                         {(void*)MM_DISPLAY_DEVICE_MAINLCD},
824                         MM_ATTRS_VALID_TYPE_INT_ARRAY,
825                         {0},
826                         {0},
827                         NULL,
828                 },
829                 // 50
830                 {
831                         MM_CAM_CLIENT_DISPLAY_SURFACE,
832                         "display-surface",
833                         MMF_VALUE_TYPE_INT,
834                         MM_ATTRS_FLAG_RW,
835                         {(void*)MM_DISPLAY_SURFACE_X},
836                         MM_ATTRS_VALID_TYPE_INT_ARRAY,
837                         {0},
838                         {0},
839                         NULL,
840                 },
841                 {
842                         MM_CAM_CLIENT_DISPLAY_RECT_X,
843                         "display-rect-x",
844                         MMF_VALUE_TYPE_INT,
845                         MM_ATTRS_FLAG_RW,
846                         {(void*)0},
847                         MM_ATTRS_VALID_TYPE_INT_RANGE,
848                         {.int_min = 0},
849                         {.int_max = _MMCAMCORDER_MAX_INT},
850                         _mmcamcorder_client_commit_display_rect,
851                 },
852                 {
853                         MM_CAM_CLIENT_DISPLAY_RECT_Y,
854                         "display-rect-y",
855                         MMF_VALUE_TYPE_INT,
856                         MM_ATTRS_FLAG_RW,
857                         {(void*)0},
858                         MM_ATTRS_VALID_TYPE_INT_RANGE,
859                         {.int_min = 0},
860                         {.int_max = _MMCAMCORDER_MAX_INT},
861                         _mmcamcorder_client_commit_display_rect,
862                 },
863                 {
864                         MM_CAM_CLIENT_DISPLAY_RECT_WIDTH,
865                         "display-rect-width",
866                         MMF_VALUE_TYPE_INT,
867                         MM_ATTRS_FLAG_RW,
868                         {(void*)0},
869                         MM_ATTRS_VALID_TYPE_INT_RANGE,
870                         {.int_min = 0},
871                         {.int_max = _MMCAMCORDER_MAX_INT},
872                         _mmcamcorder_client_commit_display_rect,
873                 },
874                 {
875                         MM_CAM_CLIENT_DISPLAY_RECT_HEIGHT,
876                         "display-rect-height",
877                         MMF_VALUE_TYPE_INT,
878                         MM_ATTRS_FLAG_RW,
879                         {(void*)0},
880                         MM_ATTRS_VALID_TYPE_INT_RANGE,
881                         {.int_min = 0},
882                         {.int_max = _MMCAMCORDER_MAX_INT},
883                         _mmcamcorder_client_commit_display_rect,
884                 },
885                 {
886                         MM_CAM_CLIENT_DISPLAY_SOURCE_X,
887                         "display-src-x",
888                         MMF_VALUE_TYPE_INT,
889                         MM_ATTRS_FLAG_RW,
890                         {(void*)0},
891                         MM_ATTRS_VALID_TYPE_INT_RANGE,
892                         {.int_min = 0},
893                         {.int_max = _MMCAMCORDER_MAX_INT},
894                         NULL,
895                 },
896                 {
897                         MM_CAM_CLIENT_DISPLAY_SOURCE_Y,
898                         "display-src-y",
899                         MMF_VALUE_TYPE_INT,
900                         MM_ATTRS_FLAG_RW,
901                         {(void*)0},
902                         MM_ATTRS_VALID_TYPE_INT_RANGE,
903                         {.int_min = 0},
904                         {.int_max = _MMCAMCORDER_MAX_INT},
905                         NULL,
906                 },
907                 {
908                         MM_CAM_CLIENT_DISPLAY_SOURCE_WIDTH,
909                         "display-src-width",
910                         MMF_VALUE_TYPE_INT,
911                         MM_ATTRS_FLAG_RW,
912                         {(void*)0},
913                         MM_ATTRS_VALID_TYPE_INT_RANGE,
914                         {.int_min = 0},
915                         {.int_max = _MMCAMCORDER_MAX_INT},
916                         NULL,
917                 },
918                 {
919                         MM_CAM_CLIENT_DISPLAY_SOURCE_HEIGHT,
920                         "display-src-height",
921                         MMF_VALUE_TYPE_INT,
922                         MM_ATTRS_FLAG_RW,
923                         {(void*)0},
924                         MM_ATTRS_VALID_TYPE_INT_RANGE,
925                         {.int_min = 0},
926                         {.int_max = _MMCAMCORDER_MAX_INT},
927                         NULL,
928                 },
929                 {
930                         MM_CAM_CLIENT_DISPLAY_ROTATION,
931                         "display-rotation",
932                         MMF_VALUE_TYPE_INT,
933                         MM_ATTRS_FLAG_RW,
934                         {(void*)MM_DISPLAY_ROTATION_NONE},
935                         MM_ATTRS_VALID_TYPE_INT_RANGE,
936                         {.int_min = MM_DISPLAY_ROTATION_NONE},
937                         {.int_max = MM_DISPLAY_ROTATION_270},
938                         _mmcamcorder_client_commit_display_rotation,
939                 },
940                 { // 60
941                         MM_CAM_CLIENT_DISPLAY_VISIBLE,
942                         "display-visible",
943                         MMF_VALUE_TYPE_INT,
944                         MM_ATTRS_FLAG_RW,
945                         {(void*)1},
946                         MM_ATTRS_VALID_TYPE_INT_ARRAY,
947                         {visible_values},
948                         {ARRAY_SIZE(visible_values)},
949                         _mmcamcorder_client_commit_display_visible,
950                 },
951                 {
952                         MM_CAM_CLIENT_DISPLAY_SCALE,
953                         "display-scale",
954                         MMF_VALUE_TYPE_INT,
955                         MM_ATTRS_FLAG_RW,
956                         {(void*)0},
957                         MM_ATTRS_VALID_TYPE_INT_RANGE,
958                         {.int_min = MM_DISPLAY_SCALE_DEFAULT},
959                         {.int_max = MM_DISPLAY_SCALE_TRIPLE_LENGTH},
960                         _mmcamcorder_client_commit_display_scale,
961                 },
962                 {
963                         MM_CAM_CLIENT_DISPLAY_GEOMETRY_METHOD,
964                         "display-geometry-method",
965                         MMF_VALUE_TYPE_INT,
966                         MM_ATTRS_FLAG_RW,
967                         {(void*)0},
968                         MM_ATTRS_VALID_TYPE_INT_RANGE,
969                         {.int_min = MM_DISPLAY_METHOD_LETTER_BOX},
970                         {.int_max = MM_DISPLAY_METHOD_CUSTOM_ROI},
971                         _mmcamcorder_client_commit_display_geometry_method,
972                 },
973                 {
974                         MM_CAM_CLIENT_DISPLAY_MODE,
975                         "display-mode",
976                         MMF_VALUE_TYPE_INT,
977                         MM_ATTRS_FLAG_RW,
978                         {(void*)MM_DISPLAY_MODE_DEFAULT},
979                         MM_ATTRS_VALID_TYPE_INT_ARRAY,
980                         {0},
981                         {0},
982                         _mmcamcorder_client_commit_display_mode,
983                 },
984                 {
985                         MM_CAM_CLIENT_DISPLAY_EVAS_SURFACE_SINK,
986                         "display-evas-surface-sink",
987                         MMF_VALUE_TYPE_STRING,
988                         MM_ATTRS_FLAG_READABLE,
989                         {(void*)NULL},
990                         MM_ATTRS_VALID_TYPE_NONE,
991                         {0},
992                         {0},
993                         NULL,
994                 },
995                 {
996                         MM_CAM_CLIENT_DISPLAY_EVAS_DO_SCALING,
997                         "display-evas-do-scaling",
998                         MMF_VALUE_TYPE_INT,
999                         MM_ATTRS_FLAG_RW,
1000                         {(void*)TRUE},
1001                         MM_ATTRS_VALID_TYPE_INT_RANGE,
1002                         {.int_min = FALSE},
1003                         {.int_max = TRUE},
1004                         _mmcamcorder_client_commit_display_evas_do_scaling,
1005                 },
1006                 {
1007                         MM_CAM_CLIENT_DISPLAY_FLIP,
1008                         "display-flip",
1009                         MMF_VALUE_TYPE_INT,
1010                         MM_ATTRS_FLAG_RW,
1011                         {(void*)MM_FLIP_NONE},
1012                         MM_ATTRS_VALID_TYPE_INT_RANGE,
1013                         {.int_min = MM_FLIP_NONE},
1014                         {.int_max = MM_FLIP_BOTH},
1015                         _mmcamcorder_client_commit_display_flip,
1016                 },
1017         };
1018
1019         memcpy(hcamcorder->cam_attrs_const_info, temp_info, sizeof(mm_cam_attr_construct_info) * attr_count);
1020
1021         for (idx = 0 ; idx < attr_count ; idx++) {
1022                 /* attribute order check. This should be same. */
1023                 if (idx != hcamcorder->cam_attrs_const_info[idx].attrid) {
1024                         _mmcam_dbg_err("Please check attributes order. Is the idx same with enum val?");
1025                         free(attrs_const_info);
1026                         attrs_const_info = NULL;
1027                         free(hcamcorder->cam_attrs_const_info);
1028                         hcamcorder->cam_attrs_const_info = NULL;
1029                         return 0;
1030                 }
1031
1032                 attrs_const_info[idx].name = hcamcorder->cam_attrs_const_info[idx].name;
1033                 attrs_const_info[idx].value_type = hcamcorder->cam_attrs_const_info[idx].value_type;
1034                 attrs_const_info[idx].flags = hcamcorder->cam_attrs_const_info[idx].flags;
1035                 attrs_const_info[idx].default_value = hcamcorder->cam_attrs_const_info[idx].default_value.value_void;
1036         }
1037
1038         /* Camcorder Attributes */
1039         _mmcam_dbg_log("Create Camcorder Attributes[%p, %d]", attrs_const_info, attr_count);
1040
1041         attrs = mmf_attrs_new_from_data("Camcorder_Mused_Attributes",
1042                                         attrs_const_info,
1043                                         attr_count,
1044                                         _mmcamcorder_commit_camcorder_attrs,
1045                                         (void *)handle);
1046
1047         free(attrs_const_info);
1048         attrs_const_info = NULL;
1049
1050         if (attrs == 0) {
1051                 _mmcam_dbg_err("Fail to alloc attribute handle");
1052                 free(hcamcorder->cam_attrs_const_info);
1053                 hcamcorder->cam_attrs_const_info = NULL;
1054                 return 0;
1055         }
1056
1057         for (idx = 0; idx < attr_count; idx++)
1058         {
1059                 _mmcam_dbg_log("Valid type [%s]", hcamcorder->cam_attrs_const_info[idx].name);
1060
1061                 mmf_attrs_set_valid_type (attrs, idx, hcamcorder->cam_attrs_const_info[idx].validity_type);
1062
1063                 switch (hcamcorder->cam_attrs_const_info[idx].validity_type)
1064                 {
1065                         case MM_ATTRS_VALID_TYPE_INT_ARRAY:
1066                                 if (hcamcorder->cam_attrs_const_info[idx].validity_value_1.int_array &&
1067                                     hcamcorder->cam_attrs_const_info[idx].validity_value_2.count > 0) {
1068                                         mmf_attrs_set_valid_array(attrs, idx,
1069                                                                   (const int *)(hcamcorder->cam_attrs_const_info[idx].validity_value_1.int_array),
1070                                                                   hcamcorder->cam_attrs_const_info[idx].validity_value_2.count,
1071                                                                   hcamcorder->cam_attrs_const_info[idx].default_value.value_int);
1072                                 }
1073                         break;
1074                         case MM_ATTRS_VALID_TYPE_INT_RANGE:
1075                                 _mmcam_dbg_err("MM_ATTRS_VALID_TYPE_INT_RANGE");
1076                                 mmf_attrs_set_valid_range(attrs, idx,
1077                                                           hcamcorder->cam_attrs_const_info[idx].validity_value_1.int_min,
1078                                                           hcamcorder->cam_attrs_const_info[idx].validity_value_2.int_max,
1079                                                           hcamcorder->cam_attrs_const_info[idx].default_value.value_int);
1080                         break;
1081                         case MM_ATTRS_VALID_TYPE_DOUBLE_ARRAY:
1082                                 if (hcamcorder->cam_attrs_const_info[idx].validity_value_1.double_array &&
1083                                     hcamcorder->cam_attrs_const_info[idx].validity_value_2.count > 0) {
1084                                         mmf_attrs_set_valid_double_array(attrs, idx,
1085                                                                          (const double *)(hcamcorder->cam_attrs_const_info[idx].validity_value_1.double_array),
1086                                                                          hcamcorder->cam_attrs_const_info[idx].validity_value_2.count,
1087                                                                          hcamcorder->cam_attrs_const_info[idx].default_value.value_double);
1088                                 }
1089                         break;
1090                         case MM_ATTRS_VALID_TYPE_DOUBLE_RANGE:
1091                                 mmf_attrs_set_valid_double_range(attrs, idx,
1092                                                                  hcamcorder->cam_attrs_const_info[idx].validity_value_1.double_min,
1093                                                                  hcamcorder->cam_attrs_const_info[idx].validity_value_2.double_max,
1094                                                                  hcamcorder->cam_attrs_const_info[idx].default_value.value_double);
1095                         break;
1096                         case MM_ATTRS_VALID_TYPE_NONE:
1097                         break;
1098                         case MM_ATTRS_VALID_TYPE_INVALID:
1099                         default:
1100                                 _mmcam_dbg_err("Valid type error.");
1101                         break;
1102                 }
1103         }
1104
1105         return attrs;
1106 }
1107
1108 static gboolean
1109 __mmcamcorder_client_gstreamer_init(camera_conf * conf)
1110 {
1111         static const int max_argc = 10;
1112         int i = 0;
1113         int cnt_str = 0;
1114         gint *argc = NULL;
1115         gchar **argv = NULL;
1116         GError *err = NULL;
1117         gboolean ret = FALSE;
1118         type_string_array *GSTInitOption = NULL;
1119
1120         mmf_return_val_if_fail(conf, FALSE);
1121
1122         _mmcam_dbg_log("");
1123
1124         /* alloc */
1125         argc = malloc(sizeof(int));
1126         argv = malloc(sizeof(gchar *) * max_argc);
1127
1128         if (!argc || !argv) {
1129                 goto ERROR;
1130         }
1131
1132         memset(argv, 0, sizeof(gchar *) * max_argc);
1133
1134         /* add initial */
1135         *argc = 1;
1136         argv[0] = g_strdup("mmcamcorder");
1137
1138         /* add gst_param */
1139         _mmcamcorder_conf_get_value_string_array(conf,
1140                                                  CONFIGURE_CATEGORY_MAIN_GENERAL,
1141                                                  "GSTInitOption",
1142                                                  &GSTInitOption);
1143         if (GSTInitOption != NULL && GSTInitOption->value) {
1144                 cnt_str = GSTInitOption->count;
1145                 for( ; *argc < max_argc && *argc <= cnt_str ; (*argc)++ )
1146                 {
1147                         argv[*argc] = g_strdup(GSTInitOption->value[(*argc)-1]);
1148                 }
1149         }
1150
1151         _mmcam_dbg_log("initializing gstreamer with following parameter[argc:%d]", *argc);
1152
1153         for (i = 0; i < *argc; i++) {
1154                 _mmcam_dbg_log("argv[%d] : %s", i, argv[i]);
1155         }
1156
1157         /* initializing gstreamer */
1158         ret = gst_init_check (argc, &argv, &err);
1159         if (!ret) {
1160                 _mmcam_dbg_err("Could not initialize GStreamer: %s ",
1161                                err ? err->message : "unknown error occurred");
1162                 if (err) {
1163                         g_error_free (err);
1164                 }
1165         }
1166
1167         /* release */
1168         for (i = 0; i < *argc; i++) {
1169                 if (argv[i]) {
1170                         g_free(argv[i]);
1171                         argv[i] = NULL;
1172                 }
1173         }
1174
1175         free(argv);
1176         argv = NULL;
1177
1178         free(argc);
1179         argc = NULL;
1180
1181         return ret;
1182
1183 ERROR:
1184         _mmcam_dbg_err("failed to initialize gstreamer");
1185
1186         if (argv) {
1187                 free(argv);
1188                 argv = NULL;
1189         }
1190
1191         if (argc) {
1192                 free(argc);
1193                 argc = NULL;
1194         }
1195
1196         return FALSE;
1197 }
1198
1199 int _mmcamcorder_client_create_preview_elements(MMHandleType handle, const char *videosink_name, char *string_caps)
1200 {
1201         int ret = MM_ERROR_NONE;
1202         GList *element_list = NULL;
1203         GstElement *pipeline = NULL;
1204         char *socket_path = NULL;
1205         int socket_path_length;
1206         GstCaps *caps;
1207
1208         mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
1209         mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
1210         mmf_return_val_if_fail(hcamcorder->sub_context, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
1211
1212         _MMCamcorderSubContext *sc = MMF_CAMCORDER_SUBCONTEXT(handle);
1213
1214         /* create pipeline */
1215         _MMCAMCORDER_PIPELINE_MAKE(sc, sc->element, _MMCAMCORDER_CLIENT_MAIN_PIPE, "camera_client", ret);
1216
1217         /* create source */
1218         if (hcamcorder->use_zero_copy_format) {
1219                 _MMCAMCORDER_ELEMENT_MAKE(sc, sc->element, _MMCAMCORDER_CLIENT_VIDEOSRC_SRC, "tizenipcsrc", "client_videosrc_src", element_list, ret);
1220         } else {
1221                 _MMCAMCORDER_ELEMENT_MAKE(sc, sc->element, _MMCAMCORDER_CLIENT_VIDEOSRC_SRC, "shmsrc", "client_videosrc_src", element_list, ret);
1222         }
1223
1224         mm_camcorder_get_attributes(handle, NULL,
1225                                     MMCAM_DISPLAY_SOCKET_PATH, &socket_path, &socket_path_length,
1226                                     NULL);
1227
1228         if (socket_path == NULL ) {
1229                 _mmcam_dbg_err("socket path is not set");
1230                 goto set_videosrc_error;
1231         }
1232
1233         _mmcam_dbg_err("ipc src socket path : %s", socket_path);
1234
1235         g_object_set(sc->element[_MMCAMCORDER_CLIENT_VIDEOSRC_SRC].gst,
1236                      "socket-path", socket_path,
1237                      "is-live", TRUE,
1238                      NULL);
1239
1240         /* create capsfilter */
1241         _MMCAMCORDER_ELEMENT_MAKE(sc, sc->element, _MMCAMCORDER_CLIENT_VIDEOSRC_FILT, "capsfilter", "client_vidoesrc_filt", element_list, ret);
1242
1243         caps = gst_caps_from_string(string_caps);
1244         MMCAMCORDER_G_OBJECT_SET_POINTER(sc->element[_MMCAMCORDER_CLIENT_VIDEOSRC_FILT].gst, "caps", caps);
1245
1246         gst_caps_unref(caps);
1247
1248         caps = NULL;
1249
1250         /* Making Video sink from here */
1251         _MMCAMCORDER_ELEMENT_MAKE(sc, sc->element, _MMCAMCORDER_CLIENT_VIDEOSINK_QUE, "queue", "client_videosink_queue", element_list, ret);
1252
1253         /* Add color converting element */
1254         if (!strcmp(videosink_name, "evasimagesink") || !strcmp(videosink_name, "ximagesink")) {
1255                 _MMCAMCORDER_ELEMENT_MAKE(sc, sc->element, _MMCAMCORDER_CLIENT_VIDEOSINK_CLS, "videoconvert", "client_videosrc_convert", element_list, ret);
1256         }
1257
1258         /* create sink */
1259         _MMCAMCORDER_ELEMENT_MAKE(sc, sc->element, _MMCAMCORDER_CLIENT_VIDEOSINK_SINK, videosink_name, "client_videosink_sink", element_list, ret);
1260
1261         if (strcmp(videosink_name, "fakesink") && strcmp(videosink_name, "tizenipcsink") &&
1262                 strcmp(videosink_name, "shmsink")) {
1263                 if (_mmcamcorder_client_videosink_window_set(handle, sc->VideosinkElement) != MM_ERROR_NONE) {
1264                         _mmcam_dbg_err("_mmcamcorder_client_videosink_window_set error");
1265                         ret = MM_ERROR_CAMCORDER_INVALID_ARGUMENT;
1266                         goto pipeline_creation_error;
1267                 }
1268         }
1269
1270         _mmcamcorder_conf_set_value_element_property(sc->element[_MMCAMCORDER_CLIENT_VIDEOSINK_SINK].gst, sc->VideosinkElement);
1271
1272         /* add elements to main pipeline */
1273         if (!_mmcamcorder_add_elements_to_bin(GST_BIN(sc->element[_MMCAMCORDER_CLIENT_MAIN_PIPE].gst), element_list)) {
1274                 _mmcam_dbg_err("element_list add error.");
1275                 ret = MM_ERROR_CAMCORDER_RESOURCE_CREATION;
1276                 goto pipeline_creation_error;
1277         }
1278
1279         /* link elements */
1280         if (!_mmcamcorder_link_elements(element_list)) {
1281                 _mmcam_dbg_err( "element link error." );
1282                 ret = MM_ERROR_CAMCORDER_GST_LINK;
1283                 goto pipeline_creation_error;
1284         }
1285
1286         pipeline = sc->element[_MMCAMCORDER_CLIENT_MAIN_PIPE].gst;
1287
1288         ret = _mmcamcorder_gst_set_state(handle, pipeline, GST_STATE_PLAYING);
1289         if (ret != MM_ERROR_NONE) {
1290                 _mmcam_dbg_err("error : destroy pipeline");
1291                 goto pipeline_creation_error;
1292         }
1293
1294         if (element_list) {
1295                 g_list_free(element_list);
1296                 element_list = NULL;
1297         }
1298
1299         return MM_ERROR_NONE;
1300
1301 pipeline_creation_error:
1302         _MMCAMCORDER_ELEMENT_REMOVE(sc->element, _MMCAMCORDER_CLIENT_VIDEOSINK_SINK);
1303         if (!strcmp(videosink_name, "evasimagesink") || !strcmp(videosink_name, "ximagesink")) {
1304                 _MMCAMCORDER_ELEMENT_REMOVE(sc->element, _MMCAMCORDER_CLIENT_VIDEOSINK_CLS);
1305         }
1306         _MMCAMCORDER_ELEMENT_REMOVE(sc->element, _MMCAMCORDER_CLIENT_VIDEOSINK_QUE);
1307 set_videosrc_error:
1308         _MMCAMCORDER_ELEMENT_REMOVE(sc->element, _MMCAMCORDER_CLIENT_VIDEOSRC_SRC);
1309         _MMCAMCORDER_ELEMENT_REMOVE(sc->element, _MMCAMCORDER_CLIENT_MAIN_PIPE);
1310
1311         if (element_list) {
1312                 g_list_free(element_list);
1313                 element_list = NULL;
1314         }
1315
1316         return ret;
1317 }
1318
1319 void __mmcamcorder_client_gst_destroy_pipeline(MMHandleType handle)
1320 {
1321         _MMCamcorderSubContext *sc;
1322         sc = MMF_CAMCORDER_SUBCONTEXT(handle);
1323
1324         if (sc->element[_MMCAMCORDER_CLIENT_MAIN_PIPE].gst) {
1325                 MMCAMCORDER_G_OBJECT_SET(sc->element[_MMCAMCORDER_CLIENT_VIDEOSINK_QUE].gst, "empty-buffers", TRUE);
1326
1327                 _mmcamcorder_gst_set_state(handle, sc->element[_MMCAMCORDER_CLIENT_MAIN_PIPE].gst, GST_STATE_NULL);
1328                 _mmcamcorder_remove_all_handlers(handle, _MMCAMCORDER_HANDLER_CATEGORY_ALL);
1329
1330                 gst_object_unref(sc->element[_MMCAMCORDER_CLIENT_MAIN_PIPE].gst);
1331         }
1332
1333         return;
1334 }
1335
1336 int _mmcamcorder_client_realize(MMHandleType handle, char *string_caps)
1337 {
1338         int ret = MM_ERROR_NONE;
1339         mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
1340
1341         _MMCamcorderSubContext *sc;
1342         int display_surface_type = MM_DISPLAY_SURFACE_X;
1343         char *videosink_element_type = NULL;
1344         const char *videosink_name = NULL;
1345         char *err_name = NULL;
1346
1347         mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
1348         _mmcam_dbg_log("Enter");
1349
1350         if (!_MMCAMCORDER_TRYLOCK_CMD(hcamcorder)) {
1351                 _mmcam_dbg_err("Another command is running.");
1352                 ret = MM_ERROR_CAMCORDER_CMD_IS_RUNNING;
1353                 goto _ERR_CAMCORDER_CMD_PRECON;
1354         }
1355
1356         /* alloc sub context */
1357         hcamcorder->sub_context = _mmcamcorder_alloc_subcontext(hcamcorder->type);
1358         if(!hcamcorder->sub_context) {
1359                 ret = MM_ERROR_CAMCORDER_RESOURCE_CREATION;
1360                 goto _ERR_CAMCORDER_CMD;
1361         }
1362
1363         sc = MMF_CAMCORDER_SUBCONTEXT(handle);
1364
1365         ret = mm_camcorder_get_attributes(handle, &err_name,
1366                                     MMCAM_DISPLAY_SURFACE, &display_surface_type,
1367                                     NULL);
1368
1369         if (ret != MM_ERROR_NONE) {
1370                 _mmcam_dbg_warn("Get attrs fail. (%s:%x)", err_name, ret);
1371                 SAFE_FREE(err_name);
1372                 goto _ERR_CAMCORDER_SET_DISPLAY;
1373         }
1374
1375         _mmcam_dbg_warn("display_surface_type : %d", display_surface_type);
1376
1377         switch (display_surface_type) {
1378         case MM_DISPLAY_SURFACE_X:
1379                 videosink_element_type = strdup("VideosinkElementX");
1380                 break;
1381         case MM_DISPLAY_SURFACE_EVAS:
1382                 videosink_element_type = strdup("VideosinkElementEvas");
1383                 break;
1384         case MM_DISPLAY_SURFACE_GL:
1385                 videosink_element_type = strdup("VideosinkElementGL");
1386                 break;
1387         case MM_DISPLAY_SURFACE_NULL:
1388                 videosink_element_type = strdup("VideosinkElementNull");
1389                 break;
1390         default:
1391                 videosink_element_type = strdup("VideosinkElementX");
1392                 break;
1393         }
1394
1395         /* check string of videosink element */
1396         if (videosink_element_type) {
1397                 _mmcamcorder_conf_get_element(handle, hcamcorder->conf_main,
1398                                               CONFIGURE_CATEGORY_MAIN_VIDEO_OUTPUT,
1399                                               videosink_element_type,
1400                                               &sc->VideosinkElement);
1401                 free(videosink_element_type);
1402                 videosink_element_type = NULL;
1403         } else {
1404                 _mmcam_dbg_warn("strdup failed(display_surface_type %d). Use default X type",
1405                                 display_surface_type);
1406
1407                 _mmcamcorder_conf_get_element(handle, hcamcorder->conf_main,
1408                                               CONFIGURE_CATEGORY_MAIN_VIDEO_OUTPUT,
1409                                               _MMCAMCORDER_DEFAULT_VIDEOSINK_TYPE,
1410                                               &sc->VideosinkElement);
1411         }
1412
1413         _mmcamcorder_conf_get_value_element_name(sc->VideosinkElement, &videosink_name);
1414
1415         if(videosink_name != NULL) {
1416                 _mmcam_dbg_log("Videosink name : %s", videosink_name);
1417                 ret = _mmcamcorder_client_create_preview_elements(handle, videosink_name, string_caps);
1418                 if (ret != MM_ERROR_NONE) {
1419                         _mmcam_dbg_err("create client's preview elements Failed.");
1420                         goto _ERR_CAMCORDER_SET_DISPLAY;
1421                 }
1422         } else {
1423                 _mmcam_dbg_err("Get Videosink name error");
1424                 goto _ERR_CAMCORDER_SET_DISPLAY;
1425         }
1426
1427         /* set command function */
1428         _mmcamcorder_set_state(handle, MM_CAMCORDER_STATE_READY);
1429
1430         _MMCAMCORDER_UNLOCK_CMD(hcamcorder);
1431         return ret;
1432
1433 _ERR_CAMCORDER_SET_DISPLAY:
1434         if (hcamcorder->sub_context) {
1435                 _mmcamcorder_dealloc_subcontext(hcamcorder->sub_context);
1436                 hcamcorder->sub_context = NULL;
1437         }
1438 _ERR_CAMCORDER_CMD:
1439         _MMCAMCORDER_UNLOCK_CMD(hcamcorder);
1440 _ERR_CAMCORDER_CMD_PRECON:
1441         return ret;
1442 }
1443
1444 int _mmcamcorder_client_unrealize(MMHandleType handle)
1445 {
1446         int ret = MM_ERROR_NONE;
1447         int state = MM_CAMCORDER_STATE_NONE;
1448         int state_FROM = MM_CAMCORDER_STATE_READY;
1449         int state_TO = MM_CAMCORDER_STATE_NULL;
1450
1451         mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
1452         mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_NOT_INITIALIZED);
1453         _mmcam_dbg_log("Enter");
1454
1455         if (!hcamcorder) {
1456                 _mmcam_dbg_err("Not initialized");
1457                 ret = MM_ERROR_CAMCORDER_NOT_INITIALIZED;
1458                 return ret;
1459         }
1460
1461         _mmcam_dbg_log("try lock");
1462         if (!_MMCAMCORDER_TRYLOCK_CMD(hcamcorder)) {
1463                 _mmcam_dbg_err("Another command is running.");
1464                 ret = MM_ERROR_CAMCORDER_CMD_IS_RUNNING;
1465                 goto _ERR_CAMCORDER_CMD_PRECON;
1466         }
1467
1468         state = _mmcamcorder_get_state(handle);
1469         if (state != state_FROM) {
1470                 _mmcam_dbg_err("Wrong state(%d)", state);
1471                 ret = MM_ERROR_CAMCORDER_INVALID_STATE;
1472                 goto _ERR_CAMCORDER_CMD_PRECON_AFTER_LOCK;
1473         }
1474
1475         /* Release SubContext */
1476         if (hcamcorder->sub_context) {
1477                 /* destroy pipeline */
1478                 _mmcam_dbg_warn("destroy pipeline");
1479                 __mmcamcorder_client_gst_destroy_pipeline(handle);
1480                 /* Deallocate SubContext */
1481                 _mmcamcorder_dealloc_subcontext(hcamcorder->sub_context);
1482                 hcamcorder->sub_context = NULL;
1483         }
1484
1485         /* Deinitialize main context member */
1486         hcamcorder->command = NULL;
1487
1488         _mmcam_dbg_log("un lock");
1489         _MMCAMCORDER_UNLOCK_CMD(hcamcorder);
1490
1491         _mmcamcorder_set_state(handle, state_TO);
1492
1493         return MM_ERROR_NONE;
1494
1495 _ERR_CAMCORDER_CMD_PRECON_AFTER_LOCK:
1496         _mmcam_dbg_log("un lock");
1497         _MMCAMCORDER_UNLOCK_CMD(hcamcorder);
1498
1499 _ERR_CAMCORDER_CMD_PRECON:
1500         /* send message */
1501         _mmcam_dbg_err("Unrealize fail (type %d, ret %x)",
1502                        hcamcorder->type, ret);
1503
1504         return ret;
1505 }
1506
1507 static int _mm_camcorder_client_set_socket_path(MMHandleType handle, const char *path)
1508 {
1509         int ret = MM_ERROR_NONE;
1510
1511         _mmcam_dbg_log("handle : 0x%x, path:%s", handle, path);
1512
1513         mm_camcorder_set_attributes(handle, NULL,
1514                                     MMCAM_DISPLAY_SOCKET_PATH, path, strlen(path),
1515                                     NULL);
1516
1517         return ret;
1518 }
1519
1520 int mm_camcorder_client_create(MMHandleType *handle)
1521 {
1522         int ret = MM_ERROR_NONE;
1523         mmf_camcorder_t *hcamcorder = NULL;
1524
1525         _mmcam_dbg_log("Enter");
1526         mmf_return_val_if_fail(handle, MM_ERROR_CAMCORDER_INVALID_ARGUMENT);
1527
1528         /* Create mmf_camcorder_t handle and initialize every variable */
1529         hcamcorder = (mmf_camcorder_t *)malloc(sizeof(mmf_camcorder_t));
1530         mmf_return_val_if_fail(hcamcorder, MM_ERROR_CAMCORDER_LOW_MEMORY);
1531         memset(hcamcorder, 0x00, sizeof(mmf_camcorder_t));
1532
1533         /* init values */
1534         hcamcorder->type = 0;
1535         hcamcorder->state = MM_CAMCORDER_STATE_NONE;
1536         hcamcorder->sub_context = NULL;
1537         hcamcorder->target_state = MM_CAMCORDER_STATE_NULL;
1538         hcamcorder->capture_in_recording = FALSE;
1539
1540         g_mutex_init(&(hcamcorder->mtsafe).lock);
1541         g_cond_init(&(hcamcorder->mtsafe).cond);
1542         g_mutex_init(&(hcamcorder->mtsafe).cmd_lock);
1543         g_mutex_init(&(hcamcorder->mtsafe).state_lock);
1544         g_mutex_init(&(hcamcorder->mtsafe).gst_state_lock);
1545         g_mutex_init(&(hcamcorder->mtsafe).message_cb_lock);
1546         g_mutex_init(&hcamcorder->restart_preview_lock);
1547
1548         /* Get Camera Configure information from Camcorder INI file */
1549         _mmcamcorder_conf_get_info((MMHandleType)hcamcorder, CONFIGURE_TYPE_MAIN, CONFIGURE_MAIN_FILE, &hcamcorder->conf_main);
1550
1551         if (!(hcamcorder->conf_main)) {
1552                 _mmcam_dbg_err( "Failed to get configure(main) info." );
1553
1554                 ret = MM_ERROR_CAMCORDER_CREATE_CONFIGURE;
1555                 goto _ERR_CAMCORDER_CREATE_CONFIGURE;
1556         }
1557         _mmcam_dbg_log("aloc attribute handle : 0x%x", (MMHandleType)hcamcorder);
1558         hcamcorder->attributes = _mmcamcorder_client_alloc_attribute((MMHandleType)hcamcorder);
1559         if (!(hcamcorder->attributes)) {
1560                 _mmcam_dbg_err("_mmcamcorder_create::alloc attribute error.");
1561
1562                 ret = MM_ERROR_CAMCORDER_RESOURCE_CREATION;
1563                 goto _ERR_CAMCORDER_RESOURCE_CREATION;
1564         }
1565
1566         ret = __mmcamcorder_client_gstreamer_init(hcamcorder->conf_main);
1567         if (!ret) {
1568                 _mmcam_dbg_err( "Failed to initialize gstreamer!!" );
1569                 ret = MM_ERROR_CAMCORDER_NOT_INITIALIZED;
1570                 goto _ERR_DEFAULT_VALUE_INIT;
1571         }
1572
1573         ret = _mmcamcorder_client_init_attr_from_configure((MMHandleType)hcamcorder);
1574         if (ret != MM_ERROR_NONE) {
1575                 _mmcam_dbg_warn("client_init_attr_from_configure error!!");
1576                 ret = MM_ERROR_CAMCORDER_INTERNAL;
1577                 goto _ERR_DEFAULT_VALUE_INIT;
1578         }
1579
1580         /* Get UseZeroCopyFormat value from INI */
1581         _mmcamcorder_conf_get_value_int((MMHandleType)hcamcorder, hcamcorder->conf_main,
1582                                         CONFIGURE_CATEGORY_MAIN_VIDEO_INPUT,
1583                                         "UseZeroCopyFormat",
1584                                         &(hcamcorder->use_zero_copy_format));
1585
1586         /* Set initial state */
1587         _mmcamcorder_set_state((MMHandleType)hcamcorder, MM_CAMCORDER_STATE_NULL);
1588
1589         _mmcam_dbg_log("created handle %p - UseZeroCopyFormat %d",
1590                 hcamcorder, hcamcorder->use_zero_copy_format);
1591
1592         *handle = (MMHandleType)hcamcorder;
1593         _mmcam_dbg_log("created client handle : 0x%x", *handle);
1594
1595         return MM_ERROR_NONE;
1596
1597 _ERR_CAMCORDER_CREATE_CONFIGURE:
1598 _ERR_CAMCORDER_RESOURCE_CREATION:
1599 _ERR_DEFAULT_VALUE_INIT:
1600         /* Release lock, cond */
1601         g_mutex_clear(&(hcamcorder->mtsafe).lock);
1602         g_cond_clear(&(hcamcorder->mtsafe).cond);
1603         g_mutex_clear(&(hcamcorder->mtsafe).cmd_lock);
1604         g_mutex_clear(&(hcamcorder->mtsafe).state_lock);
1605         g_mutex_clear(&(hcamcorder->mtsafe).gst_state_lock);
1606         g_mutex_clear(&(hcamcorder->mtsafe).gst_encode_state_lock);
1607         g_mutex_clear(&(hcamcorder->mtsafe).message_cb_lock);
1608
1609         g_mutex_clear(&(hcamcorder->restart_preview_lock));
1610
1611         if (hcamcorder->conf_ctrl) {
1612                 _mmcamcorder_conf_release_info(handle, &hcamcorder->conf_ctrl);
1613         }
1614
1615         if (hcamcorder->conf_main) {
1616                 _mmcamcorder_conf_release_info(handle, &hcamcorder->conf_main);
1617         }
1618
1619         /* Release handle */
1620         memset(hcamcorder, 0x00, sizeof(mmf_camcorder_t));
1621         free(hcamcorder);
1622
1623         return ret;
1624 }
1625
1626 void mm_camcorder_client_destroy(MMHandleType handle)
1627 {
1628         mmf_camcorder_t *hcamcorder = MMF_CAMCORDER(handle);
1629
1630         _mmcam_dbg_log("try lock");
1631
1632         if (!_MMCAMCORDER_TRYLOCK_CMD(hcamcorder)) {
1633                 _mmcam_dbg_err("Another command is running.");
1634                 goto _ERR_CAMCORDER_CMD_PRECON;
1635         }
1636
1637         if (hcamcorder->attributes) {
1638                 _mmcamcorder_dealloc_attribute(handle, hcamcorder->attributes);
1639         }
1640
1641         _mmcam_dbg_log("unlock");
1642         _MMCAMCORDER_UNLOCK_CMD(hcamcorder);
1643
1644         g_mutex_clear(&((hcamcorder->mtsafe).lock));
1645         g_cond_clear(&((hcamcorder->mtsafe).cond));
1646         g_mutex_clear(&((hcamcorder->mtsafe).cmd_lock));
1647         g_mutex_clear(&((hcamcorder->mtsafe).state_lock));
1648         g_mutex_clear(&((hcamcorder->mtsafe).gst_state_lock));
1649         g_mutex_clear(&((hcamcorder->mtsafe).message_cb_lock));
1650         g_mutex_clear(&(hcamcorder->restart_preview_lock));
1651         _mmcamcorder_set_state((MMHandleType)hcamcorder, MM_CAMCORDER_STATE_NONE);
1652         /* Release handle */
1653         memset(hcamcorder, 0x00, sizeof(mmf_camcorder_t));
1654         free(hcamcorder);
1655
1656 _ERR_CAMCORDER_CMD_PRECON:
1657         return;
1658 }
1659
1660 int mm_camcorder_client_realize(MMHandleType handle, char *caps)
1661 {
1662         int ret = MM_ERROR_NONE;
1663         ret = _mmcamcorder_client_realize(handle, caps);
1664         return ret;
1665 }
1666
1667 int mm_camcorder_client_unrealize(MMHandleType handle)
1668 {
1669         int ret = MM_ERROR_NONE;
1670         ret = _mmcamcorder_client_unrealize(handle);
1671         return ret;
1672 }
1673
1674 int mm_camcorder_client_set_socket_path(MMHandleType handle, const char *path)
1675 {
1676         int ret = MM_ERROR_NONE;
1677         _mmcam_dbg_log("Entered ");
1678         ret = _mm_camcorder_client_set_socket_path(handle, path);
1679         return ret;
1680 }
1681
1682 int mm_camcorder_client_get_root_directory(char **root_directory)
1683 {
1684         int ret = STORAGE_ERROR_NONE;
1685
1686         if (root_directory == NULL) {
1687                 _mmcam_dbg_warn("user data is NULL");
1688                 return MM_ERROR_CAMCORDER_INVALID_ARGUMENT;
1689         }
1690
1691         ret = storage_foreach_device_supported((storage_device_supported_cb)_storage_device_supported_cb, root_directory);
1692         if (ret != STORAGE_ERROR_NONE) {
1693                 _mmcam_dbg_err("storage_foreach_device_supported failed 0x%x", ret);
1694                 return MM_ERROR_CAMCORDER_INTERNAL;
1695         }
1696
1697         return MM_ERROR_NONE;
1698 }