add codes to support various audio input on one branch
[platform/core/uifw/stt.git] / server / sttd_recorder.c
1 /*
2 *  Copyright (c) 2011-2014 Samsung Electronics Co., Ltd All Rights Reserved
3 *  Licensed under the Apache License, Version 2.0 (the "License");
4 *  you may not use this file except in compliance with the License.
5 *  You may obtain a copy of the License at
6 *  http://www.apache.org/licenses/LICENSE-2.0
7 *  Unless required by applicable law or agreed to in writing, software
8 *  distributed under the License is distributed on an "AS IS" BASIS,
9 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 *  See the License for the specific language governing permissions and
11 *  limitations under the License.
12 */
13
14 #ifdef TV_PRODUCT
15 #define TV_BT_MODE
16 #endif
17
18 #include <audio_io.h>
19 #include <Ecore.h>
20 #include <math.h>
21 #include <pthread.h>
22 #include <sound_manager.h>
23 #ifdef TV_BT_MODE
24 #include <bluetooth.h>
25 #endif
26
27 #include "stt_defs.h"
28 #include "sttd_dbus.h"
29 #include "sttd_recorder.h"
30 #include "sttd_main.h"
31 #include "sttp.h"
32
33
34 #define FRAME_LENGTH 160
35 #define BUFFER_LENGTH FRAME_LENGTH * 2
36
37 static pthread_mutex_t sttd_audio_in_handle_mutex = PTHREAD_MUTEX_INITIALIZER;
38
39 typedef enum {
40         STTD_RECORDER_STATE_NONE = -1,
41         STTD_RECORDER_STATE_READY = 0,  /**< Recorder is ready to start */
42         STTD_RECORDER_STATE_RECORDING   /**< In the middle of recording */
43 } sttd_recorder_state;
44
45 typedef struct {
46         int                     engine_id;
47         int                     uid;
48         audio_in_h              audio_h;
49         sttp_audio_type_e       audio_type;
50 } stt_recorder_s;
51
52 static GSList *g_recorder_list;
53
54 static int g_recording_engine_id;
55
56 static stt_recorder_audio_cb    g_audio_cb;
57
58 static sound_stream_info_h      g_stream_info_h;
59
60 static stt_recorder_interrupt_cb        g_interrupt_cb;
61
62 static sttd_recorder_state      g_recorder_state = STTD_RECORDER_STATE_NONE;
63
64 static int g_buffer_count;
65
66 /* Sound buf save for test */
67 /*
68 #define BUF_SAVE_MODE
69 */
70 #ifdef BUF_SAVE_MODE
71 static char g_temp_file_name[128] = {'\0',};
72
73 static FILE* g_pFile;
74
75 static int g_count = 1;
76 #endif
77
78 #ifdef TV_BT_MODE
79 static float get_volume_decibel(char* data, int size, sttp_audio_type_e type);
80
81 static stt_recorder_s* __get_recorder(int engine_id);
82
83 static int g_bt_extend_count;
84
85 #define SMART_CONTROL_EXTEND_CMD        0x03
86 #define SMART_CONTROL_START_CMD         0x04
87
88 static void _bt_cb_hid_state_changed(int result, bool connected, const char *remote_address, void *user_data)
89 {
90         SLOG(LOG_DEBUG, TAG_STTD, "[Recorder] Bluetooth Event [%d] Received address [%s]", result, remote_address);
91 }
92
93 static void _bt_hid_audio_data_receive_cb(bt_hid_voice_data_s *voice_data, void *user_data)
94 {
95         if (STTD_RECORDER_STATE_RECORDING != g_recorder_state) {
96                 /* SLOG(LOG_DEBUG, TAG_STTD, "[Recorder] Exit audio reading normal func"); */
97                 return;
98         }
99
100         if (NULL != g_audio_cb) {
101                 if (0 != g_audio_cb((void*)voice_data->audio_buf, (unsigned int)voice_data->length)) {
102                         SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Fail to read audio");
103                         sttd_recorder_stop(g_recording_engine_id);
104                 }
105
106                 stt_recorder_s* recorder;
107                 recorder = __get_recorder(g_recording_engine_id);
108                 if (NULL == recorder) {
109                         return;
110                 }
111
112                 float vol_db = get_volume_decibel((char*)voice_data->audio_buf, (int)voice_data->length, recorder->audio_type);
113                 if (0 != sttdc_send_set_volume(recorder->uid, vol_db)) {
114                         SLOG(LOG_ERROR, TAG_STTD, "[Recorder] Fail to send recording volume(%f)", vol_db);
115                 }
116         }
117         
118         if (0 == g_buffer_count || 0 == g_buffer_count % 50) {
119                 SLOG(LOG_WARN, TAG_STTD, "[Recorder][%d] Recording... : read_size(%d)", g_buffer_count, voice_data->length);
120
121                 if (0 == g_bt_extend_count % 5 && 0 != g_buffer_count) {
122                         const unsigned char input_data[2] = {SMART_CONTROL_EXTEND_CMD, 0x10 };
123                         if (BT_ERROR_NONE != bt_hid_send_rc_command(NULL, input_data, sizeof(input_data))) {
124                                 SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Fail bt_hid_send_rc_command(NULL, %s, %d)", input_data, sizeof(input_data));
125                         } else {
126                                 SLOG(LOG_DEBUG, TAG_STTD, "[Recorder] Extend bt audio recorder");
127                         }
128                 }
129                 g_bt_extend_count++;
130                 
131                 if (100000 == g_buffer_count) {
132                         g_buffer_count = 0;
133                 }
134         }
135
136         g_buffer_count++;
137
138 #ifdef BUF_SAVE_MODE
139         /* write pcm buffer */
140         fwrite(data, 1, len, g_pFile);
141 #endif
142         return;
143 }
144 #endif
145
146
147 const char* __stt_get_focus_changed_reason_code(sound_stream_focus_change_reason_e reason)
148 {
149         switch (reason) {
150         case SOUND_STREAM_FOCUS_CHANGED_BY_MEDIA:                       return "SOUND_STREAM_FOCUS_CHANGED_BY_MEDIA";
151         case SOUND_STREAM_FOCUS_CHANGED_BY_SYSTEM:                      return "SOUND_STREAM_FOCUS_CHANGED_BY_SYSTEM";
152         case SOUND_STREAM_FOCUS_CHANGED_BY_ALARM:                       return "SOUND_STREAM_FOCUS_CHANGED_BY_ALARM";
153         case SOUND_STREAM_FOCUS_CHANGED_BY_NOTIFICATION:        return "SOUND_STREAM_FOCUS_CHANGED_BY_NOTIFICATION";
154         case SOUND_STREAM_FOCUS_CHANGED_BY_EMERGENCY:           return "SOUND_STREAM_FOCUS_CHANGED_BY_EMERGENCY";
155         case SOUND_STREAM_FOCUS_CHANGED_BY_VOICE_INFORMATION:   return "SOUND_STREAM_FOCUS_CHANGED_BY_VOICE_INFORMATION";
156         case SOUND_STREAM_FOCUS_CHANGED_BY_VOICE_RECOGNITION:   return "SOUND_STREAM_FOCUS_CHANGED_BY_VOICE_RECOGNITION";
157         case SOUND_STREAM_FOCUS_CHANGED_BY_RINGTONE:            return "SOUND_STREAM_FOCUS_CHANGED_BY_RINGTONE";
158         case SOUND_STREAM_FOCUS_CHANGED_BY_VOIP:                        return "SOUND_STREAM_FOCUS_CHANGED_BY_VOIP";
159         case SOUND_STREAM_FOCUS_CHANGED_BY_CALL:                        return "SOUND_STREAM_FOCUS_CHANGED_BY_CALL";
160         case SOUND_STREAM_FOCUS_CHANGED_BY_MEDIA_EXTERNAL_ONLY: return "SOUND_STREAM_FOCUS_CHANGED_BY_MEDIA_EXTERNAL_ONLY";
161         default:                                                                                        return "Undefined reason code";
162         }
163 }
164
165 void __recorder_focus_state_cb(sound_stream_info_h stream_info, sound_stream_focus_change_reason_e reason, const char *extra_info, void *user_data)
166 {
167         SLOG(LOG_DEBUG, TAG_STTD, "[Recorder] Focus state changed cb");
168
169         if (stream_info != g_stream_info_h) {
170                 SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Invalid stream info handle");
171                 return;
172         }
173
174         int ret;
175         sound_stream_focus_state_e state_for_recording;
176         ret = sound_manager_get_focus_state(g_stream_info_h, NULL, &state_for_recording);
177         if (SOUND_MANAGER_ERROR_NONE != ret) {
178                 SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Fail to get focus state");
179                 return;
180         }
181
182         SLOG(LOG_WARN, TAG_STTD, "[Recorder] focus state changed to (%d) with reason(%s)", (int)state_for_recording, __stt_get_focus_changed_reason_code(reason));
183         
184         if (STTD_RECORDER_STATE_RECORDING == g_recorder_state && SOUND_STREAM_FOCUS_STATE_RELEASED == state_for_recording) {
185                 SLOG(LOG_WARN, TAG_STTD, "[Recorder] Focus released as interrupt");
186                 if (NULL != g_interrupt_cb) {
187                         g_interrupt_cb();
188                 }
189         }
190 }
191
192
193 int sttd_recorder_initialize(stt_recorder_audio_cb audio_cb, stt_recorder_interrupt_cb interrupt_cb)
194 {
195         if (NULL == audio_cb || NULL == interrupt_cb) {
196                 SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Input param is NOT valid");
197                 return STTD_ERROR_INVALID_PARAMETER;
198         }
199
200         if (STTD_RECORDER_STATE_NONE != g_recorder_state) {
201                 SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Current state of recorder is recording");
202                 return STTD_ERROR_INVALID_STATE;
203         }
204
205         if (0 != pthread_mutex_init(&sttd_audio_in_handle_mutex, NULL)) {
206                 SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Fail to initialize audio in handle mutex.");
207         }
208
209         g_audio_cb = audio_cb;
210         g_interrupt_cb = interrupt_cb;
211         g_recorder_state = STTD_RECORDER_STATE_NONE;
212         g_recording_engine_id = -1;
213
214         if (0 != sound_manager_create_stream_information(SOUND_STREAM_TYPE_VOICE_RECOGNITION, __recorder_focus_state_cb, NULL, &g_stream_info_h)) {
215                 SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Fail to create stream info");
216         }
217
218 #ifdef TV_BT_MODE
219         if (BT_ERROR_NONE != bt_initialize()) {
220                 SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Fail to init bt");
221                 return STTD_ERROR_OPERATION_FAILED;
222         }
223
224         if (BT_ERROR_NONE != bt_hid_host_initialize(_bt_cb_hid_state_changed, NULL)) {
225                 SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Fail bt_hid_host_initialize()");
226                 return STTD_ERROR_OPERATION_FAILED;
227         }
228 #endif
229
230         return 0;
231 }
232
233 int sttd_recorder_deinitialize()
234 {
235         if (0 != pthread_mutex_destroy(&sttd_audio_in_handle_mutex)) {
236                 SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Fail to destroy audio in handle mutex.");
237         }
238
239         if (0 != sound_manager_destroy_stream_information(g_stream_info_h)) {
240                 SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Fail to destroy stream info");
241         }
242
243         /* Remove all recorder */
244         GSList *iter = NULL;
245         stt_recorder_s *recorder = NULL;
246
247         iter = g_slist_nth(g_recorder_list, 0);
248
249         while (NULL != iter) {
250                 recorder = iter->data;
251
252                 if (NULL != recorder) {
253                         g_recorder_list = g_slist_remove(g_recorder_list, recorder);
254                         audio_in_destroy(recorder->audio_h);
255
256                         free(recorder);
257                 }
258
259                 iter = g_slist_nth(g_recorder_list, 0);
260         }
261
262 #ifdef TV_BT_MODE
263         bt_hid_host_deinitialize ();
264
265         bt_deinitialize();
266 #endif
267
268         g_recorder_state = STTD_RECORDER_STATE_NONE;
269
270         return 0;
271 }
272
273 static stt_recorder_s* __get_recorder(int engine_id)
274 {
275         GSList *iter = NULL;
276         stt_recorder_s *recorder = NULL;
277
278         iter = g_slist_nth(g_recorder_list, 0);
279
280         while (NULL != iter) {
281                 recorder = iter->data;
282
283                 if (recorder->engine_id == engine_id) {
284                         return recorder;
285                 }
286
287                 iter = g_slist_next(iter);
288         }
289
290         return NULL;
291 }
292
293 int sttd_recorder_set_audio_session()
294 {
295         return 0;
296 }
297
298 int sttd_recorder_unset_audio_session()
299 {
300         return 0;
301 }
302
303 int sttd_recorder_create(int engine_id, int uid, sttp_audio_type_e type, int channel, unsigned int sample_rate)
304 {
305         /* Check engine id is valid */
306         if (NULL != __get_recorder(engine_id)) {
307                 SLOG(LOG_WARN, TAG_STTD, "[Recorder WARNING] Engine id is already registered");
308                 return STTD_ERROR_INVALID_PARAMETER;
309         }
310
311         audio_in_h temp_in_h = NULL;
312
313 #ifndef TV_BT_MODE
314         audio_channel_e audio_ch;
315         audio_sample_type_e audio_type;
316
317         switch (channel) {
318         case 1: audio_ch = AUDIO_CHANNEL_MONO;          break;
319         case 2: audio_ch = AUDIO_CHANNEL_STEREO;        break;
320         default:
321                 SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Input channel is not supported");
322                 return STTD_ERROR_OPERATION_FAILED;
323                 break;
324         }
325
326         switch (type) {
327         case STTP_AUDIO_TYPE_PCM_S16_LE:        audio_type = AUDIO_SAMPLE_TYPE_S16_LE;  break;
328         case STTP_AUDIO_TYPE_PCM_U8:            audio_type = AUDIO_SAMPLE_TYPE_U8;      break;
329         default:
330                 SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Invalid Audio Type");
331                 return STTD_ERROR_OPERATION_FAILED;
332                 break;
333         }
334
335         int ret;
336         ret = audio_in_create(sample_rate, audio_ch, audio_type, &temp_in_h);
337         if (AUDIO_IO_ERROR_NONE != ret) {
338                 SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Fail to create audio handle : %d", ret);
339                 return STTD_ERROR_OPERATION_FAILED;
340         }
341 #else
342         if (BT_ERROR_NONE != bt_hid_set_audio_data_receive_cb(_bt_hid_audio_data_receive_cb, NULL)) {
343                 SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Fail bt_hid_set_audio_data_receive_cb()");
344                 return STTD_ERROR_OPERATION_FAILED;
345         }
346 #endif
347
348         stt_recorder_s* recorder;
349         recorder = (stt_recorder_s*)calloc(1, sizeof(stt_recorder_s));
350         if (NULL == recorder) {
351 #ifndef TV_BT_MODE
352                 audio_in_destroy(temp_in_h);
353 #endif
354                 SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Fail to allocate memory");
355                 return STTD_ERROR_OUT_OF_MEMORY;
356         }
357
358         recorder->engine_id = engine_id;
359         recorder->uid = uid;
360         recorder->audio_h = temp_in_h;
361         recorder->audio_type = type;
362
363         g_recorder_list = g_slist_append(g_recorder_list, recorder);
364
365         g_recorder_state = STTD_RECORDER_STATE_READY;
366
367         return 0;
368 }
369
370 int sttd_recorder_destroy(int engine_id)
371 {
372         // critical section required because this function can be called from stt engine thread context
373         SLOG(LOG_WARN, TAG_STTD, "[Recorder WARNING] Enter critical section");
374         pthread_mutex_lock(&sttd_audio_in_handle_mutex);
375
376         /* Check engine id is valid */
377         stt_recorder_s* recorder;
378         recorder = __get_recorder(engine_id);
379         if (NULL == recorder) {
380                 SLOG(LOG_WARN, TAG_STTD, "[Recorder WARNING] Engine id is not valid");
381                 pthread_mutex_unlock(&sttd_audio_in_handle_mutex);
382                 return STTD_ERROR_INVALID_PARAMETER;
383         }
384
385 #ifndef TV_BT_MODE
386         int ret;
387         if (STTD_RECORDER_STATE_RECORDING == g_recorder_state) {
388                 ret = audio_in_unprepare(recorder->audio_h);
389                 if (AUDIO_IO_ERROR_NONE != ret) {
390                         SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Fail to unprepare audioin : %d", ret);
391                 }
392
393                 g_recorder_state = STTD_RECORDER_STATE_READY;
394         }
395
396         ret = audio_in_destroy(recorder->audio_h);
397         if (AUDIO_IO_ERROR_NONE != ret) {
398                 SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Fail to destroy audioin : %d", ret);
399         }
400 #else 
401         if (STTD_RECORDER_STATE_RECORDING == g_recorder_state) {
402                 g_recorder_state = STTD_RECORDER_STATE_READY;
403         }
404
405         bt_hid_unset_audio_data_receive_cb();
406 #endif
407
408         g_recorder_list = g_slist_remove(g_recorder_list, recorder);
409
410         free(recorder);
411
412         pthread_mutex_unlock(&sttd_audio_in_handle_mutex);
413         SLOG(LOG_WARN, TAG_STTD, "[Recorder WARNING] Leave critical section");
414
415         return 0;
416 }
417
418 static float get_volume_decibel(char* data, int size, sttp_audio_type_e type)
419 {
420         #define MAX_AMPLITUDE_MEAN_16   32768
421         #define MAX_AMPLITUDE_MEAN_08   128
422
423         int i, depthByte;
424         int count = 0;
425
426         float db = 0.0;
427         float rms = 0.0;
428         unsigned long long square_sum = 0;
429
430         if (type == STTP_AUDIO_TYPE_PCM_S16_LE)
431                 depthByte = 2;
432         else
433                 depthByte = 1;
434
435         for (i = 0; i < size; i += (depthByte<<1)) {
436                 if (depthByte == 2) {
437                         short pcm16 = 0;
438                         memcpy(&pcm16, data + i, sizeof(short));
439                         square_sum += pcm16 * pcm16;
440                 } else {
441                         char pcm8 = 0;
442                         memcpy(&pcm8, data + i, sizeof(char));
443                         square_sum += pcm8 * pcm8;
444                 }
445                 count++;
446         }
447
448         if (0 == count)
449                 rms = 0.0;
450         else
451                 rms = sqrt(square_sum/count);
452
453         if (depthByte == 2)
454                 db = 20 * log10(rms/MAX_AMPLITUDE_MEAN_16);
455         else
456                 db = 20 * log10(rms/MAX_AMPLITUDE_MEAN_08);
457
458         return db;
459 }
460
461 #ifndef TV_BT_MODE
462 Eina_Bool __read_audio_func(void *data)
463 {
464         int read_byte = -1;
465         static char g_buffer[BUFFER_LENGTH];
466
467         /* Check engine id is valid */
468         stt_recorder_s* recorder;
469         recorder = __get_recorder(g_recording_engine_id);
470         if (NULL == recorder) {
471                 return EINA_FALSE;
472         }
473
474         if (STTD_RECORDER_STATE_READY == g_recorder_state) {
475                 SLOG(LOG_DEBUG, TAG_STTD, "[Recorder] Exit audio reading func");
476                 return EINA_FALSE;
477         }
478
479         read_byte = audio_in_read(recorder->audio_h, g_buffer, BUFFER_LENGTH);
480         if (0 > read_byte) {
481                 SLOG(LOG_WARN, TAG_STTD, "[Recorder WARNING] Fail to read audio : %d", read_byte);
482                 g_recorder_state = STTD_RECORDER_STATE_READY;
483                 return EINA_FALSE;
484         }
485
486         if (0 != g_audio_cb(g_buffer, read_byte)) {
487                 SLOG(LOG_WARN, TAG_STTD, "[Recorder WARNING] Fail audio callback");
488                 sttd_recorder_stop(g_recording_engine_id);
489                 return EINA_FALSE;
490         }
491
492         if (0 == g_buffer_count % 30) {
493                 float vol_db = get_volume_decibel(g_buffer, BUFFER_LENGTH, recorder->audio_type);
494                 if (0 != sttdc_send_set_volume(recorder->uid, vol_db)) {
495                         SLOG(LOG_ERROR, TAG_STTD, "[Recorder] Fail to send recording volume(%f)", vol_db);
496                 }
497         }
498
499         /* Audio read log */
500         if (0 == g_buffer_count % 50) {
501                 SLOG(LOG_DEBUG, TAG_STTD, "[Recorder][%d] Recording... : read_size(%d)", g_buffer_count, read_byte);
502
503                 if (100000 == g_buffer_count) {
504                         g_buffer_count = 0;
505                 }
506         }
507
508         g_buffer_count++;
509
510 #ifdef BUF_SAVE_MODE
511         /* write pcm buffer */
512         fwrite(g_buffer, 1, BUFFER_LENGTH, g_pFile);
513 #endif
514
515         return EINA_TRUE;
516 }
517 #endif
518
519 int sttd_recorder_start(int engine_id)
520 {
521         if (STTD_RECORDER_STATE_RECORDING == g_recorder_state)
522                 return 0;
523
524         int ret = -1;
525 #ifndef TV_BT_MODE
526         /* Check engine id is valid */
527         stt_recorder_s* recorder;
528         recorder = __get_recorder(engine_id);
529         if (NULL == recorder) {
530                 SLOG(LOG_WARN, TAG_STTD, "[Recorder WARNING] Engine id is not valid");
531                 return STTD_ERROR_INVALID_PARAMETER;
532         }
533
534         ret = sound_manager_acquire_focus(g_stream_info_h, SOUND_STREAM_FOCUS_FOR_RECORDING, NULL);
535         if (SOUND_MANAGER_ERROR_NONE != ret) {
536                 SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Fail to acquire focus : %d", ret);
537         } else {
538                 ret = audio_in_set_stream_info(recorder->audio_h, g_stream_info_h);
539                 if (AUDIO_IO_ERROR_NONE != ret) {
540                         SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Fail to set stream info");
541                 }
542         }
543         
544         ret = audio_in_prepare(recorder->audio_h);
545         if (AUDIO_IO_ERROR_NONE != ret) {
546                 SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Fail to start audio : %d", ret);
547                 return STTD_ERROR_RECORDER_BUSY;
548         }
549
550         /* Add ecore timer to read audio data */
551         ecore_timer_add(0, __read_audio_func, NULL);
552
553 #else
554         g_bt_extend_count = 0;
555         const unsigned char input_data[2] = {SMART_CONTROL_START_CMD, 0x00 };
556         int bt_retry = 0;
557         bool started = false;
558         while (5 > bt_retry) {
559                 ret = bt_hid_send_rc_command(NULL, input_data, sizeof(input_data));
560                 if (BT_ERROR_NONE == ret) {
561                         SLOG(LOG_DEBUG, TAG_STTD, "[Recorder] Start bt audio recorder");
562                         started = true;
563                         break;
564                 } else if (BT_ERROR_NOW_IN_PROGRESS == ret) {
565                         SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Fail bt_hid_send_rc_command(NULL, %s, %d)", input_data, sizeof(input_data));
566                         usleep(50000);
567                         bt_retry++;
568                 } else {
569                         break;
570                 }
571         }
572         if (false == started) {
573                 SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Fail to start bt audio");
574                 return STTD_ERROR_OPERATION_FAILED;
575         }
576 #endif
577         g_recorder_state = STTD_RECORDER_STATE_RECORDING;
578         g_recording_engine_id = engine_id;
579
580         g_buffer_count = 0;
581
582 #ifdef BUF_SAVE_MODE
583         g_count++;
584
585         snprintf(g_temp_file_name, sizeof(g_temp_file_name), "/tmp/stt_temp_%d_%d", getpid(), g_count);
586         SECURE_SLOG(LOG_DEBUG, TAG_STTD, "[Recorder] Temp file name=[%s]", g_temp_file_name);
587
588         /* open test file */
589         g_pFile = fopen(g_temp_file_name, "wb+");
590         if (!g_pFile) {
591                 SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] File not found!");
592                 return -1;
593         }
594 #endif
595
596         return 0;
597 }
598
599 int sttd_recorder_stop(int engine_id)
600 {
601         if (STTD_RECORDER_STATE_READY == g_recorder_state)
602                 return 0;
603
604         /* Check engine id is valid */
605         stt_recorder_s* recorder;
606         recorder = __get_recorder(engine_id);
607         if (NULL == recorder) {
608                 SLOG(LOG_WARN, TAG_STTD, "[Recorder WARNING] Engine id is not valid");
609                 return STTD_ERROR_INVALID_PARAMETER;
610         }
611
612         int ret;
613 #ifndef TV_BT_MODE
614         ret = audio_in_unprepare(recorder->audio_h);
615         if (AUDIO_IO_ERROR_NONE != ret) {
616                 SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Fail to unprepare audioin : %d", ret);
617         }
618 #else 
619         int bt_retry = 0;
620         bool stopped = false;
621         while (5 > bt_retry) {
622                 ret = bt_hid_rc_stop_sending_voice(NULL);
623                 if (BT_ERROR_NONE == ret) {
624                         SLOG(LOG_DEBUG, TAG_STTD, "[Recorder] Stop bt audio");
625                         stopped = true;
626                         break;
627                 } else if (BT_ERROR_NOW_IN_PROGRESS == ret) {
628                         SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Fail bt_hid_rc_stop_sending_voice()");
629                         usleep(50000);
630                         bt_retry++;
631                 } else {
632                         break;
633                 }
634         }
635         if (false == stopped) {
636                 SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Fail to stop bt audio");
637                 return STTD_ERROR_OPERATION_FAILED;
638         }
639 #endif
640
641         g_recorder_state = STTD_RECORDER_STATE_READY;
642         g_recording_engine_id = -1;
643
644         ret = sound_manager_release_focus(g_stream_info_h, SOUND_STREAM_FOCUS_FOR_RECORDING, NULL);
645         if (SOUND_MANAGER_ERROR_NONE != ret) {
646                 SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Fail to release focus :%d", ret);
647         }
648
649 #ifdef BUF_SAVE_MODE
650         fclose(g_pFile);
651 #endif
652
653         return 0;
654 }