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