需求:选中多个播放终端,通过会议呼叫多个终端,在呼叫接通后,播放指定的音乐文件。
思路:通过动态拨号计划,下发播放指令和指定的终端进行文件播放。
PHP控制的拨号计划:
//通过conference_inject_music_play控制播放循环和播放曲目个数。 $this->Gateway_XML .= "\n<action application=\"conference_inject_music_play\" data=\"repeat=1&count=2\"/>"; //需要修改主叫时,是sendonly $this->Gateway_XML .= "\n<action application=\"conference_inject_music_url\" data=\"/tmp/123.wav,/tmp/456.wav\"/>"; //根据会议中的人员动态添加呼叫的对象 $this->Gateway_XML .= "\n<action application=\"conference_set_auto_outcall\" data=\"user/\${dialed_extension}@\${domain_name}\"/>"; //进入会议 $this->Gateway_XML .= "\n<action application=\"conference\" data=\"999$1@default\"/>";
修改conference_mod.c,添加conference_inject_music_api和conference_inject_music_url_api两个api
SWITCH_STANDARD_APP(conference_inject_music_api) { switch_channel_t *channel = switch_core_session_get_channel(session); char *play_url_string = NULL; play_url_string = switch_channel_get_private(channel, "_conference_inject_music_play_"); if (zstr(data)) { play_url_string = NULL; } else { int repeat = 0; int mp3_count = 0; int count = 0; play_url_string = switch_core_session_strdup(session, data); count = sscanf((char * )play_url_string, "repeat=%d&count=%d", &repeat, &mp3_count); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "play_url_string:%s,count:%d, mp3_count:%d, repeat=%d.\n", play_url_string, count, mp3_count, repeat); } switch_channel_set_private(channel, "_conference_inject_music_play_", play_url_string); } SWITCH_STANDARD_APP(conference_inject_music_url_api) { switch_channel_t *channel = switch_core_session_get_channel(session); char *play_url_string = NULL; int repeat = 0; int mp3_count = 0; play_url_string = switch_channel_get_private(channel, "_conference_inject_music_play_"); if (play_url_string != NULL){ int count = 0; count = sscanf((char * )play_url_string, "repeat=%d&count=%d", &repeat, &mp3_count); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "conference_inject_music_url_api :%s,count:%d, mp3_count:%d, repeat=%d.\n", play_url_string, count, mp3_count, repeat); } if (zstr(data)) { play_url_string = NULL; } else { char *token; char *saveptr; char name_url[128]; char *play_url_list = switch_core_session_strdup(session, data); int i=0; token = strtok_r(play_url_list, ",", &saveptr); while (token) { sprintf(name_url, "_conference_inject_music_play_%d", i++); switch_channel_set_private(channel, name_url, token); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "name_url:%s,name_url=%s.\n", name_url, token); token = strtok_r(NULL, ",", &saveptr); } } }
修改:给会议根据播放控制动态播放音乐文件。
/* marshall frames from the call leg to the conference thread for muxing to other call legs */ void *SWITCH_THREAD_FUNC conference_loop_music_play(switch_thread_t *thread, void *obj) { conference_member_t *member = obj; switch_channel_t *channel = NULL; char name_url[128]; int repeat = 0; int mp3_count = 0; int count = 0; int i = 0; char *play_url_string; channel = switch_core_session_get_channel(member->session); play_url_string = switch_channel_get_private(channel, "_conference_inject_music_play_"); if (play_url_string == NULL){ return NULL; } count = sscanf((char * )play_url_string, "repeat=%d&count=%d", &repeat, &mp3_count); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "conference_loop_music_play loop:%s,count:%d, mp3_count:%d, repeat=%d.\n", play_url_string, count, mp3_count, repeat); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "conference_loop_music_play loop: %d running:%d, read:%d \n", member->loop_loop, conference_utils_member_test_flag(member, MFLAG_RUNNING), switch_channel_ready(channel)); while (conference_utils_member_test_flag(member, MFLAG_RUNNING) && switch_channel_ready(channel)) { char *play_url_path = NULL; const char *temp = NULL; sprintf(name_url, "_conference_inject_music_play_%d", i++); temp = switch_channel_get_private(channel, name_url); if (temp == NULL){ break; } play_url_path = switch_core_session_strdup(member->session, temp); conference_file_play(member->conference, (char *)play_url_path, CONF_DEFAULT_LEADIN, NULL, 0); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "start play:%s \n", play_url_path); //conference_file_local_play(member->conference, //member->session, (char *)play_url_path, CONF_DEFAULT_LEADIN, NULL, 0); switch_sleep(5000000); if (i == mp3_count){ if (repeat != 0){ i = 0; }else{ break; } } } switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "conference_loop_music_play end.\n"); conference_utils_member_clear_flag_locked(member, MFLAG_ITHREAD); return NULL; } /* launch an music thread for the conference */ void conference_loop_launch_music_play(conference_member_t *member, switch_memory_pool_t *pool) { switch_threadattr_t *thd_attr = NULL; if (member == NULL || member->music_thread) return; switch_threadattr_create(&thd_attr, pool); switch_threadattr_stacksize_set(thd_attr, SWITCH_THREAD_STACKSIZE); conference_utils_member_set_flag_locked(member, MFLAG_ITHREAD); if (switch_thread_create(&member->music_thread, thd_attr, conference_loop_music_play, member, pool) != SWITCH_STATUS_SUCCESS) { conference_utils_member_clear_flag_locked(member, MFLAG_ITHREAD); } } 在conference_loop_output的合适地方添加下面的代码。 #if 1//start a thread to play files { char *play_url_string = switch_channel_get_private(channel, "_conference_inject_music_play_"); if (play_url_string != NULL){ int repeat = 0; int mp3_count = 0; int count = 0; count = sscanf((char * )play_url_string, "repeat=%d&count=%d", &repeat, &mp3_count); switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "loop:%s,count:%d, mp3_count:%d, repeat=%d.\n", play_url_string, count, mp3_count, repeat); if (count > 0){ conference_loop_launch_music_play(member, switch_core_session_get_pool(member->session)); } }else{ switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "play_url_string is null.\n"); } } #endif//add for play mp3 in conference
验证OK。
但是格式只支持wav,后面使用playback的功能播放mp3文件。
-------------------广告线---------------
项目、合作,欢迎勾搭,邮箱:promall@qq.com
本文为呱牛笔记原创文章,转载无需和我联系,但请注明来自呱牛笔记 ,it3q.com