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