2 * Copyright (c) 2011-2015 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #define TV_MSF_WIFI_MODE
24 #include <sound_manager.h>
25 #include <sound_manager_internal.h>
28 #include <bluetooth_product.h>
30 #ifdef TV_MSF_WIFI_MODE
31 #include <MSFVoiceInterface.h>
35 #include "vcd_client_data.h"
36 #include "vcd_config.h"
38 #include "vcd_engine_agent.h"
39 #include "vcd_recorder.h"
41 #include "voice_control_plugin_engine.h"
43 #define FRAME_LENGTH 160
44 #define BUFFER_LENGTH FRAME_LENGTH * 2
46 #define FOCUS_SERVER_READY "/tmp/.focus_server_ready"
48 #define VCP_AUDIO_ID_NONE "VC_AUDIO_ID_NONE" /**< None audio id */
50 static vcd_recorder_state_e g_recorder_state = VCD_RECORDER_STATE_READY;
52 static vcd_recoder_audio_cb g_audio_cb = NULL;
54 static vcd_recorder_interrupt_cb g_interrupt_cb = NULL;
56 static audio_in_h g_audio_h;
59 static sound_stream_info_h g_stream_info_h;
62 static vcp_audio_type_e g_audio_type;
64 static int g_audio_rate;
66 static int g_audio_channel;
68 static char g_normal_buffer[BUFFER_LENGTH + 10];
70 static bool g_is_valid_audio_in = false;
72 static bool g_is_valid_bt_in = false;
74 static char* g_current_audio_type = NULL;
76 static int g_buffer_count;
84 static FILE* g_normal_file;
86 static int g_count = 1;
89 static float get_volume_decibel(char* data, int size);
91 #ifdef TV_MSF_WIFI_MODE
92 static void __msf_wifi_audio_data_receive_cb(msf_wifi_voice_data_s *voice_data, void* user_data)
94 if (0 != strncmp(g_current_audio_type, VCP_AUDIO_ID_MSF, sizeof(VCP_AUDIO_ID_MSF))) {
95 vcd_state_e state = vcd_config_get_service_state();
96 if (VCD_STATE_READY == state) {
97 vcd_recorder_set(VCP_AUDIO_ID_MSF, VCP_AUDIO_TYPE_PCM_S16_LE, 16000, 1);
99 SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] current audio type is (%s)", g_current_audio_type);
104 if (VCD_RECORDER_STATE_RECORDING != g_recorder_state) {
105 SLOG(LOG_WARN, TAG_VCD, "[Recorder] Not start yet, but send audio data vi MSF");
106 vcd_recorder_start();
109 if (NULL != g_audio_cb) {
110 if (0 != g_audio_cb((void*)voice_data->audio_buf, (unsigned int)voice_data->length)) {
111 SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Fail to read audio");
117 if (0 == g_buffer_count % 30) {
118 float vol_db = get_volume_decibel((char*)voice_data->audio_buf, (unsigned int)voice_data->length);
119 if (0 != vcdc_send_set_volume(vcd_client_manager_get_pid(), vol_db)) {
120 SLOG(LOG_ERROR, TAG_VCD, "[Recorder] Fail to send recording volume(%f)", vol_db);
124 if (0 == g_buffer_count || 0 == g_buffer_count % 50) {
125 SLOG(LOG_WARN, TAG_VCD, "[Recorder][%d] Recording... : read_size(%ld)", g_buffer_count, voice_data->length);
127 if (100000 == g_buffer_count)
134 /* write pcm buffer */
135 fwrite(voice_data->audio_buf, 1, voice_data->length, g_normal_file);
144 static int g_bt_extend_count;
146 #define SMART_CONTROL_EXTEND_CMD 0x03
147 #define SMART_CONTROL_START_CMD 0x04
149 static void _bt_cb_hid_state_changed(int result, bool connected, const char *remote_address, void *user_data)
151 SLOG(LOG_DEBUG, TAG_VCD, "[Recorder] Bluetooth Event [%d] Received address [%s]", result, remote_address);
155 static void _bt_hid_audio_data_receive_cb(bt_hid_voice_data_s *voice_data, void *user_data)
157 if (0 != strncmp(g_current_audio_type, VCP_AUDIO_ID_BLUETOOTH, sizeof(VCP_AUDIO_ID_BLUETOOTH))) {
158 vcd_state_e state = vcd_config_get_service_state();
159 if (VCD_STATE_READY == state) {
160 vcd_recorder_set(VCP_AUDIO_ID_BLUETOOTH, VCP_AUDIO_TYPE_PCM_S16_LE, 16000, 1);
162 SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] current audio type is (%s)", g_current_audio_type);
167 if (VCD_RECORDER_STATE_RECORDING != g_recorder_state) {
168 SLOG(LOG_WARN, TAG_VCD, "[Recorder] Not start yet, but send audio data vi Bluetooth");
169 vcd_recorder_start();
172 if (NULL != g_audio_cb) {
173 if (0 != g_audio_cb((void*)voice_data->audio_buf, (unsigned int)voice_data->length)) {
174 SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Fail to read audio");
180 if (0 == g_buffer_count % 15) {
181 float vol_db = get_volume_decibel((char*)voice_data->audio_buf, (unsigned int)voice_data->length);
182 if (0 != vcdc_send_set_volume(vcd_client_manager_get_pid(), vol_db)) {
183 SLOG(LOG_ERROR, TAG_VCD, "[Recorder] Fail to send recording volume(%f)", vol_db);
187 if (0 == g_buffer_count || 0 == g_buffer_count % 50) {
188 SLOG(LOG_WARN, TAG_VCD, "[Recorder][%d] Recording... : read_size(%d)", g_buffer_count, voice_data->length);
190 if (0 == g_bt_extend_count % 5 && 0 != g_buffer_count) {
191 const unsigned char input_data[2] = {SMART_CONTROL_EXTEND_CMD, 0x10 };
192 if (BT_ERROR_NONE != bt_hid_send_rc_command(NULL, input_data, sizeof(input_data))) {
193 SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Fail bt_hid_send_rc_command");
195 SLOG(LOG_DEBUG, TAG_VCD, "[Recorder] Extend bt audio recorder");
200 if (100000 == g_buffer_count) {
208 /* write pcm buffer */
209 fwrite(voice_data->audio_buf, 1, voice_data->length, g_normal_file);
217 static const char* __get_focus_changed_reason_code(sound_stream_focus_change_reason_e reason)
220 case SOUND_STREAM_FOCUS_CHANGED_BY_MEDIA: return "SOUND_STREAM_FOCUS_CHANGED_BY_MEDIA";
221 case SOUND_STREAM_FOCUS_CHANGED_BY_SYSTEM: return "SOUND_STREAM_FOCUS_CHANGED_BY_SYSTEM";
222 case SOUND_STREAM_FOCUS_CHANGED_BY_ALARM: return "SOUND_STREAM_FOCUS_CHANGED_BY_ALARM";
223 case SOUND_STREAM_FOCUS_CHANGED_BY_NOTIFICATION: return "SOUND_STREAM_FOCUS_CHANGED_BY_NOTIFICATION";
224 case SOUND_STREAM_FOCUS_CHANGED_BY_EMERGENCY: return "SOUND_STREAM_FOCUS_CHANGED_BY_EMERGENCY";
225 case SOUND_STREAM_FOCUS_CHANGED_BY_VOICE_INFORMATION: return "SOUND_STREAM_FOCUS_CHANGED_BY_VOICE_INFORMATION";
226 case SOUND_STREAM_FOCUS_CHANGED_BY_VOICE_RECOGNITION: return "SOUND_STREAM_FOCUS_CHANGED_BY_VOICE_RECOGNITION";
227 case SOUND_STREAM_FOCUS_CHANGED_BY_RINGTONE: return "SOUND_STREAM_FOCUS_CHANGED_BY_RINGTONE";
228 case SOUND_STREAM_FOCUS_CHANGED_BY_VOIP: return "SOUND_STREAM_FOCUS_CHANGED_BY_VOIP";
229 case SOUND_STREAM_FOCUS_CHANGED_BY_CALL: return "SOUND_STREAM_FOCUS_CHANGED_BY_CALL";
230 case SOUND_STREAM_FOCUS_CHANGED_BY_MEDIA_EXTERNAL_ONLY: return "SOUND_STREAM_FOCUS_CHANGED_BY_MEDIA_EXTERNAL_ONLY";
231 default: return "Undefined reason code";
235 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,
236 sound_stream_focus_change_reason_e reason, int sound_behavior, const char *extra_info, void *user_data)
238 SLOG(LOG_DEBUG, TAG_VCD, "[Recorder] Focus state changed cb");
240 if (stream_info != g_stream_info_h) {
241 SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Invalid stream info handle");
245 SLOG(LOG_WARN, TAG_VCD, "[Recorder] focus state chagned to (%d) with reason (%s)", (int)focus_state, __get_focus_changed_reason_code(reason));
247 if (VCD_RECORDER_STATE_RECORDING == g_recorder_state && SOUND_STREAM_FOCUS_STATE_RELEASED == focus_state) {
248 SLOG(LOG_WARN, TAG_VCD, "[Recorder] Focus released as interrupt");
249 if (NULL != g_interrupt_cb) {
256 static int __apply_device_for_stream_routing()
258 sound_device_list_h device_list = NULL;
259 sound_device_h device = NULL;
260 sound_device_type_e type;
261 sound_device_io_direction_e io_direction;
263 if (0 != sound_manager_get_current_device_list(SOUND_DEVICE_IO_DIRECTION_IN_MASK, &device_list)) {
264 SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Fail to get current device list");
269 while (0 == (ret = sound_manager_get_next_device(device_list, &device))) {
270 if (0 != sound_manager_get_device_type(device, &type)) {
271 SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Fail to get device tyep");
274 if (0 != sound_manager_get_device_io_direction(device, &io_direction)) {
275 SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Fail to get device io direction");
278 if (SOUND_DEVICE_USB_AUDIO == type && SOUND_DEVICE_IO_DIRECTION_IN == io_direction) {
279 if (0 != sound_manager_add_device_for_stream_routing(g_stream_info_h, device)) {
280 SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Fail to add device");
283 if (0 != sound_manager_apply_stream_routing(g_stream_info_h)) {
284 SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR} Fail to apply stream routing");
287 SLOG(LOG_DEBUG, TAG_VCD, "[Recorder] Apply device for stream routing");
292 SLOG(LOG_WARN, TAG_VCD, "[Recorder] No device");
296 int vcd_recorder_create(vcd_recoder_audio_cb audio_cb, vcd_recorder_interrupt_cb interrupt_cb)
298 if (NULL == audio_cb || NULL == interrupt_cb) {
299 SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Input param is NOT valid");
300 return VCD_ERROR_INVALID_PARAMETER;
303 /* check focus server */
306 if (0 == access(FOCUS_SERVER_READY, F_OK)) {
307 SLOG(LOG_ERROR, TAG_VCD, "[Recorder SUCCESS] focus server is available");
311 SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] focus server is not available");
319 g_is_valid_audio_in = false;
320 g_is_valid_bt_in = false;
321 g_current_audio_type = NULL;
323 g_audio_type = VCP_AUDIO_TYPE_PCM_S16_LE;
324 g_audio_rate = 16000;
327 audio_channel_e audio_ch;
328 audio_sample_type_e audio_type;
330 SLOG(LOG_DEBUG, TAG_VCD, "[Recorder] AUdio type(%d) rate(%d) channel(%d)", g_audio_type, g_audio_rate, g_audio_channel);
332 switch (g_audio_channel) {
333 case 1: audio_ch = AUDIO_CHANNEL_MONO; break;
334 case 2: audio_ch = AUDIO_CHANNEL_STEREO; break;
336 SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Input channel is not supported");
337 return VCD_ERROR_OPERATION_FAILED;
341 switch (g_audio_type) {
342 case VCP_AUDIO_TYPE_PCM_S16_LE: audio_type = AUDIO_SAMPLE_TYPE_S16_LE; break;
343 case VCP_AUDIO_TYPE_PCM_U8: audio_type = AUDIO_SAMPLE_TYPE_U8; break;
345 SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Invalid Audio Type");
346 return VCD_ERROR_OPERATION_FAILED;
350 ret = audio_in_create(g_audio_rate, audio_ch, audio_type, &g_audio_h);
351 if (AUDIO_IO_ERROR_NONE == ret) {
352 g_is_valid_audio_in = true;
354 SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Rate(%d) Channel(%d) Type(%d)", g_audio_rate, audio_ch, audio_type);
355 SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Fail to create audio handle : %d", ret);
356 g_is_valid_audio_in = false;
360 if (0 != sound_manager_create_stream_information_internal(SOUND_STREAM_TYPE_VOICE_RECOGNITION_SERVICE, __recorder_focus_state_cb, NULL, &g_stream_info_h)) {
361 SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Fail to create stream info");
363 __apply_device_for_stream_routing();
366 if (0 != audio_in_set_sound_stream_info(g_audio_h, g_stream_info_h)) {
367 SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Fail to set stream info");
371 g_audio_cb = audio_cb;
372 g_interrupt_cb = interrupt_cb;
373 g_recorder_state = VCD_RECORDER_STATE_READY;
377 bool is_bt_failed = false;
379 if (false == is_bt_failed && BT_ERROR_NONE != bt_initialize()) {
380 SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Fail to init bt");
384 if (false == is_bt_failed && BT_ERROR_NONE != bt_hid_host_initialize(_bt_cb_hid_state_changed, NULL)) {
385 SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Fail bt_hid_host_initialize()");
389 if (false == is_bt_failed && BT_ERROR_NONE != bt_hid_set_audio_data_receive_cb(_bt_hid_audio_data_receive_cb, NULL)) {
390 SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Fail bt_hid_set_audio_data_receive_cb()");
395 if (false == is_bt_failed) {
396 SLOG(LOG_DEBUG, TAG_VCD, "[Recorder] Bluetooth is available");
397 g_is_valid_bt_in = true;
400 /* Select default audio type */
401 if (true == g_is_valid_audio_in) {
402 g_current_audio_type = strdup(VCP_AUDIO_ID_NONE);
404 if (true == g_is_valid_bt_in) {
405 g_current_audio_type = strdup(VCP_AUDIO_ID_BLUETOOTH);
407 SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] No valid audio");
412 SLOG(LOG_DEBUG, TAG_VCD, "[Recorder] Audio type : %s", g_current_audio_type);
417 int vcd_recorder_destroy()
419 if (VCD_RECORDER_STATE_RECORDING == g_recorder_state) {
420 if (0 == strncmp(VCP_AUDIO_ID_BLUETOOTH, g_current_audio_type, strlen(VCP_AUDIO_ID_BLUETOOTH))) {
422 bt_hid_unset_audio_data_receive_cb();
424 } else if (0 == strncmp(VCP_AUDIO_ID_MSF, g_current_audio_type, strlen(VCP_AUDIO_ID_MSF))) {
425 #ifdef TV_MSF_WIFI_MODE
426 UnRegisterMSFAudioCallback();
429 audio_in_unprepare(g_audio_h);
431 g_recorder_state = VCD_RECORDER_STATE_READY;
435 if (0 != sound_manager_destroy_stream_information(g_stream_info_h)) {
436 SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Fail to destroy stream info");
440 audio_in_destroy(g_audio_h);
443 bt_hid_unset_audio_data_receive_cb();
445 bt_hid_host_deinitialize();
452 if (NULL != g_current_audio_type) {
453 free(g_current_audio_type);
454 g_current_audio_type = NULL;
460 int vcd_recorder_set(const char* audio_type, vcp_audio_type_e type, int rate, int channel)
462 if (NULL == audio_type) {
463 return VCD_ERROR_INVALID_PARAMETER;
466 if (NULL != g_current_audio_type) {
467 if (0 == strncmp(g_current_audio_type, audio_type, strlen(g_current_audio_type))) {
468 SLOG(LOG_DEBUG, TAG_VCD, "[Recorder] Current audio type is already set : %s", audio_type);
472 SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Recorder is NOT created");
473 return VCD_ERROR_INVALID_STATE;
476 SLOG(LOG_DEBUG, TAG_VCD, "[Recorder] set audio type (%s)", audio_type);
477 vcd_engine_set_audio_type(audio_type);
479 if (VCD_RECORDER_STATE_READY != g_recorder_state) {
480 if ((!strncmp(g_current_audio_type, VCP_AUDIO_ID_NONE, strlen(g_current_audio_type)) &&
481 strncmp(audio_type, VCP_AUDIO_ID_BLUETOOTH, strlen(audio_type)) &&
482 strncmp(audio_type, VCP_AUDIO_ID_MSF, strlen(audio_type))) ||
483 (strncmp(g_current_audio_type, VCP_AUDIO_ID_BLUETOOTH, strlen(g_current_audio_type)) &&
484 strncmp(g_current_audio_type, VCP_AUDIO_ID_MSF, strlen(g_current_audio_type)) &&
485 strncmp(g_current_audio_type, VCP_AUDIO_ID_NONE, strlen(g_current_audio_type)) &&
486 !strncmp(audio_type, VCP_AUDIO_ID_NONE, strlen(audio_type)))) {
487 SLOG(LOG_DEBUG, TAG_VCD, "[Recorder] Skip stop recording while Recorder is NOT ready");
489 SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Recorder is NOT ready");
491 //return VCD_ERROR_INVALID_STATE;
497 if (0 == strncmp(VCP_AUDIO_ID_BLUETOOTH, audio_type, strlen(VCP_AUDIO_ID_BLUETOOTH))) {
498 if (false == g_is_valid_bt_in) {
499 SLOG(LOG_ERROR, TAG_VCD, "[Recorder] BT audio is NOT valid");
500 return VCD_ERROR_OPERATION_REJECTED;
503 if (NULL != g_current_audio_type) {
504 free(g_current_audio_type);
505 g_current_audio_type = NULL;
508 g_current_audio_type = strdup(audio_type);
509 } else if (0 == strncmp(VCP_AUDIO_ID_MSF, audio_type, strlen(VCP_AUDIO_ID_MSF))) {
510 if (NULL != g_current_audio_type) {
511 free(g_current_audio_type);
512 g_current_audio_type = NULL;
515 g_current_audio_type = strdup(audio_type);
517 if (false == g_is_valid_audio_in) {
518 SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Audio-in is NOT valid");
519 return VCD_ERROR_OPERATION_REJECTED;
522 if (g_audio_type != type || g_audio_rate != rate || g_audio_channel != channel) {
523 SLOG(LOG_DEBUG, TAG_VCD, "[Recorder] New audio type(%d) rate(%d) channel(%d)", type, rate, channel);
524 audio_in_destroy(g_audio_h);
526 audio_channel_e audio_ch;
527 audio_sample_type_e audio_type;
530 case 1: audio_ch = AUDIO_CHANNEL_MONO; break;
531 case 2: audio_ch = AUDIO_CHANNEL_STEREO; break;
533 SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Input channel is not supported");
534 return VCD_ERROR_OPERATION_FAILED;
539 case VCP_AUDIO_TYPE_PCM_S16_LE: audio_type = AUDIO_SAMPLE_TYPE_S16_LE; break;
540 case VCP_AUDIO_TYPE_PCM_U8: audio_type = AUDIO_SAMPLE_TYPE_U8; break;
542 SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Invalid Audio Type");
543 return VCD_ERROR_OPERATION_FAILED;
547 ret = audio_in_create(rate, audio_ch, audio_type, &g_audio_h);
548 if (AUDIO_IO_ERROR_NONE != ret) {
549 SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Fail to create audio handle : %d", ret);
550 g_is_valid_audio_in = false;
551 return VCD_ERROR_OPERATION_FAILED;
554 if (0 != audio_in_set_sound_stream_info(g_audio_h, g_stream_info_h)) {
555 SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Fail to set stream info");
560 g_audio_channel = channel;
564 if (NULL != g_current_audio_type) {
565 free(g_current_audio_type);
566 g_current_audio_type = NULL;
569 g_current_audio_type = strdup(audio_type);
573 SLOG(LOG_DEBUG, TAG_VCD, "[Recorder] Current audio type is changed : %s", g_current_audio_type);
578 int vcd_recorder_get(char** audio_type)
580 if (NULL == audio_type) {
581 return VCD_ERROR_INVALID_PARAMETER;
584 if (NULL != g_current_audio_type) {
585 *audio_type = strdup(g_current_audio_type);
587 SLOG(LOG_WARN, TAG_VCD, "[Recorder] Current audio type(%s) is NOT ready", *audio_type);
594 static float get_volume_decibel(char* data, int size)
596 #define MAX_AMPLITUDE_MEAN_16 32768
603 unsigned long long square_sum = 0;
608 for (i = 0; i < size; i += (depthByte<<1)) {
610 memcpy(&pcm16, data + i, sizeof(short));
611 square_sum += pcm16 * pcm16;
615 if (0 == count || 0 == square_sum) {
616 SLOG(LOG_ERROR, TAG_VCD, "[ERROR] No data");
619 rms = sqrt((float)square_sum/count);
622 db = 20 * log10(rms/MAX_AMPLITUDE_MEAN_16);
626 Eina_Bool __read_normal_func(void *data)
630 if (VCD_RECORDER_STATE_RECORDING != g_recorder_state) {
631 SLOG(LOG_DEBUG, TAG_VCD, "[Recorder] Exit audio reading normal func");
635 memset(g_normal_buffer, '\0', BUFFER_LENGTH + 10);
637 ret = audio_in_read(g_audio_h, g_normal_buffer, BUFFER_LENGTH);
639 SLOG(LOG_WARN, TAG_VCD, "[Recorder WARNING] Fail to read audio : %d", ret);
640 g_recorder_state = VCD_RECORDER_STATE_READY;
644 if (NULL != g_audio_cb) {
645 if (0 != g_audio_cb(g_normal_buffer, BUFFER_LENGTH)) {
646 SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Fail to read audio : %d", ret);
653 if (0 == g_buffer_count % 30) {
654 float vol_db = get_volume_decibel(g_normal_buffer, BUFFER_LENGTH);
655 if (0 != vcdc_send_set_volume(vcd_client_manager_get_pid(), vol_db)) {
656 SLOG(LOG_ERROR, TAG_VCD, "[Recorder] Fail to send recording volume(%f)", vol_db);
660 if (0 == g_buffer_count || 0 == g_buffer_count % 50) {
661 SLOG(LOG_WARN, TAG_VCD, "[Recorder][%d] Recording... : read_size(%d)", g_buffer_count, ret);
663 if (100000 == g_buffer_count) {
671 /* write pcm buffer */
672 fwrite(g_normal_buffer, 1, BUFFER_LENGTH, g_normal_file);
678 static void __timer_read_normal_func(void *data)
680 SLOG(LOG_DEBUG, TAG_VCD, "[Recorder] before __read_normal_func");
681 ecore_timer_add(0, __read_normal_func, NULL);
685 static void __check_audio_format()
687 vcp_audio_type_e type;
691 int ret = vcd_engine_get_audio_format(VCP_AUDIO_ID_NONE, &type, &rate, &channel);
693 SLOG(LOG_ERROR, TAG_VCD, "[Server ERROR] Fail to get audio format : %d", ret);
697 if (false == g_is_valid_audio_in) {
698 SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Audio-in is NOT valid");
702 if (g_audio_type != type || g_audio_rate != rate || g_audio_channel != channel) {
703 SLOG(LOG_DEBUG, TAG_VCD, "[Recorder] New audio type(%d) rate(%d) channel(%d)", type, rate, channel);
704 audio_in_destroy(g_audio_h);
706 audio_channel_e audio_ch;
707 audio_sample_type_e audio_type;
710 case 1: audio_ch = AUDIO_CHANNEL_MONO; break;
711 case 2: audio_ch = AUDIO_CHANNEL_STEREO; break;
713 SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Input channel is not supported");
719 case VCP_AUDIO_TYPE_PCM_S16_LE: audio_type = AUDIO_SAMPLE_TYPE_S16_LE; break;
720 case VCP_AUDIO_TYPE_PCM_U8: audio_type = AUDIO_SAMPLE_TYPE_U8; break;
722 SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Invalid Audio Type");
727 ret = audio_in_create(rate, audio_ch, audio_type, &g_audio_h);
728 if (AUDIO_IO_ERROR_NONE != ret) {
729 SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Fail to create audio handle : %d", ret);
730 g_is_valid_audio_in = false;
734 if (0 != audio_in_set_sound_stream_info(g_audio_h, g_stream_info_h)) {
735 SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Fail to set stream info");
740 g_audio_channel = channel;
742 SLOG(LOG_DEBUG, TAG_VCD, "[Recorder] audio type(%d) rate(%d) channel(%d)", g_audio_type, g_audio_rate, g_audio_channel);
748 int vcd_recorder_start()
753 SLOG(LOG_DEBUG, TAG_VCD, "[Recorder] Enter, recorder state(%d)", g_recorder_state);
755 if (VCD_RECORDER_STATE_RECORDING == g_recorder_state) return 0;
757 bool started = false;
758 SLOG(LOG_DEBUG, TAG_VCD, "[Recorder] audio type : %s", g_current_audio_type);
760 if (NULL != g_current_audio_type) {
761 if (0 == strncmp(VCP_AUDIO_ID_BLUETOOTH, g_current_audio_type, strlen(VCP_AUDIO_ID_BLUETOOTH))) {
763 const unsigned char input_data[2] = {SMART_CONTROL_START_CMD, 0x00};
765 while (5 > bt_retry) {
766 ret = bt_hid_send_rc_command(NULL, input_data, sizeof(input_data));
767 if (BT_ERROR_NONE == ret) {
768 SLOG(LOG_DEBUG, TAG_VCD, "[Recorder] Start bt audio recorder");
771 } else if (BT_ERROR_NOW_IN_PROGRESS == ret) {
772 SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Fail bt_hid_send_rc_command : %d", ret);
779 if (false == started) {
780 SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Fail to start bt audio");
781 return VCD_ERROR_OPERATION_FAILED;
784 g_bt_extend_count = 0;
786 } else if (0 == strncmp(VCP_AUDIO_ID_MSF, g_current_audio_type, strlen(VCP_AUDIO_ID_MSF))) {
787 SLOG(LOG_DEBUG, TAG_VCD, "[Recorder] call RegisterMSFAudioCallback() function");
788 #ifdef TV_MSF_WIFI_MODE
790 ret = RegisterMSFAudioCallback(__msf_wifi_audio_data_receive_cb, NULL);
791 SLOG(LOG_ERROR, TAG_VCD, "[Recorder] ret = %d", ret);
792 if (MSFResult_OK == ret) {
795 SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Fail to start MSF(wifi) audio");
796 return VCD_ERROR_OPERATION_FAILED;
802 SLOG(LOG_DEBUG, TAG_VCD, "[Recorder] started = %d", started);
803 if (false == started) {
804 /* check audio format */
805 __check_audio_format();
807 ret = sound_manager_acquire_focus(g_stream_info_h, SOUND_STREAM_FOCUS_FOR_RECORDING, NULL);
808 if (SOUND_MANAGER_ERROR_NONE != ret) {
809 SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Fail to acquire focus : %d", ret);
811 ret = audio_in_set_sound_stream_info(g_audio_h, g_stream_info_h);
812 if (AUDIO_IO_ERROR_NONE != ret) {
813 SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Fail to set stream info : %d", ret);
818 ret = audio_in_prepare(g_audio_h);
819 if (AUDIO_IO_ERROR_NONE != ret) {
820 if (AUDIO_IO_ERROR_SOUND_POLICY == ret) {
821 SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Audio is busy.");
822 return VCD_ERROR_RECORDER_BUSY;
824 SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Fail to start audio : %d", ret);
826 return VCD_ERROR_OPERATION_FAILED;
829 /* Add ecore timer to read audio data */
830 ecore_main_loop_thread_safe_call_async(__timer_read_normal_func, NULL);
831 SLOG(LOG_DEBUG, TAG_VCD, "[Recorder] Start audio in recorder");
834 g_recorder_state = VCD_RECORDER_STATE_RECORDING;
837 char normal_file_name[128] = {'\0',};
841 snprintf(normal_file_name, sizeof(normal_file_name), "/tmp/vc_normal_%d_%d", getpid(), g_count);
842 ret = access(normal_file_name, 0);
845 SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] File is already exist");
846 if (0 == remove(normal_file_name)) {
847 SLOG(LOG_DEBUG, TAG_VCD, "[Recorder] Remove file");
857 SLOG(LOG_DEBUG, TAG_VCD, "[Recorder] File normal name : %s", normal_file_name);
860 g_normal_file = fopen(normal_file_name, "wb+x");
861 if (!g_normal_file) {
862 SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] File not found!");
868 int vcd_recorder_stop()
872 if (VCD_RECORDER_STATE_READY == g_recorder_state)
875 g_recorder_state = VCD_RECORDER_STATE_READY;
878 fclose(g_normal_file);
883 if (NULL != g_current_audio_type) {
884 if (0 == strncmp(VCP_AUDIO_ID_BLUETOOTH, g_current_audio_type, strlen(VCP_AUDIO_ID_BLUETOOTH))) {
887 while (5 > bt_retry) {
888 ret = bt_hid_rc_stop_sending_voice(NULL);
889 if (BT_ERROR_NONE == ret) {
890 SLOG(LOG_DEBUG, TAG_VCD, "[Recorder] Stop bt audio recorder");
893 } else if (BT_ERROR_NOW_IN_PROGRESS == ret) {
894 SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Fail bt_hid_rc_stop_sending_voice()");
901 if (NULL != g_current_audio_type &&
902 (!strncmp(g_current_audio_type, VCP_AUDIO_ID_BLUETOOTH, sizeof(VCP_AUDIO_ID_BLUETOOTH)) ||
903 !strncmp(g_current_audio_type, VCP_AUDIO_ID_MSF, sizeof(VCP_AUDIO_ID_MSF)))) {
904 SLOG(LOG_DEBUG, TAG_VCD, "[DEBUG] Recorder reset to NONE");
905 vcd_recorder_set(VCP_AUDIO_ID_NONE, g_audio_type, g_audio_rate, g_audio_channel);
908 if (false == stoped) {
909 SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Fail to stop bt audio");
910 return VCD_ERROR_OPERATION_FAILED;
913 } else if (0 == strncmp(VCP_AUDIO_ID_MSF, g_current_audio_type, strlen(VCP_AUDIO_ID_MSF))) {
914 #ifdef TV_MSF_WIFI_MODE
915 UnRegisterMSFAudioCallback();
916 if (NULL != g_current_audio_type &&
917 (!strncmp(g_current_audio_type, VCP_AUDIO_ID_BLUETOOTH, sizeof(VCP_AUDIO_ID_BLUETOOTH)) ||
918 !strncmp(g_current_audio_type, VCP_AUDIO_ID_MSF, sizeof(VCP_AUDIO_ID_MSF)))) {
919 SLOG(LOG_DEBUG, TAG_VCD, "[DEBUG] Recorder reset to NONE");
920 vcd_recorder_set(VCP_AUDIO_ID_NONE, g_audio_type, g_audio_rate, g_audio_channel);
925 SLOG(LOG_DEBUG, TAG_VCD, "[Recorder] current audio type is NONE");
929 if (false == stoped) {
930 ret = audio_in_unprepare(g_audio_h);
931 if (AUDIO_IO_ERROR_NONE != ret) {
932 SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Fail to stop audio : %d", ret);
933 return VCD_ERROR_OPERATION_FAILED;
937 ret = sound_manager_release_focus(g_stream_info_h, SOUND_STREAM_FOCUS_FOR_RECORDING, NULL);
938 if (SOUND_MANAGER_ERROR_NONE != ret) {
939 SLOG(LOG_ERROR, TAG_VCD, "[Recorder ERROR] Fail to release focus : %d", ret);
947 int vcd_recorder_get_state()
949 return g_recorder_state;