Remove to send BT RC command
[platform/core/uifw/stt.git] / server / sttd_recorder.c
1 /*
2 *  Copyright (c) 2011-2016 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 #include <sound_manager_internal.h>
24 #ifdef TV_BT_MODE
25 #include <bluetooth_product.h>
26 #endif
27
28 #include "stt_defs.h"
29 #include "sttd_dbus.h"
30 #include "sttd_recorder.h"
31 #include "sttd_main.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                     uid;
47         audio_in_h              audio_h;
48         stte_audio_type_e       audio_type;
49 } stt_recorder_s;
50
51 static stt_recorder_s* g_recorder = NULL;
52
53 static stt_recorder_audio_cb    g_audio_cb;
54
55 static sound_stream_info_h      g_stream_info_h;
56
57 static stt_recorder_interrupt_cb        g_interrupt_cb;
58
59 static sttd_recorder_state      g_recorder_state = STTD_RECORDER_STATE_NONE;
60
61 static int g_buffer_count;
62
63 static int g_stream_focus_id;
64
65 /* Sound buf save for test */
66 /*
67 #define BUF_SAVE_MODE
68 */
69 #ifdef BUF_SAVE_MODE
70 static char g_temp_file_name[128] = {'\0',};
71
72 static FILE* g_pFile;
73
74 static int g_count = 1;
75 #endif
76
77 #ifdef TV_BT_MODE
78 static float get_volume_decibel(char* data, int size, stte_audio_type_e type);
79
80 //static stt_recorder_s* __get_recorder(int engine_id);
81
82 #define SMART_CONTROL_EXTEND_CMD        0x03
83 #define SMART_CONTROL_START_CMD         0x04
84
85 static void _bt_cb_hid_state_changed(int result, bool connected, const char *remote_address, void *user_data)
86 {
87         SLOG(LOG_DEBUG, TAG_STTD, "[Recorder] Bluetooth Event [%d] Received address [%s]", result, remote_address);
88 }
89
90 static void _bt_hid_audio_data_receive_cb(bt_hid_voice_data_s *voice_data, void *user_data)
91 {
92         if (STTD_RECORDER_STATE_RECORDING != g_recorder_state) {
93                 /* SLOG(LOG_DEBUG, TAG_STTD, "[Recorder] Exit audio reading normal func"); */
94                 return;
95         }
96
97         if (NULL != g_audio_cb) {
98                 if (0 != g_audio_cb((void*)voice_data->audio_buf, (unsigned int)voice_data->length)) {
99                         SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Fail to read audio");
100                         sttd_recorder_stop();
101                 }
102
103                 if (NULL == g_recorder) {
104                         return;
105                 }
106
107                 float vol_db = get_volume_decibel((char*)voice_data->audio_buf, (int)voice_data->length, g_recorder->audio_type);
108                 if (0 != sttdc_send_set_volume(g_recorder->uid, vol_db)) {
109                         SLOG(LOG_ERROR, TAG_STTD, "[Recorder] Fail to send recording volume(%f)", vol_db);
110                 }
111         }
112
113         if (0 == g_buffer_count || 0 == g_buffer_count % 50) {
114                 SLOG(LOG_WARN, TAG_STTD, "[Recorder][%d] Recording... : read_size(%d)", g_buffer_count, voice_data->length);
115
116                 if (100000 == g_buffer_count) {
117                         g_buffer_count = 0;
118                 }
119         }
120
121         g_buffer_count++;
122
123 #ifdef BUF_SAVE_MODE
124         /* write pcm buffer */
125         fwrite(data, 1, len, g_pFile);
126 #endif
127         return;
128 }
129 #endif
130
131
132 const char* __stt_get_focus_changed_reason_code(sound_stream_focus_change_reason_e reason)
133 {
134         switch (reason) {
135         case SOUND_STREAM_FOCUS_CHANGED_BY_MEDIA:                       return "SOUND_STREAM_FOCUS_CHANGED_BY_MEDIA";
136         case SOUND_STREAM_FOCUS_CHANGED_BY_SYSTEM:                      return "SOUND_STREAM_FOCUS_CHANGED_BY_SYSTEM";
137         case SOUND_STREAM_FOCUS_CHANGED_BY_ALARM:                       return "SOUND_STREAM_FOCUS_CHANGED_BY_ALARM";
138         case SOUND_STREAM_FOCUS_CHANGED_BY_NOTIFICATION:        return "SOUND_STREAM_FOCUS_CHANGED_BY_NOTIFICATION";
139         case SOUND_STREAM_FOCUS_CHANGED_BY_EMERGENCY:           return "SOUND_STREAM_FOCUS_CHANGED_BY_EMERGENCY";
140         case SOUND_STREAM_FOCUS_CHANGED_BY_VOICE_INFORMATION:   return "SOUND_STREAM_FOCUS_CHANGED_BY_VOICE_INFORMATION";
141         case SOUND_STREAM_FOCUS_CHANGED_BY_VOICE_RECOGNITION:   return "SOUND_STREAM_FOCUS_CHANGED_BY_VOICE_RECOGNITION";
142         case SOUND_STREAM_FOCUS_CHANGED_BY_RINGTONE:            return "SOUND_STREAM_FOCUS_CHANGED_BY_RINGTONE";
143         case SOUND_STREAM_FOCUS_CHANGED_BY_VOIP:                        return "SOUND_STREAM_FOCUS_CHANGED_BY_VOIP";
144         case SOUND_STREAM_FOCUS_CHANGED_BY_CALL:                        return "SOUND_STREAM_FOCUS_CHANGED_BY_CALL";
145         case SOUND_STREAM_FOCUS_CHANGED_BY_MEDIA_EXTERNAL_ONLY: return "SOUND_STREAM_FOCUS_CHANGED_BY_MEDIA_EXTERNAL_ONLY";
146         default:                                                                                        return "Undefined reason code";
147         }
148 }
149
150 void __recorder_focus_state_watch_cb(int id, sound_stream_focus_mask_e focus_mask, sound_stream_focus_state_e focus_state, 
151                                                 sound_stream_focus_change_reason_e reason, const char *extra_info, void *user_data)
152 {
153         SLOG(LOG_WARN, TAG_STTD, "[Recorder] focus_state_watch_cb is called, focus_state(%d), reason(%s)", (int)focus_state, __stt_get_focus_changed_reason_code(reason));
154
155         if (STTD_RECORDER_STATE_RECORDING == g_recorder_state && SOUND_STREAM_FOCUS_STATE_ACQUIRED == focus_state) {
156                 SLOG(LOG_WARN, TAG_STTD, "[Recorder] Focus released as interrupt");
157                 if (NULL != g_interrupt_cb) {
158                         g_interrupt_cb();
159                 }
160         }
161 }
162
163 int sttd_recorder_initialize(stt_recorder_audio_cb audio_cb, stt_recorder_interrupt_cb interrupt_cb)
164 {
165         if (NULL == audio_cb || NULL == interrupt_cb) {
166                 SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Input param is NOT valid");
167                 return STTD_ERROR_INVALID_PARAMETER;
168         }
169
170         if (STTD_RECORDER_STATE_NONE != g_recorder_state) {
171                 SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Current state of recorder is recording");
172                 return STTD_ERROR_INVALID_STATE;
173         }
174
175         if (0 != pthread_mutex_init(&sttd_audio_in_handle_mutex, NULL)) {
176                 SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Fail to initialize audio in handle mutex.");
177         }
178
179         g_audio_cb = audio_cb;
180         g_interrupt_cb = interrupt_cb;
181         g_recorder_state = STTD_RECORDER_STATE_NONE;
182         g_recorder = NULL;
183
184         if (0 != sound_manager_create_stream_information_internal(SOUND_STREAM_TYPE_VOICE_RECOGNITION_SERVICE, NULL, NULL, &g_stream_info_h)) {
185                 SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Fail to create stream info");
186         }
187
188         if (0 != sound_manager_add_focus_state_watch_cb(SOUND_STREAM_FOCUS_FOR_BOTH, __recorder_focus_state_watch_cb, NULL, &g_stream_focus_id)) {
189                 SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Fail to add focus state watch callback");
190         }
191
192 #ifdef TV_BT_MODE
193         if (BT_ERROR_NONE != bt_product_init()) {
194                 SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Fail to init bt");
195                 return STTD_ERROR_OPERATION_FAILED;
196         }
197
198         if (BT_ERROR_NONE != bt_hid_host_initialize(_bt_cb_hid_state_changed, NULL)) {
199                 SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Fail bt_hid_host_initialize()");
200                 return STTD_ERROR_OPERATION_FAILED;
201         }
202 #endif
203
204         return 0;
205 }
206
207 int sttd_recorder_deinitialize()
208 {
209         if (0 != pthread_mutex_destroy(&sttd_audio_in_handle_mutex)) {
210                 SLOG(LOG_ERROR, TAG_STTD, "[Server ERROR] Fail to destroy audio in handle mutex.");
211         }
212
213         if (0 != sound_manager_remove_focus_state_watch_cb(g_stream_focus_id)) {
214                 SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Fail to remove focus state watch callback");
215         }
216
217         if (0 != sound_manager_destroy_stream_information(g_stream_info_h)) {
218                 SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Fail to destroy stream info");
219         }
220
221         if (NULL != g_recorder) {
222                 audio_in_destroy(g_recorder->audio_h);
223                 g_recorder->audio_h = NULL;
224                 free(g_recorder);
225                 g_recorder = NULL;
226         }
227
228 #ifdef __UNUSED_CODES__
229         /* Remove all recorder */
230         GSList *iter = NULL;
231         stt_recorder_s *recorder = NULL;
232
233         iter = g_slist_nth(g_recorder_list, 0);
234
235         while (NULL != iter) {
236                 recorder = iter->data;
237
238                 if (NULL != recorder) {
239                         g_recorder_list = g_slist_remove(g_recorder_list, recorder);
240                         if (recorder->audio_h) {
241                                 audio_in_destroy(recorder->audio_h);
242                                 recorder->audio_h = NULL;
243                         }
244                         free(recorder);
245                 }
246
247                 iter = g_slist_nth(g_recorder_list, 0);
248         }
249 #endif
250
251 #ifdef TV_BT_MODE
252         bt_hid_host_deinitialize();
253
254         bt_product_deinit();
255 #endif
256
257         g_recorder_state = STTD_RECORDER_STATE_NONE;
258
259         return 0;
260 }
261
262 int sttd_recorder_set_audio_session()
263 {
264         return 0;
265 }
266
267 int sttd_recorder_unset_audio_session()
268 {
269         return 0;
270 }
271
272 int sttd_recorder_create(stte_audio_type_e type, int channel, unsigned int sample_rate)
273 {
274         /* Check engine id is valid */
275         if (NULL != g_recorder) {
276                 SLOG(LOG_WARN, TAG_STTD, "[Recorder WARNING] Engine id is already registered");
277                 return STTD_ERROR_INVALID_PARAMETER;
278         }
279
280         audio_in_h temp_in_h = NULL;
281
282 #ifndef TV_BT_MODE
283         audio_channel_e audio_ch;
284         audio_sample_type_e audio_type;
285
286         switch (channel) {
287         case 1: audio_ch = AUDIO_CHANNEL_MONO;          break;
288         case 2: audio_ch = AUDIO_CHANNEL_STEREO;        break;
289         default:
290                 SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Input channel is not supported");
291                 return STTD_ERROR_OPERATION_FAILED;
292                 break;
293         }
294
295         switch (type) {
296         case STTE_AUDIO_TYPE_PCM_S16_LE:        audio_type = AUDIO_SAMPLE_TYPE_S16_LE;  break;
297         case STTE_AUDIO_TYPE_PCM_U8:            audio_type = AUDIO_SAMPLE_TYPE_U8;      break;
298         default:
299                 SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Invalid Audio Type");
300                 return STTD_ERROR_OPERATION_FAILED;
301                 break;
302         }
303
304         int ret;
305         ret = audio_in_create(sample_rate, audio_ch, audio_type, &temp_in_h);
306         if (AUDIO_IO_ERROR_NONE != ret) {
307                 SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Fail to create audio handle : %d", ret);
308                 return STTD_ERROR_OPERATION_FAILED;
309         }
310 #else
311         if (BT_ERROR_NONE != bt_hid_set_audio_data_receive_cb(_bt_hid_audio_data_receive_cb, NULL)) {
312                 SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Fail bt_hid_set_audio_data_receive_cb()");
313                 return STTD_ERROR_OPERATION_FAILED;
314         }
315 #endif
316
317         stt_recorder_s* recorder;
318         recorder = (stt_recorder_s*)calloc(1, sizeof(stt_recorder_s));
319         if (NULL == recorder) {
320 #ifndef TV_BT_MODE
321                 if (temp_in_h) {
322                         audio_in_destroy(temp_in_h);
323                         temp_in_h = NULL;
324                 }
325 #endif
326                 SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Fail to allocate memory");
327                 return STTD_ERROR_OUT_OF_MEMORY;
328         }
329
330         recorder->uid = -1;
331         recorder->audio_h = temp_in_h;
332         recorder->audio_type = type;
333
334         g_recorder = recorder;
335
336         g_recorder_state = STTD_RECORDER_STATE_READY;
337
338         return 0;
339 }
340
341 int sttd_recorder_destroy()
342 {
343         // critical section required because this function can be called from stt engine thread context
344         SLOG(LOG_WARN, TAG_STTD, "[Recorder WARNING] Enter critical section");
345         pthread_mutex_lock(&sttd_audio_in_handle_mutex);
346
347         /* Check engine id is valid */
348         if (NULL == g_recorder) {
349                 SLOG(LOG_WARN, TAG_STTD, "[Recorder WARNING] Engine id is not valid");
350                 pthread_mutex_unlock(&sttd_audio_in_handle_mutex);
351                 return STTD_ERROR_INVALID_PARAMETER;
352         }
353
354 #ifndef TV_BT_MODE
355         int ret;
356         if (STTD_RECORDER_STATE_RECORDING == g_recorder_state) {
357                 if (g_recorder->audio_h) {
358                         ret = audio_in_unprepare(g_recorder->audio_h);
359                         if (AUDIO_IO_ERROR_NONE != ret) {
360                                 SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Fail to unprepare audioin : %d", ret);
361                         }
362                 }
363
364                 g_recorder_state = STTD_RECORDER_STATE_READY;
365         }
366
367         if (g_recorder->audio_h) {
368                 ret = audio_in_destroy(g_recorder->audio_h);
369                 if (AUDIO_IO_ERROR_NONE != ret) {
370                         SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Fail to destroy audioin : %d", ret);
371                 }
372                 g_recorder->audio_h = NULL;
373         }
374
375 #else
376         if (STTD_RECORDER_STATE_RECORDING == g_recorder_state) {
377                 g_recorder_state = STTD_RECORDER_STATE_READY;
378         }
379
380         bt_hid_unset_audio_data_receive_cb();
381 #endif
382
383         free(g_recorder);
384         g_recorder = NULL;
385
386         pthread_mutex_unlock(&sttd_audio_in_handle_mutex);
387         SLOG(LOG_WARN, TAG_STTD, "[Recorder WARNING] Leave critical section");
388
389         return 0;
390 }
391
392 static float get_volume_decibel(char* data, int size, stte_audio_type_e type)
393 {
394         #define MAX_AMPLITUDE_MEAN_16   32768
395         #define MAX_AMPLITUDE_MEAN_08   128
396
397         int i, depthByte;
398         int count = 0;
399
400         float db = 0.0;
401         float rms = 0.0;
402         unsigned long long square_sum = 0;
403
404         if (type == STTE_AUDIO_TYPE_PCM_S16_LE)
405                 depthByte = 2;
406         else
407                 depthByte = 1;
408
409         for (i = 0; i < size; i += (depthByte<<1)) {
410                 if (depthByte == 2) {
411                         short pcm16 = 0;
412                         memcpy(&pcm16, data + i, sizeof(short));
413                         square_sum += pcm16 * pcm16;
414                 } else {
415                         char pcm8 = 0;
416                         memcpy(&pcm8, data + i, sizeof(char));
417                         square_sum += pcm8 * pcm8;
418                 }
419                 count++;
420         }
421
422         if (0 == count)
423                 rms = 0.0;
424         else
425                 rms = sqrt((double)square_sum/count);
426
427         if (depthByte == 2)
428                 db = 20 * log10(rms/MAX_AMPLITUDE_MEAN_16);
429         else
430                 db = 20 * log10(rms/MAX_AMPLITUDE_MEAN_08);
431
432         return db;
433 }
434
435 #ifndef TV_BT_MODE
436 Eina_Bool __read_audio_func(void *data)
437 {
438         int read_byte = -1;
439         static char g_buffer[BUFFER_LENGTH];
440
441         /* Check engine id is valid */
442         if (NULL == g_recorder) {
443                 return EINA_FALSE;
444         }
445
446         if (STTD_RECORDER_STATE_READY == g_recorder_state) {
447                 SLOG(LOG_DEBUG, TAG_STTD, "[Recorder] Exit audio reading func");
448                 return EINA_FALSE;
449         }
450
451         read_byte = audio_in_read(g_recorder->audio_h, g_buffer, BUFFER_LENGTH);
452         if (0 > read_byte) {
453                 SLOG(LOG_WARN, TAG_STTD, "[Recorder WARNING] Fail to read audio : %d", read_byte);
454                 g_recorder_state = STTD_RECORDER_STATE_READY;
455                 return EINA_FALSE;
456         }
457
458         if (0 != g_audio_cb(g_buffer, read_byte)) {
459                 SLOG(LOG_WARN, TAG_STTD, "[Recorder WARNING] Fail audio callback");
460                 sttd_recorder_stop();
461                 return EINA_FALSE;
462         }
463
464         if (0 == g_buffer_count % 30) {
465                 float vol_db = get_volume_decibel(g_buffer, BUFFER_LENGTH, g_recorder->audio_type);
466                 if (0 != sttdc_send_set_volume(g_recorder->uid, vol_db)) {
467                         SLOG(LOG_ERROR, TAG_STTD, "[Recorder] Fail to send recording volume(%f)", vol_db);
468                 }
469         }
470
471         /* Audio read log */
472         if (0 == g_buffer_count % 50) {
473                 SLOG(LOG_DEBUG, TAG_STTD, "[Recorder][%d] Recording... : read_size(%d)", g_buffer_count, read_byte);
474
475                 if (100000 == g_buffer_count) {
476                         g_buffer_count = 0;
477                 }
478         }
479
480         g_buffer_count++;
481
482 #ifdef BUF_SAVE_MODE
483         /* write pcm buffer */
484         fwrite(g_buffer, 1, BUFFER_LENGTH, g_pFile);
485 #endif
486
487         return EINA_TRUE;
488 }
489 #endif
490
491 int sttd_recorder_start(int uid)
492 {
493         if (STTD_RECORDER_STATE_RECORDING == g_recorder_state)
494                 return 0;
495
496 #ifndef TV_BT_MODE
497         int ret = -1;
498         /* Check engine id is valid */
499         if (NULL == g_recorder) {
500                 SLOG(LOG_WARN, TAG_STTD, "[Recorder WARNING] Engine id is not valid");
501                 return STTD_ERROR_INVALID_PARAMETER;
502         }
503
504         ret = audio_in_set_sound_stream_info(g_recorder->audio_h, g_stream_info_h);
505         if (AUDIO_IO_ERROR_NONE != ret) {
506                 SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Fail to set stream info");
507         }
508
509         ret = audio_in_prepare(g_recorder->audio_h);
510         if (AUDIO_IO_ERROR_NONE != ret) {
511                 SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Fail to start audio : %d", ret);
512                 return STTD_ERROR_RECORDER_BUSY;
513         }
514
515         /* Add ecore timer to read audio data */
516         ecore_timer_add(0, __read_audio_func, NULL);
517 #endif
518
519         g_recorder_state = STTD_RECORDER_STATE_RECORDING;
520         g_recorder->uid = uid;
521
522         g_buffer_count = 0;
523
524 #ifdef BUF_SAVE_MODE
525         g_count++;
526
527         while (1) {
528                 snprintf(g_temp_file_name, sizeof(g_temp_file_name), "/tmp/stt_temp_%d_%d", getpid(), g_count);
529                 ret = access(g_temp_file_name, 0);
530
531                 if (0 == ret) {
532                         SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] File is already exist");
533                         if (0 == remove(g_temp_file_name)) {
534                                 SLOG(LOG_DEBUG, TAG_STTD, "[Recorder] Remove file");
535                                 break;
536                         } else {
537                                 g_count++;
538                         }
539                 } else {
540                         break;
541                 }
542         }
543
544         SECURE_SLOG(LOG_DEBUG, TAG_STTD, "[Recorder] Temp file name=[%s]", g_temp_file_name);
545
546         /* open test file */
547         g_pFile = fopen(g_temp_file_name, "wb+x");
548         if (!g_pFile) {
549                 SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] File not found!");
550                 return -1;
551         }
552 #endif
553
554         return 0;
555 }
556
557 int sttd_recorder_stop()
558 {
559         if (STTD_RECORDER_STATE_READY == g_recorder_state)
560                 return 0;
561
562         // critical section required because this function can be called from stt engine thread context
563         SLOG(LOG_WARN, TAG_STTD, "[Recorder WARNING] Enter critical section");
564         pthread_mutex_lock(&sttd_audio_in_handle_mutex);
565
566         /* Check engine id is valid */
567         if (NULL == g_recorder) {
568                 SLOG(LOG_WARN, TAG_STTD, "[Recorder WARNING] Engine id is not valid");
569                 pthread_mutex_unlock(&sttd_audio_in_handle_mutex);
570                 return STTD_ERROR_INVALID_PARAMETER;
571         }
572
573         g_recorder->uid = -1;
574
575         int ret = -1;
576 #ifndef TV_BT_MODE
577         ret = audio_in_unprepare(g_recorder->audio_h);
578         if (AUDIO_IO_ERROR_NONE != ret) {
579                 SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Fail to unprepare audioin : %d", ret);
580         }
581 #else
582         int bt_retry = 0;
583         bool stopped = false;
584         while (5 > bt_retry) {
585                 ret = bt_hid_rc_stop_sending_voice(NULL);
586                 if (BT_ERROR_NONE == ret) {
587                         SLOG(LOG_DEBUG, TAG_STTD, "[Recorder] Stop bt audio");
588                         stopped = true;
589                         break;
590                 } else if (BT_ERROR_NOW_IN_PROGRESS == ret) {
591                         SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Fail bt_hid_rc_stop_sending_voice()");
592                         usleep(50000);
593                         bt_retry++;
594                 } else {
595                         SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] bt_hid_rc_stop_sending_voice(): ret(%d)", ret);
596                         break;
597                 }
598         }
599         if (false == stopped) {
600                 SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Fail to stop bt audio(%d)", ret);
601 //              return STTD_ERROR_OPERATION_FAILED;
602         }
603 #endif
604
605         g_recorder_state = STTD_RECORDER_STATE_READY;
606
607 #ifdef BUF_SAVE_MODE
608         fclose(g_pFile);
609 #endif
610         pthread_mutex_unlock(&sttd_audio_in_handle_mutex);
611         SLOG(LOG_WARN, TAG_STTD, "[Recorder WARNING] Leave critical section");
612
613         return 0;
614 }
615
616 int sttd_recorder_start_file(int uid, const char *filepath)
617 {
618         if (STTD_RECORDER_STATE_RECORDING == g_recorder_state)
619                 return 0;
620
621         /* Check engine id is valid */
622         if (NULL == g_recorder) {
623                 SLOG(LOG_WARN, TAG_STTD, "[Recorder WARNING] Engine id is not valid");
624                 return STTD_ERROR_INVALID_PARAMETER;
625         }
626         g_recorder_state = STTD_RECORDER_STATE_RECORDING;
627         g_recorder->uid = uid;
628
629         int cnt = 0;
630         int totalReadBytes = 0;
631
632         FILE *infile = fopen(filepath, "rb");
633
634         //process the file
635         if (infile != NULL) {
636                 while (!feof(infile)) {
637                         static char pcm_buff[BUFFER_LENGTH];
638                         int read_byte = fread(pcm_buff, 1, BUFFER_LENGTH, infile);
639                         totalReadBytes += read_byte;
640                         if (0 != read_byte) {
641                                 if (0 != g_audio_cb(pcm_buff, read_byte)) {
642                                         SLOG(LOG_ERROR, TAG_STTD, "[Recorder ERROR] Fail to call audio callback");
643                                         fclose(infile);
644                                         return -1;
645                                 }
646                                 if (0 == cnt % 30) {
647                                         float vol_db = get_volume_decibel(pcm_buff, BUFFER_LENGTH, g_recorder->audio_type);
648                                         if (0 != sttdc_send_set_volume(g_recorder->uid, vol_db)) {
649                                                 SLOG(LOG_ERROR, TAG_STTD, "[Recorder] Fail to send recording volume(%f)", vol_db);
650                                         }
651                                 }
652
653                                 /* Audio read log */
654                                 if (0 == cnt % 50)
655                                         SLOG(LOG_DEBUG, TAG_STTD, "[Recorder][%d] Recording... : read_size(%d)", cnt, read_byte);
656                                 cnt++;
657                         }
658                 }
659                 fclose(infile);
660         }
661
662         SLOG(LOG_DEBUG, TAG_STTD, "[Recorder][%d] total bytes(%d)", cnt, totalReadBytes);
663         return 0;
664 }
665
666 int sttd_recorder_stop_file()
667 {
668         if (STTD_RECORDER_STATE_READY == g_recorder_state)
669                 return 0;
670
671         /* Check engine id is valid */
672         if (NULL == g_recorder) {
673                 SLOG(LOG_WARN, TAG_STTD, "[Recorder WARNING] Engine id is not valid");
674                 return STTD_ERROR_INVALID_PARAMETER;
675         }
676
677         g_recorder->uid = -1;
678         g_recorder_state = STTD_RECORDER_STATE_READY;
679
680         return 0;
681 }
682
683 int sttd_recorder_clear()
684 {
685 #ifdef TV_BT_MODE
686         SLOG(LOG_DEBUG, TAG_STTD, "[Recorder DEBUG] Clear recorder on TV");
687
688         if (STTD_RECORDER_STATE_RECORDING == g_recorder_state) {
689                 sttd_recorder_stop();
690         }
691         if (STTD_RECORDER_STATE_READY == g_recorder_state) {
692                 sttd_recorder_destroy();
693         }
694 #endif
695
696         return STTD_ERROR_NONE;
697 }