/*================================================================ * Copyright (C) 2018 AISPEECH Ltd. All rights reserved. * * 文件名称:music.c * 创 建 者:chenjie.gu * 创建日期:2018年05月24日 * 描 述: * ================================================================*/ #include #include #include #include "audio_player.h" #include #include "cJSON.h" #include #include #include audio_player_t *aplayer = NULL; float vol_multiplier = 0.5; int vol_system = 70; int player_is_end = 0; pthread_mutex_t music_mutex; int play_judge_f(int index, int count, int mode); static int g_player_ev = AUDIO_PLAYER_EV_END; void play_manager_f(const char *cmd, const char *data, char **user_data); bool music_is_playing(void) { if (g_player_ev == AUDIO_PLAYER_EV_END || g_player_ev == AUDIO_PLAYER_EV_ERROR || g_player_ev == AUDIO_PLAYER_EV_STOPPED) return false; else return true; } static int play_callback(void *userdata, int ev) { printf("++++++%s: ev %d\n", __func__, ev); if (ev == AUDIO_PLAYER_EV_END) { player_is_end = 1; } g_player_ev = ev; return 0; } void *player_routine(void *user) { while (1) { if (player_is_end) { player_is_end = 0; play_manager_f("player.end", NULL, NULL); } usleep(100 * 1000); } return (void *)0; } int music_player_init(char *dev) { aplayer = audio_player_new(play_callback, NULL); audio_player_set_device(aplayer, dev); audio_player_set_channel_volume(aplayer, vol_multiplier); pthread_mutex_init(&music_mutex, NULL); system("amixer cset name='Master Playback Volume' 70"); return 0; } int music_player_play(char *path) { audio_player_play(aplayer, path); } int music_player_start() { int ret; pthread_t tid; pthread_create(&tid, NULL, player_routine, NULL); return 0; } static void send_vol_update_topic (int vol) { printf("send_vol_update_topic vol is %d\n", vol); char out[128] = {0}; sprintf(out, "{\"volume\":\"%d\"}", vol); printf("send_vol_update_topic is %s\n", out); busserver_send_msg("ui.control.topics.response", out); } static void send_music_update_topic(int change, int status, int mode, int index, cJSON *list) { printf("send_music_update_topic %d %d %d %d %p\n", change, status, mode, index, list); char *out; cJSON *root, *root2; char *music; root = cJSON_CreateObject(); root2 = cJSON_CreateObject(); cJSON_AddNumberToObject(root, "change", change); cJSON_AddNumberToObject(root, "status", status); cJSON_AddNumberToObject(root, "mode", mode); cJSON_AddNumberToObject(root, "currentIndex", index); if (list) { cJSON *tmp = cJSON_GetObjectItem(list, "content"); cJSON_AddItemReferenceToObject(root, "list", tmp); } music = cJSON_PrintUnformatted(root); cJSON_Delete(root); cJSON_AddStringToObject(root2, "music", music); out = cJSON_PrintUnformatted(root2); cJSON_Delete(root2); printf("send_music_update_topic is %s\n", out); busserver_send_msg("ui.control.topics.response", out); free(music); free(out); } void play_manager_f(const char *cmd, const char *data, char **user_data) { /* * 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 * 12. music.info */ enum PLAY_MODE { sequence, random, single, loop }; enum PLAY_STATUS { idle, playing, pause }; static enum PLAY_MODE mode = sequence; static enum PLAY_STATUS status = idle; static int count = 0; static int index = 0; static int old_index = 0; static cJSON *root = NULL; printf("play_manager_f cmd: %s\tdata: %s\n", cmd, data); pthread_mutex_lock(&music_mutex); if (!strcmp(cmd, "volume.set")) { // 设置音量 if (!strcmp(data, "+")) { vol_system += 10; if (vol_system > 100) vol_system = 100; } else if (!strcmp(data, "-")) { vol_system -= 10; if (vol_system < 0) vol_system = 0; } else { vol_system = atoi(data); } char cmd[64] = {0}; sprintf(cmd, "amixer cset name='Master Playback Volume' %d", vol_system); system(cmd); printf("set vol to %d\n", vol_system); send_vol_update_topic(vol_system); } else if (!strcmp(cmd, "play.list.clear")) { // 清空播放列表 printf("clear the play list info\n"); audio_player_stop(aplayer); cJSON_Delete(root); root = NULL; index = 0; old_index = 0; count = 0; status = idle; send_music_update_topic(0, status, mode, index, NULL); } else if (!strcmp(cmd, "play.list.get")) { } else if (!strcmp(cmd, "music.info")) { if (root) { cJSON *temp, *music; music = cJSON_GetObjectItem(root, "content"); temp = cJSON_GetArrayItem(music, index); *user_data = cJSON_Print(temp); } else *user_data = NULL; } else if (!strcmp(cmd, "play.list.check")) { // 开始真正播放 cJSON *temp, *music; if (root) { if (status == idle) { temp = cJSON_GetObjectItem(root, "count"); count = temp->valueint; if (count > 0) { status = playing; music = cJSON_GetObjectItem(root, "content"); temp = cJSON_GetArrayItem(music, index); temp = cJSON_GetObjectItem(temp, "linkUrl"); printf("ready to play url is %s\n", temp->valuestring); audio_player_play(aplayer, temp->valuestring); } } else if (status == pause) { status = playing; audio_player_resume(aplayer); } send_music_update_topic(0, status, mode, index, root); } else send_music_update_topic(0, status, mode, index, NULL); } else if (!strcmp(cmd, "play.list.update")) { // 更新播放列表 // TODO: update printf("update the play list info\n"); audio_player_stop(aplayer); if (root) cJSON_Delete(root); root = NULL; index = 0; old_index = 0; count = 0; status = idle; root = cJSON_Parse(data); } else if (!strcmp(cmd, "status.set")) { // 设置播放状态 printf("status.set data is %s status is %d\n", data, status); if (!strcmp(data, "pause") && status == playing) { status = pause; audio_player_pause(aplayer); } else if (!strcmp(data, "resume") && status == pause) { status = playing; audio_player_resume(aplayer); } else if (!strcmp(data, "replay") && status == pause) { status = playing; } else if (!strcmp(data, "step")) { if (status == playing) { status = pause; audio_player_pause(aplayer); } else if (status == pause) { status = playing; audio_player_resume(aplayer); } } send_music_update_topic(0, status, mode, index, root); } else if (!strcmp(cmd, "mode.set")) { // 播放模式 if (!strcmp(data, "sequence")) mode = sequence; else if (!strcmp(data, "random")) mode = random; else if (!strcmp(data, "single")) mode = single; else if (!strcmp(data, "loop")) mode = loop; send_music_update_topic(0, status, mode, index, root); } else if (!strcmp(cmd, "change.set")) { // 歌曲切换 // TODO: update if (!strcmp(data, "prev")) { // 上一首 index = old_index; } else if (!strcmp(data, "next")) { // 下一首 old_index = index; index = play_judge_f(index, count, mode); } else if (!strcmp(data, "change")) { // 换一首 old_index = index; index = play_judge_f(index, count, mode); } if (index == -1) { // 播放结束 cJSON_Delete(root); audio_player_stop(aplayer); root = NULL; index = 0; old_index = 0; count = 0; status = idle; } else { // 待播放指定的音频 status = idle; } } else if (!strcmp(cmd, "play.choose.update")) { // 播放特定歌曲 old_index = index; index = atoi(data); cJSON *temp, *music; music = cJSON_GetObjectItem(root, "content"); temp = cJSON_GetArrayItem(music, index); temp = cJSON_GetObjectItem(temp, "linkUrl"); printf("ready to play url is %s\n", temp->valuestring); audio_player_stop(aplayer); audio_player_play(aplayer, temp->valuestring); send_music_update_topic(0, status, mode, index, root); } else if (!strcmp(cmd, "play.collect.choose")) { // 收藏歌曲 } else if (!strcmp(cmd, "play.uncollect.choose")) { // 取消收藏 } else if (!strcmp(cmd, "player.end") && root) { // 播放器播放结束 // TODO: update old_index = index; index = play_judge_f(index, count, mode); printf("play_judge_f index is %d\n", index); if (index == -1) { // 播放结束 audio_player_stop(aplayer); cJSON_Delete(root); root = NULL; index = 0; old_index = 0; count = 0; status = idle; send_music_update_topic(0, status, mode, index, NULL); } else { // 播放指定的音频 cJSON *temp, *music; music = cJSON_GetObjectItem(root, "content"); temp = cJSON_GetArrayItem(music, index); temp = cJSON_GetObjectItem(temp, "linkUrl"); printf("ready to play url is %s\n", temp->valuestring); audio_player_stop(aplayer); audio_player_play(aplayer, temp->valuestring); send_music_update_topic(0, status, mode, index, root); } } pthread_mutex_unlock(&music_mutex); } int play_judge_f(int index, int count, int mode) { // sequence, random, single, loop if (mode == 0) { // 顺序播放 if (index + 1 == count) return -1; else return index + 1; } else if (mode == 1) { // 随机播放 srand(time(0)); return rand() % count; } else if (mode == 2) { // 单曲循环 return index; } else if (mode == 3) { // 循环播放 return (index + 1) % count; } else return -1; }