#include "server/audio_server.h" #include "server/server_core.h" #include "app_config.h" #include "storage_device.h" #include "event/key_event.h" #include "event/device_event.h" #include "event/net_event.h" #include "syscfg/syscfg_id.h" #include "system/wait.h" #include "system/app_core.h" #include "lwip.h" #ifdef USE_AUDIO_DEMO #ifdef CONFIG_NET_MUSIC_MODE_ENABLE #include "server/ai_server.h" #include "network_download/net_download.h" #define CONFIG_STORE_VOLUME #define VOLUME_STEP 5 #define MIN_VOLUME_VALUE 5 #define MAX_VOLUME_VALUE 100 #define INIT_VOLUME_VALUE 50 struct net_music_hdl { char volume; u16 wait_download; int download_ready; int play_time; int total_time; void *net_file; const char *ai_name; struct server *dec_server; struct server *ai_server; char *url; //保存断点歌曲的链接 struct audio_dec_breakpoint dec_bp; }; static struct net_music_hdl net_music_handler; #define __this (&net_music_handler) //网络解码需要的数据访问句柄 static const struct audio_vfs_ops net_audio_dec_vfs_ops = { .fread = net_download_read, .fseek = net_download_seek, .flen = net_download_get_file_len, }; int get_app_music_volume(void) { return __this->volume; } int get_app_music_playtime(void) { return __this->play_time; } int get_app_music_total_time(void) { return __this->total_time; } //检查音频需要的格式检查数据头部是否下载缓冲完成 static int __net_download_ready(void *p) { __this->download_ready = net_download_check_ready(__this->net_file); if (__this->download_ready) { return 1; } return 0; } //暂停/继续播放 static int net_music_dec_play_pause(u8 notify) { union audio_req r = {0}; union ai_req req = {0}; #ifdef CONFIG_DEC_ANALOG_VOLUME_ENABLE r.dec.attr = AUDIO_ATTR_FADE_INOUT; #endif r.dec.cmd = AUDIO_DEC_PP; server_request(__this->dec_server, AUDIO_REQ_DEC, &r); if (r.dec.status == AUDIO_DEC_START) { /* 播放状态 */ net_download_set_pp(__this->net_file, 0); } else if (r.dec.status == AUDIO_DEC_PAUSE) { /* 暂停状态 */ net_download_set_pp(__this->net_file, 1); } if (notify && __this->ai_server && r.dec.status != AUDIO_DEC_STOP) { //notify : 是否需要通知云端暂停 req.evt.event = AI_EVENT_PLAY_PAUSE; req.evt.ai_name = __this->ai_name; if (r.dec.status == AUDIO_DEC_PAUSE) { req.evt.arg = 1; } ai_server_request(__this->ai_server, AI_REQ_EVENT, &req); } return 0; } //停止播放 static int net_music_dec_stop(void) { union audio_req r = {0}; union ai_req req = {0}; if (!__this->net_file) { return 0; } log_i("net_music_dec_stop\n"); net_download_buf_inactive(__this->net_file); if (__this->wait_download) { /* * 歌曲还未开始播放,删除wait */ /* sys_timer_del(__this->wait_download); */ wait_completion_del(__this->wait_download); __this->wait_download = 0; } else { r.dec.cmd = AUDIO_DEC_STOP; server_request(__this->dec_server, AUDIO_REQ_DEC, &r); int argv[2]; argv[0] = AUDIO_SERVER_EVENT_END; argv[1] = (int)__this->net_file; server_event_handler_del(__this->dec_server, 2, argv); } extern int lwip_canceladdrinfo(void); lwip_canceladdrinfo(); //释放网络下载资源 net_download_close(__this->net_file); __this->net_file = NULL; return 0; } //播放结束 static int net_music_dec_end(void) { union ai_req req = {0}; log_i("net_music_dec_end\n"); net_music_dec_stop(); if (!__this->ai_server) { return 0; } /* 歌曲播放完成,发送此命令后ai平台会发送新的URL */ req.evt.event = AI_EVENT_MEDIA_END; req.evt.ai_name = __this->ai_name; return ai_server_request(__this->ai_server, AI_REQ_EVENT, &req); } //数据缓冲已完成,开始解码 static int __net_music_dec_file(void *file) { int err; union ai_req r = {0}; union audio_req req = {0}; __this->wait_download = 0; if (__this->download_ready < 0) { /* 网络下载失败 */ goto __err; } //获取网络资源的格式 req.dec.dec_type = net_download_get_media_type(file); if (req.dec.dec_type == NULL) { goto __err; } log_i("url_file_type: %s\n", req.dec.dec_type); net_download_set_read_timeout(file, 5000); req.dec.cmd = AUDIO_DEC_OPEN; req.dec.volume = __this->volume; req.dec.output_buf_len = 6 * 1024; req.dec.file = (FILE *)file; req.dec.channel = 0; req.dec.sample_rate = 0; req.dec.priority = 1; req.dec.vfs_ops = &net_audio_dec_vfs_ops; req.dec.sample_source = CONFIG_AUDIO_DEC_PLAY_SOURCE; /* req.dec.bp = &__this->dec_bp; //恢复断点 */ #if 0 //变声变调功能 req.dec.speedV = 80; // >80是变快,<80是变慢,建议范围:30到130 req.dec.pitchV = 32768; // >32768是音调变高,<32768音调变低,建议范围20000到50000 req.dec.attr = AUDIO_ATTR_PS_EN; #endif err = server_request(__this->dec_server, AUDIO_REQ_DEC, &req); if (err) { goto __err; } __this->play_time = req.dec.play_time; __this->total_time = req.dec.total_time; net_download_set_read_timeout(file, 0); req.dec.cmd = AUDIO_DEC_START; server_request(__this->dec_server, AUDIO_REQ_DEC, &req); net_download_set_pp(file, 0); return 0; __err: log_e("play_net_music_faild\n"); net_download_buf_inactive(file); req.dec.cmd = AUDIO_DEC_STOP; server_request(__this->dec_server, AUDIO_REQ_DEC, &req); net_download_close(file); __this->net_file = NULL; if (__this->ai_server) { r.evt.event = AI_EVENT_MEDIA_END; r.evt.ai_name = __this->ai_name; ai_server_request(__this->ai_server, AI_REQ_EVENT, &r); } return -1; } static int net_music_dec_file(const char *url) { int err; struct net_download_parm parm = {0}; net_music_dec_stop(); if (!url) { return -1; } log_i("net_download_open\n"); parm.url = url; //网络缓冲buf大小 #ifdef CONFIG_NO_SDRAM_ENABLE parm.cbuf_size = 150 * 1024; #else parm.cbuf_size = 500 * 1024; #endif //设置网络下载超时 parm.timeout_millsec = 10000; #ifdef CONFIG_DOWNLOAD_SAVE_FILE if (storage_device_ready()) { parm.save_file = 1; parm.file_dir = NULL; } #endif parm.seek_threshold = 1024 * 200; //用户可适当调整 /* parm.seek_low_range = __this->dec_bp.fptr; //恢复断点时设置网络的开始下载地址 */ err = net_download_open(&__this->net_file, &parm); if (err) { log_e("net_download_open: err = %d\n", err); return err; } /*异步等待网络下载ready,防止网络阻塞导致app_core卡住 */ __this->wait_download = wait_completion(__net_download_ready, (int (*)(void *))__net_music_dec_file, __this->net_file, NULL); return 0; } //切换上一首或下一首 static int net_music_dec_switch_file(int fsel_mode) { union ai_req req = {0}; if (!__this->ai_server) { return 0; } log_i("net_music_dec_switch_file\n"); if (!strcmp(__this->ai_name, "dlna")) { return 0; } net_music_dec_stop(); if (fsel_mode == FSEL_NEXT_FILE) { req.evt.event = AI_EVENT_NEXT_SONG; } else if (fsel_mode == FSEL_PREV_FILE) { req.evt.event = AI_EVENT_PREVIOUS_SONG; } else { return 0; } req.evt.ai_name = __this->ai_name; return ai_server_request(__this->ai_server, AI_REQ_EVENT, &req); } //获取断点数据 static int net_music_get_dec_breakpoint(struct audio_dec_breakpoint *bp) { int err; union audio_req r = {0}; bp->len = 0; r.dec.bp = bp; r.dec.cmd = AUDIO_DEC_GET_BREAKPOINT; if (bp->data) { free(bp->data); bp->data = NULL; } err = server_request(__this->dec_server, AUDIO_REQ_DEC, &r); if (err) { return err; } if (r.dec.status == AUDIO_DEC_STOP) { bp->len = 0; free(bp->data); bp->data = NULL; return -1; } /* put_buf(bp->data, bp->len); */ return 0; } //设置音量大小 static int net_music_set_dec_volume(int step) { union audio_req req = {0}; union ai_req ai = {0}; int volume = __this->volume + step; if (volume < MIN_VOLUME_VALUE) { volume = MIN_VOLUME_VALUE; } else if (volume > MAX_VOLUME_VALUE) { volume = MAX_VOLUME_VALUE; } if (volume == __this->volume) { return -1; } __this->volume = volume; log_d("set_dec_volume: %d\n", volume); req.dec.cmd = AUDIO_DEC_SET_VOLUME; req.dec.volume = volume; server_request(__this->dec_server, AUDIO_REQ_DEC, &req); #ifdef CONFIG_STORE_VOLUME syscfg_write(CFG_MUSIC_VOL, &__this->volume, sizeof(__this->volume)); #endif if (__this->ai_server) { ai.evt.event = AI_EVENT_VOLUME_CHANGE; ai.evt.arg = __this->volume; ai.evt.ai_name = __this->ai_name; return ai_server_request(__this->ai_server, AI_REQ_EVENT, &ai); } return 0; } //获取解码器状态 static int net_music_get_dec_status(void) { union audio_req req = {0}; req.dec.cmd = AUDIO_DEC_GET_STATUS; server_request(__this->dec_server, AUDIO_REQ_DEC, &req); return req.dec.status; } //快进快退,单位是秒,暂时只支持MP3格式 static int net_music_dec_seek(int seek_step) { int err; union audio_req r = {0}; if (0 == seek_step) { return 0; } if (__this->total_time != 0 && __this->total_time != -1) { if (__this->play_time + seek_step <= 0 || __this->play_time + seek_step >= __this->total_time) { log_e("local music seek out of range\n"); return -1; } } if (seek_step > 0) { r.dec.cmd = AUDIO_DEC_FF; r.dec.ff_fr_step = seek_step; } else { r.dec.cmd = AUDIO_DEC_FR; r.dec.ff_fr_step = -seek_step; } log_i("net music seek step : %d\n", seek_step); return server_request(__this->dec_server, AUDIO_REQ_DEC, &r); } static void dec_server_event_handler(void *priv, int argc, int *argv) { switch (argv[0]) { case AUDIO_SERVER_EVENT_ERR: log_i("net_music: AUDIO_SERVER_EVENT_ERR\n"); case AUDIO_SERVER_EVENT_END: log_i("net_music: AUDIO_SERVER_EVENT_END\n"); net_music_dec_end(); break; case AUDIO_SERVER_EVENT_CURR_TIME: log_d("play_time: %d\n", argv[1]); __this->play_time = argv[1]; break; } } //第三方平台的事件通知回调 static void ai_server_event_handler(void *priv, int argc, int *argv) { if (!__this->ai_server) { switch (argv[0]) { case AI_SERVER_EVENT_URL: free((void *)argv[1]); break; } return; } switch (argv[0]) { case AI_SERVER_EVENT_CONNECTED: break; case AI_SERVER_EVENT_DISCONNECTED: break; case AI_SERVER_EVENT_URL: case AI_SERVER_EVENT_URL_TTS: case AI_SERVER_EVENT_URL_MEDIA: __this->total_time = 0; //清空上一首歌的信息 __this->ai_name = (const char *)argv[2]; const char *url = (const char *)argv[1]; free(__this->url); __this->url = malloc(strlen(url) + 1); if (__this->url) { strcpy(__this->url, url); } net_music_dec_file(url); break; case AI_SERVER_EVENT_CONTINUE: if (AUDIO_DEC_PAUSE == net_music_get_dec_status()) { net_music_dec_play_pause(0); } break; case AI_SERVER_EVENT_PAUSE: if (AUDIO_DEC_START == net_music_get_dec_status()) { net_music_dec_play_pause(0); } break; case AI_SERVER_EVENT_STOP: net_music_dec_stop(); break; case AI_SERVER_EVENT_RESUME_PLAY: break; case AI_SERVER_EVENT_SEEK: net_music_dec_seek(argv[1] - __this->play_time); break; case AI_SERVER_EVENT_VOLUME_CHANGE: net_music_set_dec_volume(argv[1] - __this->volume); break; case AI_SERVER_EVENT_SET_PLAY_TIME: __this->play_time = argv[1]; break; default: break; } } static int net_music_mode_init(void) { log_i("net_music_play_main\n"); memset(__this, 0, sizeof(struct net_music_hdl)); #ifdef CONFIG_STORE_VOLUME if (syscfg_read(CFG_MUSIC_VOL, &__this->volume, sizeof(__this->volume)) < 0 || __this->volume < MIN_VOLUME_VALUE || __this->volume > MAX_VOLUME_VALUE) { __this->volume = INIT_VOLUME_VALUE; } #else __this->volume = INIT_VOLUME_VALUE; #endif if (__this->volume < 0 || __this->volume > MAX_VOLUME_VALUE) { __this->volume = INIT_VOLUME_VALUE; } __this->ai_name = "unknown"; __this->dec_server = server_open("audio_server", "dec"); if (!__this->dec_server) { return -1; } server_register_event_handler_to_task(__this->dec_server, NULL, dec_server_event_handler, "app_core"); if (lwip_dhcp_bound()) { __this->ai_server = server_open("ai_server", NULL); if (__this->ai_server) { union ai_req req = {0}; server_register_event_handler_to_task(__this->ai_server, NULL, ai_server_event_handler, "app_core"); ai_server_request(__this->ai_server, AI_REQ_CONNECT, &req); } } return 0; } static void net_music_mode_exit(void) { net_music_dec_stop(); server_close(__this->dec_server); __this->dec_server = NULL; if (__this->ai_server) { server_close(__this->ai_server); __this->ai_server = NULL; } free(__this->url); __this->url = NULL; } static int net_music_key_click(struct key_event *key) { int ret = true; switch (key->value) { case KEY_OK: net_music_dec_play_pause(1); break; case KEY_VOLUME_DEC: net_music_set_dec_volume(-VOLUME_STEP); break; case KEY_VOLUME_INC: net_music_set_dec_volume(VOLUME_STEP); break; default: ret = false; break; } return ret; } static int net_music_key_long(struct key_event *key) { switch (key->value) { case KEY_OK: /* net_music_dec_file(""); */ break; case KEY_VOLUME_DEC: net_music_dec_switch_file(FSEL_PREV_FILE); break; case KEY_VOLUME_INC: net_music_dec_switch_file(FSEL_NEXT_FILE); break; case KEY_MODE: net_music_get_dec_breakpoint(&__this->dec_bp); break; default: break; } return true; } static int net_music_key_event_handler(struct key_event *key) { switch (key->action) { case KEY_EVENT_CLICK: return net_music_key_click(key); case KEY_EVENT_LONG: return net_music_key_long(key); default: break; } return true; } static int net_music_net_event_handler(struct net_event *event) { switch (event->event) { case NET_EVENT_CONNECTED: if (!__this->ai_server) { __this->ai_server = server_open("ai_server", NULL); if (__this->ai_server) { union ai_req req = {0}; server_register_event_handler_to_task(__this->ai_server, NULL, ai_server_event_handler, "app_core"); ai_server_request(__this->ai_server, AI_REQ_CONNECT, &req); } } break; default: break; } return false; } static int net_music_event_handler(struct application *app, struct sys_event *event) { switch (event->type) { case SYS_KEY_EVENT: return net_music_key_event_handler((struct key_event *)event->payload); case SYS_NET_EVENT: return net_music_net_event_handler((struct net_event *)event->payload); default: return false; } } static int net_music_state_machine(struct application *app, enum app_state state, struct intent *it) { switch (state) { case APP_STA_CREATE: break; case APP_STA_START: net_music_mode_init(); break; case APP_STA_PAUSE: break; case APP_STA_RESUME: break; case APP_STA_STOP: net_music_mode_exit(); break; case APP_STA_DESTROY: break; } return 0; } static const struct application_operation net_music_ops = { .state_machine = net_music_state_machine, .event_handler = net_music_event_handler, }; REGISTER_APPLICATION(net_music) = { .name = "net_music", .ops = &net_music_ops, .state = APP_STA_DESTROY, }; #endif #endif//USE_AUDIO_DEMO