Fix errors which are created by solving merge conflict
[platform/core/uifw/voice-control.git] / server / vcd_recorder.c
1 /*
2  * Copyright (c) 2011-2017 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include <audio_io.h>
18 #include <math.h>
19 #include <sound_manager.h>
20 #include <sound_manager_internal.h>
21
22 #include "vcd_client_data.h"
23 #include "vcd_config.h"
24 #include "vcd_tidl.h"
25 #include "vcd_engine_agent.h"
26 #include "vcd_recorder.h"
27 #include "dependency_audio_manager.h"
28 #include "vcd_main.h"
29
30 #define FRAME_LENGTH 320
31 #define BUFFER_LENGTH FRAME_LENGTH * 2
32
33 #define FOCUS_SERVER_READY      "/tmp/.focus_server_ready"
34
35 #define VCE_AUDIO_ID_NONE       "VC_AUDIO_ID_NONE"              /**< None audio id */
36 #define VCE_AUDIO_ID_FFV        "VC_FARFIELD_VOICE_VD"
37
38
39 static vcd_recorder_state_e g_recorder_state = VCD_RECORDER_STATE_READY;
40
41 static vcd_recoder_audio_cb g_audio_cb = NULL;
42 static vcd_recorder_interrupt_cb g_interrupt_cb = NULL;
43
44 static sound_stream_info_h g_stream_info_h = NULL;
45 static sound_stream_info_h g_stream_for_volume_h = NULL;
46 static virtual_sound_stream_h g_virtual_sound_stream_h = NULL;
47
48
49 static int g_buffer_count = 0;
50 static int g_device_id = -1;
51
52 static char* g_pcm_path = NULL;
53 static FILE* g_pcm_fp = NULL;
54
55
56 /* Sound buf save */
57 #if 0
58 #define BUF_SAVE_MODE
59 #endif
60
61 #ifdef BUF_SAVE_MODE
62 static FILE* g_normal_file = NULL;
63 static int g_count = 1;
64 #endif
65
66
67 // TODO: make common function?
68 static float get_volume_decibel(const char* data, const unsigned int size)
69 {
70         const int MAX_AMPLITUDE_MEAN_16 = 32768;
71
72         int i, depthByte;
73         int count = 0;
74
75         float db = 0.0;
76         float rms = 0.0;
77         unsigned long long square_sum = 0;
78         short pcm16 = 0;
79
80         depthByte = 2;
81
82         for (i = 0; i < size; i += (depthByte<<1)) {
83                 pcm16 = 0;
84                 memcpy(&pcm16, data + i, sizeof(short));
85                 square_sum += pcm16 * pcm16;
86                 count++;
87         }
88
89         if (0 == count || 0 == square_sum) {
90                 SLOG(LOG_ERROR, TAG_VCD, "[ERROR] No data");
91                 rms = 1.0;
92         } else {
93                 rms = sqrt((float)square_sum/count);
94         }
95
96         db = 20 * log10(rms/MAX_AMPLITUDE_MEAN_16);
97         return db;
98 }
99
100 static const char* __get_focus_changed_reason_code(sound_stream_focus_change_reason_e reason)
101 {
102         switch (reason) {
103         case SOUND_STREAM_FOCUS_CHANGED_BY_MEDIA:               return "SOUND_STREAM_FOCUS_CHANGED_BY_MEDIA";
104         case SOUND_STREAM_FOCUS_CHANGED_BY_SYSTEM:              return "SOUND_STREAM_FOCUS_CHANGED_BY_SYSTEM";
105         case SOUND_STREAM_FOCUS_CHANGED_BY_ALARM:               return "SOUND_STREAM_FOCUS_CHANGED_BY_ALARM";
106         case SOUND_STREAM_FOCUS_CHANGED_BY_NOTIFICATION:        return "SOUND_STREAM_FOCUS_CHANGED_BY_NOTIFICATION";
107         case SOUND_STREAM_FOCUS_CHANGED_BY_EMERGENCY:           return "SOUND_STREAM_FOCUS_CHANGED_BY_EMERGENCY";
108         case SOUND_STREAM_FOCUS_CHANGED_BY_VOICE_INFORMATION:   return "SOUND_STREAM_FOCUS_CHANGED_BY_VOICE_INFORMATION";
109         case SOUND_STREAM_FOCUS_CHANGED_BY_VOICE_RECOGNITION:   return "SOUND_STREAM_FOCUS_CHANGED_BY_VOICE_RECOGNITION";
110         case SOUND_STREAM_FOCUS_CHANGED_BY_RINGTONE:            return "SOUND_STREAM_FOCUS_CHANGED_BY_RINGTONE";
111         case SOUND_STREAM_FOCUS_CHANGED_BY_VOIP:                return "SOUND_STREAM_FOCUS_CHANGED_BY_VOIP";
112         case SOUND_STREAM_FOCUS_CHANGED_BY_CALL:                return "SOUND_STREAM_FOCUS_CHANGED_BY_CALL";
113         case SOUND_STREAM_FOCUS_CHANGED_BY_MEDIA_EXTERNAL_ONLY: return "SOUND_STREAM_FOCUS_CHANGED_BY_MEDIA_EXTERNAL_ONLY";
114         default:                                                return "Undefined reason code";
115         }
116 }
117
118 static void __recorder_focus_state_cb(sound_stream_info_h stream_info, sound_stream_focus_mask_e focus_mask, sound_stream_focus_state_e focus_state,
119                 sound_stream_focus_change_reason_e reason, int sound_behavior, const char *extra_info, void *user_data)
120 {
121         SLOG(LOG_INFO, TAG_VCD, "[Recorder] Focus state changed cb");
122
123         if (stream_info != g_stream_info_h) {
124                 SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Invalid stream info handle");
125                 return;
126         }
127
128         SLOG(LOG_WARN, TAG_VCD, "[Recorder] focus state changed to (%d) with reason (%s)", (int)focus_state, __get_focus_changed_reason_code(reason));
129
130         if (VCD_RECORDER_STATE_RECORDING == g_recorder_state && SOUND_STREAM_FOCUS_STATE_RELEASED == focus_state) {
131                 SLOG(LOG_WARN, TAG_VCD, "[Recorder] Focus released as interrupt");
132                 if (NULL != g_interrupt_cb) {
133                         g_interrupt_cb();
134                 }
135         }
136 }
137
138 static int __apply_device_for_stream_routing()
139 {
140         sound_device_list_h device_list = NULL;
141         sound_device_h device = NULL;
142         sound_device_type_e type;
143         sound_device_io_direction_e io_direction;
144
145         if (0 != sound_manager_get_device_list(SOUND_DEVICE_IO_DIRECTION_IN_MASK, &device_list)) {
146                 SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Fail to get current device list");
147                 return -1;
148         }
149
150         int ret = -1;
151         while (0 == sound_manager_get_next_device(device_list, &device)) {
152                 if (0 != sound_manager_get_device_type(device, &type)) {
153                         SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Fail to get device type");
154                         continue;
155                 }
156                 if (0 != sound_manager_get_device_io_direction(device, &io_direction)) {
157                         SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Fail to get device io direction");
158                         continue;
159                 }
160                 if (SOUND_DEVICE_USB_AUDIO == type && SOUND_DEVICE_IO_DIRECTION_IN == io_direction) {
161                         if (0 != sound_manager_add_device_for_stream_routing(g_stream_info_h, device)) {
162                                 SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Fail to add device");
163                                 continue;
164                         }
165                         if (0 != sound_manager_apply_stream_routing(g_stream_info_h)) {
166                                 SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Fail to apply stream routing");
167                                 continue;
168                         }
169                         ret = 0;
170                         break;
171                 }
172         }
173
174         sound_manager_free_device_list(device_list);
175         device_list = NULL;
176
177         if (0 != ret) {
178                 SLOG(LOG_WARN, TAG_VCD, "[Recorder] No device");
179         } else {
180                 SLOG(LOG_INFO, TAG_VCD, "[Recorder] Apply device for stream routing");
181         }
182         return ret;
183 }
184
185 static void __device_connection_changed_cb(sound_device_h device, bool is_connected, void *user_data)
186 {
187         sound_device_type_e type;
188         if (is_connected) {
189                 if (0 != sound_manager_get_device_type(device, &type)) {
190                         SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Fail to get device type");
191                         return;
192                 }
193                 if (type == SOUND_DEVICE_USB_AUDIO) {
194                         bool is_recording_state = false;
195                         if (VCD_RECORDER_STATE_RECORDING == g_recorder_state) {
196                                 SLOG(LOG_INFO, TAG_VCD, "[Recorder] Stop recorder");
197                                 vcd_recorder_stop();
198                                 is_recording_state = true;
199                         }
200                         if (0 != sound_manager_remove_device_for_stream_routing(g_stream_info_h, device))
201                                 SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Fail to remove device");
202
203                         if (0 != sound_manager_add_device_for_stream_routing(g_stream_info_h, device)) {
204                                 SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Fail to add device");
205                                 return;
206                         }
207                         if (0 != sound_manager_apply_stream_routing(g_stream_info_h)) {
208                                 SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR} Fail to apply stream routing");
209                                 return;
210                         }
211                         if (true == is_recording_state) {
212                                 SLOG(LOG_INFO, TAG_VCD, "[Recorder] Start recorder");
213                                 vcd_recorder_start();
214                         }
215                         SLOG(LOG_INFO, TAG_VCD, "[Recorder] Apply device for stream routing");
216                 }
217         }
218         return;
219 }
220
221 static int __feed_audio_data_cb(const void* data, const unsigned int length)
222 {
223         if (NULL != g_audio_cb) {
224                 if (0 != g_audio_cb(data, length)) {
225                         SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Fail to read audio");
226                         vcd_recorder_stop();
227                 }
228         }
229
230         if (0 == g_buffer_count % 15) {
231                 float vol_db = get_volume_decibel((char*)data, length);
232                 if (0 != vcdc_send_set_volume(vcd_client_manager_get_pid(), vol_db)) {
233                         SLOG(LOG_ERROR, TAG_VCD, "[Recorder] Fail to send recording volume(%f)", vol_db);
234                 }
235         }
236
237         if (0 == g_buffer_count % 50) {
238                 SLOG(LOG_WARN, TAG_VCD, "[Recorder][%d] Recording... : read_size(%d)", g_buffer_count, length);
239
240                 if (100000 == g_buffer_count) {
241                         g_buffer_count = 0;
242                 }
243         }
244
245         g_buffer_count++;
246
247 #ifdef BUF_SAVE_MODE
248         /* write pcm buffer */
249         fwrite(data, 1, BUFFER_LENGTH, g_normal_file);
250 #endif
251
252         return VCD_ERROR_NONE;
253 }
254
255
256 int vcd_recorder_create(vcd_recoder_audio_cb audio_cb, vcd_recorder_interrupt_cb interrupt_cb)
257 {
258         if (NULL == audio_cb || NULL == interrupt_cb) {
259                 SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Input param is NOT valid");
260                 return VCD_ERROR_INVALID_PARAMETER;
261         }
262
263         /* check focus server */
264         int cnt = 0;
265         while (1) {
266                 if (0 == access(FOCUS_SERVER_READY, F_OK)) {
267                         SLOG(LOG_ERROR, TAG_VCD, "[Recorder SUCCESS] focus server is available");
268                         break;
269                 } else {
270                         if (0 == cnt++ % 10)
271                                 SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] focus server is not available");
272                         usleep(50000);
273                 }
274         }
275
276         int ret = sound_manager_add_device_connection_changed_cb(SOUND_DEVICE_IO_DIRECTION_IN_MASK, __device_connection_changed_cb, NULL, &g_device_id);
277         if (0 != ret)
278                 SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Fail to add device connection changed callback");
279
280         if (0 != sound_manager_create_stream_information_internal(SOUND_STREAM_TYPE_VOICE_RECOGNITION_SERVICE, __recorder_focus_state_cb, NULL, &g_stream_info_h)) {
281                 SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Fail to create stream info");
282         } else {
283                 __apply_device_for_stream_routing();
284         }
285
286         if (0 != dependency_audio_manager_initialize(g_stream_info_h, __feed_audio_data_cb)) {
287                 SLOG(LOG_ERROR, TAG_VCD, "[ERROR] Fail to initialize dependency audio manager");
288                 return VCD_ERROR_OPERATION_FAILED;
289         }
290
291         g_audio_cb = audio_cb;
292         g_interrupt_cb = interrupt_cb;
293         g_recorder_state = VCD_RECORDER_STATE_READY;
294
295         return ret;
296 }
297
298 int vcd_recorder_destroy()
299 {
300         if (VCD_RECORDER_STATE_RECORDING == g_recorder_state) {
301                 vcd_recorder_stop();
302         }
303
304         int ret = sound_manager_remove_device_connection_changed_cb(g_device_id);
305         if (0 != ret) {
306                 SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Fail to remove device connection changed callback, ret(%d)", ret);
307         }
308         g_device_id = -1;
309
310         ret = sound_manager_destroy_stream_information(g_stream_info_h);
311         if (0 != ret) {
312                 SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Fail to destroy stream info, ret(%d)", ret);
313         }
314         g_stream_info_h = NULL;
315
316         ret = dependency_audio_manager_deinitialize();
317         if (0 != ret) {
318                 SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Fail to audio in destroy, ret(%d)", ret);
319         }
320
321         g_audio_cb = NULL;
322
323         if (NULL != g_pcm_path) {
324                 free(g_pcm_path);
325                 g_pcm_path = NULL;
326         }
327
328         if (NULL != g_pcm_fp) {
329                 fclose(g_pcm_fp);
330                 g_pcm_fp = NULL;
331         }
332
333         return VCD_ERROR_NONE;
334 }
335
336 int vcd_recorder_set(const char* audio_type, vce_audio_type_e type, int rate, int channel)
337 {
338         if (NULL == audio_type) {
339                 SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] audio_type is NULL");
340                 return VCD_ERROR_INVALID_PARAMETER;
341         }
342
343         SLOG(LOG_INFO, TAG_VCD, "[Recorder] set audio type (%s)", audio_type);
344         vcd_engine_set_audio_type(audio_type);
345
346         int ret = -1;
347         ret = dependency_audio_manager_set_audio_info(g_stream_info_h, audio_type, type, rate, channel);
348         if (0 != ret) {
349                 SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Fail to set audio information");
350                 return VCD_ERROR_OPERATION_FAILED;
351         }
352
353         return VCD_ERROR_NONE;
354 }
355
356 int vcd_recorder_get(char** audio_type)
357 {
358         if (NULL == audio_type) {
359                 return VCD_ERROR_INVALID_PARAMETER;
360         }
361
362         if (0 != dependency_audio_manager_get_audio_source_type(audio_type)) {
363                 SLOG(LOG_WARN, TAG_VCD, "[Recorder] Current audio type(%s) is NOT ready", *audio_type);
364                 *audio_type = NULL;
365                 return VCD_ERROR_INVALID_STATE;
366         }
367
368         return VCD_ERROR_NONE;
369 }
370
371 int vcd_recorder_set_audio_streaming_mode(vcd_audio_streaming_mode_e mode)
372 {
373         if (0 != dependency_audio_manager_set_streaming_mode((vc_audio_streaming_mode_e)mode)) {
374                 SLOG(LOG_WARN, TAG_VCD, "[Recorder] Fail to set audio mode to dependency module(%d)", mode);
375                 return VCD_ERROR_OPERATION_FAILED;
376         }
377
378         return VCD_ERROR_NONE;
379 }
380
381 Eina_Bool __read_test_func(void *data)
382 {
383         if (VCD_RECORDER_STATE_RECORDING != g_recorder_state) {
384                 SLOG(LOG_DEBUG, TAG_VCD, "[Recorder test] Exit audio reading normal func");
385                 return EINA_FALSE;
386         }
387
388         if (NULL == g_pcm_fp) {
389                 g_pcm_fp = fopen(g_pcm_path, "r");
390                 if (NULL == g_pcm_fp) {
391                         SLOG(LOG_ERROR, TAG_VCD, "[Recorder test ERROR] Cannot open a file : %s", g_pcm_path);
392                         return EINA_FALSE;
393                 }
394         }
395
396         char buffer[BUFFER_LENGTH + 10];
397         memset(buffer, '\0', BUFFER_LENGTH + 10);
398         int buffer_size = 0;
399         if (!feof(g_pcm_fp))
400                 buffer_size = fread(buffer, 1, BUFFER_LENGTH, g_pcm_fp);
401         if (buffer_size != BUFFER_LENGTH)
402                 SLOG(LOG_DEBUG, TAG_VCD, "[Recorder test] Get data size(%d)", buffer_size);
403
404         buffer_size = MIN(buffer_size, BUFFER_LENGTH);
405
406         if (buffer_size != 0)
407                 __feed_audio_data_cb(buffer, buffer_size);
408
409         float vol_db = get_volume_decibel(buffer, buffer_size);
410         if (0 != vcdc_send_set_volume(vcd_client_manager_get_pid(), vol_db))
411                 SLOG(LOG_ERROR, TAG_VCD, "[Recorder test] Fail to send recording volume(%f)", vol_db);
412
413         if (feof(g_pcm_fp) != 0) {
414                 fclose(g_pcm_fp);
415                 g_pcm_fp = NULL;
416                 return EINA_FALSE;
417         }
418
419         return EINA_TRUE;
420 }
421
422 static void __timer_read_test_func(void *data)
423 {
424         ecore_timer_add(0, __read_test_func, NULL);
425         return;
426 }
427
428 int vcd_recorder_start_streaming()
429 {
430         SLOG(LOG_INFO, TAG_VCD, "[Recorder] start streaming");
431
432         vcd_audio_streaming_mode_e streaming_mode;
433         vcd_config_get_audio_streaming_mode(&streaming_mode);
434         if (VCD_AUDIO_STREAMING_MODE_OUTSIDE != streaming_mode) {
435                 SLOG(LOG_INFO, TAG_VCD, "[Recorder] Current audio streaming mode(%d)", streaming_mode);
436                 return VCD_ERROR_NONE;
437         }
438
439 #ifdef BUF_SAVE_MODE
440         char normal_file_name[128] = {'\0',};
441         g_count++;
442
443         while (1) {
444                 snprintf(normal_file_name, sizeof(normal_file_name), "/tmp/vc_streaming_%d_%d", getpid(), g_count);
445                 int ret = access(normal_file_name, 0);
446
447                 if (0 == ret) {
448                         SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] File is already exist");
449                         if (0 == remove(normal_file_name)) {
450                                 SLOG(LOG_DEBUG, TAG_VCD, "[Recorder] Remove file");
451                                 break;
452                         } else {
453                                 g_count++;
454                         }
455                 } else {
456                         break;
457                 }
458         }
459
460         SLOG(LOG_DEBUG, TAG_VCD, "[Recorder] File normal name : %s", normal_file_name);
461
462         /* open test file */
463         g_normal_file = fopen(normal_file_name, "wb+x");
464         if (!g_normal_file) {
465                 SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] File not found!");
466         }
467 #endif
468
469         return VCD_ERROR_NONE;
470 }
471
472 int vcd_recorder_send_streaming(const void* buffer, const unsigned int length)
473 {
474         vcd_audio_streaming_mode_e streaming_mode;
475         vcd_config_get_audio_streaming_mode(&streaming_mode);
476         if (VCD_AUDIO_STREAMING_MODE_OUTSIDE != streaming_mode) {
477                 SLOG(LOG_INFO, TAG_VCD, "[Recorder] Current audio streaming mode(%d)", streaming_mode);
478                 return VCD_ERROR_NONE;
479         }
480
481         if (NULL != g_audio_cb) {
482                 int ret = g_audio_cb(buffer, length);
483                 if (0 != ret) {
484                         SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Fail to start streaming : %d", ret);
485                         vcd_recorder_stop();
486                         return ret;
487                 }
488         }
489
490 #ifdef BUF_SAVE_MODE
491         /* write pcm buffer */
492         if (g_normal_file)
493                 fwrite(buffer, 1, length, g_normal_file);
494 #endif
495
496         return VCD_ERROR_NONE;
497 }
498
499 int vcd_recorder_stop_streaming()
500 {
501         SLOG(LOG_INFO, TAG_VCD, "[Recorder] stop streaming");
502
503         vcd_audio_streaming_mode_e streaming_mode;
504         vcd_config_get_audio_streaming_mode(&streaming_mode);
505         if (VCD_AUDIO_STREAMING_MODE_OUTSIDE != streaming_mode) {
506                 SLOG(LOG_INFO, TAG_VCD, "[Recorder] Current audio streaming mode(%d)", streaming_mode);
507                 return VCD_ERROR_NONE;
508         }
509
510 #ifdef BUF_SAVE_MODE
511         if (g_normal_file)
512                 fclose(g_normal_file);
513 #endif
514
515         return VCD_ERROR_NONE;
516 }
517
518 int vcd_recorder_change_system_volume()
519 {
520         int ret = VCD_ERROR_NONE;
521
522         if (!g_stream_for_volume_h) {
523                 ret = sound_manager_create_stream_information_internal(SOUND_STREAM_TYPE_VOICE_RECOGNITION_SERVICE, NULL, NULL, &g_stream_for_volume_h);
524                 if (0 != ret) {
525                         SLOG(LOG_INFO, TAG_VCD, "[Recorder] Fail to create stream information, ret(%d)", ret);
526                         return VCD_ERROR_OPERATION_FAILED;
527                 }
528         }
529
530         if (!g_virtual_sound_stream_h) {
531                 ret = sound_manager_create_virtual_stream(g_stream_for_volume_h, &g_virtual_sound_stream_h);
532                 if (0 != ret) {
533                         SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Fail to create virtual stream, ret(%d)", ret);
534                         return VCD_ERROR_OPERATION_FAILED;
535                 }
536
537                 ret = sound_manager_start_virtual_stream(g_virtual_sound_stream_h);
538                 if (0 != ret) {
539                         SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Fail to start virtual stream, ret(%d)", ret);
540                         return VCD_ERROR_OPERATION_FAILED;
541                 }
542         }
543
544         return VCD_ERROR_NONE;
545 }
546
547 int vcd_recorder_recover_system_volume()
548 {
549         int ret = VCD_ERROR_NONE;
550
551         if (g_virtual_sound_stream_h) {
552                 ret = sound_manager_stop_virtual_stream(g_virtual_sound_stream_h);
553                 if (0 != ret) {
554                         SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Fail to stop virtual stream, ret(%d)", ret);
555                         return VCD_ERROR_OPERATION_FAILED;
556                 }
557                 ret = sound_manager_destroy_virtual_stream(g_virtual_sound_stream_h);
558                 if (0 != ret) {
559                         SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Fail to destroy virtual stream, ret(%d)", ret);
560                         return VCD_ERROR_OPERATION_FAILED;
561                 }
562                 g_virtual_sound_stream_h = NULL;
563         }
564
565         if (g_stream_for_volume_h) {
566                 ret = sound_manager_destroy_stream_information(g_stream_for_volume_h);
567                 if (0 != ret) {
568                         SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Fail to destroy stream information, ret(%d)", ret);
569                         return VCD_ERROR_OPERATION_FAILED;
570                 }
571                 g_stream_for_volume_h = NULL;
572         }
573
574         return VCD_ERROR_NONE;
575 }
576
577 int vcd_recorder_start()
578 {
579         vcd_audio_streaming_mode_e streaming_mode;
580         vcd_config_get_audio_streaming_mode(&streaming_mode);
581         if (VCD_AUDIO_STREAMING_MODE_OUTSIDE == streaming_mode) {
582                 SLOG(LOG_INFO, TAG_VCD, "[Recorder] Current audio streaming mode(%d)", streaming_mode);
583                 return VCD_ERROR_NONE;
584         }
585
586         g_buffer_count = 0;
587
588         SLOG(LOG_INFO, TAG_VCD, "[Recorder] Enter, recorder state(%d)", g_recorder_state);
589         if (VCD_RECORDER_STATE_RECORDING == g_recorder_state) {
590                 return VCD_ERROR_NONE;
591         }
592
593         if (NULL != g_pcm_path) {
594                 // For testing
595                 ecore_main_loop_thread_safe_call_async(__timer_read_test_func, NULL);
596         } else {
597                 int ret = dependency_audio_manager_start_recording();
598                 if (0 != ret) {
599                         SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Fail to start recording, [ret(%d)]", ret);
600                         return VCD_ERROR_OPERATION_FAILED;
601                 }
602         }
603
604         g_recorder_state = VCD_RECORDER_STATE_RECORDING;
605
606 #ifdef BUF_SAVE_MODE
607         char normal_file_name[128] = {'\0',};
608         g_count++;
609
610         while (1) {
611                 snprintf(normal_file_name, sizeof(normal_file_name), "/tmp/vc_normal_%d_%d", getpid(), g_count);
612                 int ret = access(normal_file_name, 0);
613
614                 if (0 == ret) {
615                         SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] File is already exist");
616                         if (0 == remove(normal_file_name)) {
617                                 SLOG(LOG_DEBUG, TAG_VCD, "[Recorder] Remove file");
618                                 break;
619                         } else {
620                                 g_count++;
621                         }
622                 } else {
623                         break;
624                 }
625         }
626
627         SLOG(LOG_DEBUG, TAG_VCD, "[Recorder] File normal name : %s", normal_file_name);
628
629         /* open test file */
630         g_normal_file = fopen(normal_file_name, "wb+x");
631         if (!g_normal_file) {
632                 SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] File not found!");
633         }
634 #endif
635         return VCD_ERROR_NONE;
636 }
637
638 int vcd_recorder_stop()
639 {
640         vcd_audio_streaming_mode_e streaming_mode;
641         vcd_config_get_audio_streaming_mode(&streaming_mode);
642         if (VCD_AUDIO_STREAMING_MODE_OUTSIDE == streaming_mode) {
643                 SLOG(LOG_INFO, TAG_VCD, "[Recorder] Current audio streaming mode(%d)", streaming_mode);
644                 return VCD_ERROR_NONE;
645         }
646
647         if (VCD_RECORDER_STATE_READY == g_recorder_state) {
648                 SLOG(LOG_DEBUG, TAG_VCD, "[Recorder] Recorder is already stopped");
649                 return VCD_ERROR_NONE;
650         }
651
652         g_recorder_state = VCD_RECORDER_STATE_READY;
653
654 #ifdef BUF_SAVE_MODE
655         fclose(g_normal_file);
656 #endif
657
658         if (NULL != g_pcm_fp) {
659                 fclose(g_pcm_fp);
660                 g_pcm_fp = NULL;
661         }
662
663         if (NULL != g_pcm_path) {
664                 // For testing
665                 free(g_pcm_path);
666                 g_pcm_path = NULL;
667         } else {
668                 int ret = dependency_audio_manager_stop_recording();
669                 if (0 != ret) {
670                         SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Fail to stop audio : %d", ret);
671                         return ret;
672                 }
673         }
674
675         return VCD_ERROR_NONE;
676 }
677
678 int vcd_recorder_get_state()
679 {
680         return g_recorder_state;
681 }
682
683 int vcd_recorder_set_pcm_path(const char *path)
684 {
685         if (path == NULL) {
686                 return VCD_ERROR_INVALID_PARAMETER;
687         }
688
689         SLOG(LOG_INFO, TAG_VCD, "[Recorder] set pcm path : %s", path);
690         if (NULL != g_pcm_path) {
691                 free(g_pcm_path);
692                 g_pcm_path = NULL;
693         }
694
695         g_pcm_path = strdup(path);
696         return VCD_ERROR_NONE;
697 }