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