Files
device_rockchip/rk3308/aispeech/dds_client/demo/main.c
Eddie Cai 6ea5e91a98 initial commit
Signed-off-by: Eddie Cai <eddie.cai.linux@gmail.com>
2018-06-23 10:08:13 +08:00

463 lines
15 KiB
C
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*================================================================
* Copyright (C) 2018 AISPEECH Ltd. All rights reserved.
*
* 文件名称main.c
* 创 建 者chenjie.gu
* 创建日期2018年05月16日
* 描 述:
*
================================================================*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <sys/select.h>
#include <pthread.h>
#include <time.h>
#include "dds_client.h"
#include "button.h"
#include "cJSON.h"
#include <stdbool.h>
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\"}");
}
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;
}