/*================================================================ * Copyright (C) 2018 AISPEECH Ltd. All rights reserved. * * 文件名称:main.c * 创 建 者:chenjie.gu * 创建日期:2018年05月16日 * 描 述: * ================================================================*/ #include #include #include #include #include #include #include #include "dds_client.h" #include "button.h" #include "cJSON.h" #include int is_enable_wakeup = 1; struct dds_client *dc = NULL; bool m_is_dialog = false; bool m_is_tts_playing = false; pthread_mutex_t mylock=PTHREAD_MUTEX_INITIALIZER; pthread_cond_t mycond=PTHREAD_COND_INITIALIZER; extern int music_player_init(char *dev); extern int music_player_start(); extern bool music_is_playing(void); extern void play_manager_f(const char *cmd, const char *data); void handle_doa_result(int doa); #define WAIT_WAKEUP_SYSTEM_CMD "./aispeech_led -m on 4" #define RUNNING_ASR_SYSTEM_CMD "./aispeech_led -m scroll -b 4 2 -s 100" #define WAIT_DM_OUT_SYSTEM_CMD "./aispeech_led -m scroll -b 4 2 -s 100" #define RUNNING_TTS_SYSTEM_CMD "./aispeech_led -m on -b 2 2" #define DISABLE_WAKEUP_SYSTEM_CMD "./aispeech_led -m on -b 2 1" void led_off() { printf("%s\n", __func__); system("./aispeech_led -m on 4"); } void clean_silence_frame() { system("echo 0 > /sys/module/snd_soc_rockchip_vad/parameters/voice_inactive_frames"); } void do_system_sleep() { system("echo mem > /sys/power/state"); } /* * 1. volume.set * 2. play.list.update * 3. play.list.clear * 4. play.list.get * 5. status.set * 6. change.set * 7. mode.set * 8. play.choose.update * 9. play.collect.choose * 10. play.uncollect.choose * 11. player.end */ void dds_cb(const char *topic, const char *topic_data, void *user) { static int end_dialog = 0; printf("####### dds cb receive topic: %s\n", topic); printf("####### dds cb receive topic_data: %s\n", topic_data); if (!strcmp(topic, "dm.output")) { cJSON *root = cJSON_Parse(topic_data); assert(root != NULL); cJSON *dm = cJSON_GetObjectItem(root, "dm"); cJSON *widget = cJSON_GetObjectItem(dm, "widget"); if (widget) { cJSON *count = cJSON_GetObjectItem(widget, "count"); if (count && count->valueint > 0) { char *out = cJSON_PrintUnformatted(widget); play_manager_f("play.list.update", out); free(out); } } cJSON *end_session = cJSON_GetObjectItem(dm, "shouldEndSession"); if (end_session->valueint) { end_dialog = 1; } else end_dialog = 0; system(WAIT_WAKEUP_SYSTEM_CMD); clean_silence_frame(); m_is_dialog = false; printf("dm.output close dialog\n"); cJSON_Delete(root); } else if (!strcmp(topic, "doa.result")) { // doa 结果 cJSON *root = cJSON_Parse(topic_data); assert(root != NULL); cJSON *doa = cJSON_GetObjectItem(root, "doa"); handle_doa_result(doa->valueint); cJSON_Delete(root); } else if (!strcmp(topic, "command://spk.speaker.close")) { play_manager_f("play.list.clear", NULL); dds_client_resp_nativeapi(dc, topic, "{\"duiWidget\":\"text\", \"extra\":{\"APICommandResult\":\"success\"}}"); } else if (!strcmp(topic, "native://mediacontrol.media.single")) { play_manager_f("mode.set", "single"); dds_client_resp_nativeapi(dc, topic, "{\"duiWidget\":\"text\", \"extra\":{\"APICommandResult\":\"success\"}}"); } else if (!strcmp(topic, "native://mediacontrol.media.sequence")) { play_manager_f("mode.set", "sequence"); dds_client_resp_nativeapi(dc, topic, "{\"duiWidget\":\"text\", \"extra\":{\"APICommandResult\":\"success\"}}"); } else if (!strcmp(topic, "native://mediacontrol.media.random")) { play_manager_f("mode.set", "random"); dds_client_resp_nativeapi(dc, topic, "{\"duiWidget\":\"text\", \"extra\":{\"APICommandResult\":\"success\"}}"); } else if (!strcmp(topic, "native://mediacontrol.media.loop")) { play_manager_f("mode.set", "loop"); dds_client_resp_nativeapi(dc, topic, "{\"duiWidget\":\"text\", \"extra\":{\"APICommandResult\":\"success\"}}"); } else if (!strcmp(topic, "native://mediacontrol.media.pause")) { play_manager_f("status.set", "pause"); dds_client_resp_nativeapi(dc, topic, "{\"duiWidget\":\"text\", \"extra\":{\"APICommandResult\":\"success\"}}"); } else if (!strcmp(topic, "native://mediacontrol.media.continue")) { play_manager_f("status.set", "resume"); dds_client_resp_nativeapi(dc, topic, "{\"duiWidget\":\"text\", \"extra\":{\"APICommandResult\":\"success\"}}"); } else if (!strcmp(topic, "native://mediacontrol.media.stop")) { play_manager_f("play.list.clear", NULL); dds_client_resp_nativeapi(dc, topic, "{\"duiWidget\":\"text\", \"extra\":{\"APICommandResult\":\"success\"}}"); } else if (!strcmp(topic, "native://mediacontrol.media.replay")) { play_manager_f("status.set", "replay"); dds_client_resp_nativeapi(dc, topic, "{\"duiWidget\":\"text\", \"extra\":{\"APICommandResult\":\"success\"}}"); } else if (!strcmp(topic, "native://mediacontrol.media.prev")) { play_manager_f("change.set", "prev"); dds_client_resp_nativeapi(dc, topic, "{\"duiWidget\":\"text\", \"extra\":{\"count\":\"more\", \"skillName\":\"speakerChinaPlay\", \"title\":\"\"}}"); } else if (!strcmp(topic, "native://mediacontrol.media.next")) { play_manager_f("change.set", "next"); dds_client_resp_nativeapi(dc, topic, "{\"duiWidget\":\"text\", \"extra\":{\"count\":\"more\", \"skillName\":\"speakerChinaPlay\", \"title\":\"\"}}"); } else if (!strcmp(topic, "native://mediacontrol.media.change")) { play_manager_f("change.set", "change"); dds_client_resp_nativeapi(dc, topic, "{\"duiWidget\":\"text\", \"extra\":{\"count\":\"more\", \"skillName\":\"speakerChinaPlay\", \"title\":\"\"}}"); } else if (!strcmp(topic, "command://spk.speaker.voice")) { cJSON *root = cJSON_Parse(topic_data); cJSON *voice = cJSON_GetObjectItem(root, "voice"); if (voice) { play_manager_f("volume.set", voice->valuestring); } play_manager_f("status.set", "resume"); cJSON_Delete(root); } else if (!strcmp(topic, "native://alarm.set")) { dds_client_resp_nativeapi(dc, topic, "{\"duiWidget\":\"text\", \"extra\":{\"text\":\"已为您设置闹钟\"}}"); } else if (!strcmp(topic, "native://alarm.list")) { dds_client_resp_nativeapi(dc, topic, "{\"duiWidget\":\"text\", \"extra\":{\"text\":\"您要查的闹钟不存在哦\"}}"); } else if (!strcmp(topic, "native://alarm.delete")) { dds_client_resp_nativeapi(dc, topic, "{\"duiWidget\":\"text\", \"extra\":{\"text\":\"已为您删除闹钟\"}}"); } else if (!strcmp(topic, "native://alarm.close")) { dds_client_resp_nativeapi(dc, topic, "{\"duiWidget\":\"text\", \"extra\":{\"text\":\"已为您关闭闹钟\"}}"); } else if (!strcmp(topic, "native://remind.set")) { dds_client_resp_nativeapi(dc, topic, "{\"duiWidget\":\"text\", \"extra\":{\"text\":\"已为您设置提醒\"}}"); } else if (!strcmp(topic, "native://remind.list")) { dds_client_resp_nativeapi(dc, topic, "{\"duiWidget\":\"text\", \"extra\":{\"text\":\"暂时抄不到提醒哦\"}}"); } else if (!strcmp(topic, "native://remind.delete")) { dds_client_resp_nativeapi(dc, topic, "{\"duiWidget\":\"text\", \"extra\":{\"text\":\"已为您删除提醒\"}}"); } else if (!strcmp(topic, "native://remind.close")) { dds_client_resp_nativeapi(dc, topic, "{\"duiWidget\":\"text\", \"extra\":{\"text\":\"已为您关闭提醒\"}}"); } else if (!strcmp(topic, "local_wakeup.result")) { end_dialog = 0; play_manager_f("status.set", "pause"); } else if (!strcmp(topic, "sys.dm.end")) { // 对话退出 play_manager_f("play.list.check", NULL); system(WAIT_WAKEUP_SYSTEM_CMD); clean_silence_frame(); m_is_dialog = false; if (!is_enable_wakeup) { system(DISABLE_WAKEUP_SYSTEM_CMD); } printf("sys.dm.end out \n"); } else if (!strcmp(topic, "sys.tts.begin")) { clean_silence_frame(); } else if (!strcmp(topic, "sys.tts.end")) { } else if (!strcmp(topic, "sys.vad.end")) { } else if (!strcmp(topic, "sys.asr.begin")) { system(RUNNING_ASR_SYSTEM_CMD); clean_silence_frame(); m_is_dialog = true; } else if (!strcmp(topic, "device.mode.return")) { pthread_cond_signal(&mycond); } } void handle_doa_result(int doa) { printf("handle_doa_result doa is %d\n", doa); static char *doa_led_table[12] = { "./aispeech_led -m single -i 2 0", "./aispeech_led -m single -i 3 0", "./aispeech_led -m single -i 4 0", "./aispeech_led -m single -i 5 0", "./aispeech_led -m single -i 6 0", "./aispeech_led -m single -i 7 0", "./aispeech_led -m single -i 8 0", "./aispeech_led -m single -i 9 0", "./aispeech_led -m single -i 10 0", "./aispeech_led -m single -i 11 0", "./aispeech_led -m single -i 0 0", "./aispeech_led -m single -i 1 0" }; if (doa >= 0) { if (doa >=345 || doa < 15) { system(doa_led_table[0]); } else if (doa >= 15 && doa < 45) { system(doa_led_table[1]); } else if (doa >= 45 && doa < 75) { system(doa_led_table[2]); } else if (doa >= 75 && doa < 105) { system(doa_led_table[3]); } else if (doa >= 105 && doa < 135) { system(doa_led_table[4]); } else if (doa >= 135 && doa < 165) { system(doa_led_table[5]); } else if (doa >= 165 && doa < 195) { system(doa_led_table[6]); } else if (doa >= 195 && doa < 225) { system(doa_led_table[7]); } else if (doa >= 225 && doa < 255) { system(doa_led_table[8]); } else if (doa >= 255 && doa < 285) { system(doa_led_table[9]); } else if (doa >= 285 && doa < 315) { system(doa_led_table[10]); } else if (doa >= 315 && doa < 345) { system(doa_led_table[11]); } } else printf("=== doa result is wrong\n"); } void button_cb(button_event_t ev, void *userdata) { const char *info[] = { "BUTTON_EVENT_VOLUME_ADD", "BUTTON_EVENT_VOLUME_SUB", "BUTTON_EVENT_PREV", "BUTTON_EVENT_NEXT", "BUTTON_EVENT_PLAY_PAUSE", "BUTTON_EVENT_PLAY_PAUSE_LONG", "BUTTON_EVENT_MUTE_UNMUTE", "BUTTON_EVENT_MUTE_UNMUTE_LONG", "BUTTON_EVENT_MODE_WIFI", "BUTTON_EVENT_MODE_NORMAL" }; printf("%s\n", info[ev]); if (ev == BUTTON_EVENT_VOLUME_ADD) { //短按触发 play_manager_f("volume.set", "+"); } else if (ev == BUTTON_EVENT_VOLUME_SUB) { //短按触发 play_manager_f("volume.set", "-"); } else if (ev == BUTTON_EVENT_PREV) { //长按每隔1.5秒触发一次 play_manager_f("change.set", "prev"); play_manager_f("play.list.check", NULL); } else if (ev == BUTTON_EVENT_NEXT) { //长按每隔1.5秒触发一次 play_manager_f("change.set", "next"); play_manager_f("play.list.check", NULL); } else if (ev == BUTTON_EVENT_PLAY_PAUSE) { //短按触发 play_manager_f("status.set", "step"); } else if (ev == BUTTON_EVENT_MUTE_UNMUTE) { // mute if (is_enable_wakeup) { is_enable_wakeup = 0; dds_client_stop_dialog(dc); dds_client_disable_wakeup(dc); system(DISABLE_WAKEUP_SYSTEM_CMD); } else { is_enable_wakeup = 1; dds_client_enable_wakeup(dc); system(WAIT_WAKEUP_SYSTEM_CMD); } } } void *button_routine(void *user) { button_config_t config = { .dev = "/dev/input/event0", // v11: event0 | v10: event1 .cb = button_cb }; button_handle_t button = button_create(&config); while (1) { button_run(button); } button_destroy(button); return (void *)0; } const unsigned int voice_inactive_max_count = 16000 * 5; //16k, 3 seconds unsigned int read_voice_inactive_frames(void) { FILE *fp; char buf[100]; unsigned int frames = 0; fp = popen("cat /sys/module/snd_soc_rockchip_vad/parameters/voice_inactive_frames", "r"); if(!fp) { perror("popen"); exit(EXIT_FAILURE); } memset(buf, 0, sizeof(buf)); if (fgets(buf, sizeof(buf) - 1, fp) != 0 ) { sscanf(buf, "%ul", &frames); //printf("%s frames %lu\n", buf, frames); } pclose(fp); return frames; } bool sleep_check(void) { unsigned int inactive_frames = read_voice_inactive_frames(); bool music_playing = music_is_playing(); printf("inactive frames %d, max %d, dialog %d, tts %d, music %d\n", inactive_frames, voice_inactive_max_count, m_is_dialog, m_is_tts_playing, music_playing); if (music_playing) { clean_silence_frame(); } if ((inactive_frames > voice_inactive_max_count) \ && !m_is_dialog && !music_playing) return true; return false; } void wait_device_mode_timeout_ms(int microseconds) { struct timeval tv; long long absmsec; struct timespec abstime; gettimeofday(&tv, NULL); absmsec = tv.tv_sec * 1000ll + tv.tv_usec / 1000ll; absmsec += microseconds; abstime.tv_sec = absmsec / 1000ll; abstime.tv_nsec = absmsec % 1000ll * 1000000ll; printf("#### public sleep mode ####"); pthread_mutex_lock(&mylock); pthread_cond_timedwait(&mycond, &mylock, &abstime); pthread_mutex_unlock(&mylock); printf("#### return sleep mode succeed ####"); } void *vad_detect_func(void* arg) { clean_silence_frame(); while(true) { if (sleep_check()) { fprintf(stderr,"voice inactive timeout,go to sleep\n"); dds_client_publish(dc, DDS_CLIENT_USER_DEVICE_MODE, "{\"mode\":\"sleep\"}"); wait_device_mode_timeout_ms(30); printf("pause >>>>\n"); clean_silence_frame(); do_system_sleep(); printf("resume >>>>\n"); dds_client_publish(dc, DDS_CLIENT_USER_DEVICE_MODE, "{\"mode\":\"normal\"}"); wait_device_mode_timeout_ms(30); } usleep(1000*1000); } } int main () { int ret; char config[1024 * 5]; FILE *fp = NULL; fp = fopen("./config.json", "r"); if (fp) { fread(config, 1, 1024 * 5, fp); fclose(fp); } else return -1; // 1. init music player cJSON *root = cJSON_Parse(config); cJSON *player = cJSON_GetObjectItem(root, "player"); if (player) { player = cJSON_GetObjectItem(player, "device"); if (player) music_player_init(player->valuestring); else music_player_init("default"); } else music_player_init("default"); // 2. start the music player music_player_start(); // 3. run the dds client dc = dds_client_init(config); assert(dc != NULL); ret = dds_client_start(dc, dds_cb, NULL); assert(ret != -1); // 4. button thread pthread_t tid2; pthread_create(&tid2, NULL, button_routine, NULL); // 5. system init system("amixer cset name='Master Playback Volume' 70"); system("alsaucm -c rockchiprk3308v"); system("chmod +x aispeech_led"); pthread_t softvad_detect; pthread_create(&softvad_detect,NULL,vad_detect_func,NULL); led_off();//led init select(0, 0, 0, 0, 0); dds_client_release(dc); return 0; }