需求:选中多个播放终端,通过会议呼叫多个终端,在呼叫接通后,播放指定的音乐文件。
思路:通过动态拨号计划,下发播放指令和指定的终端进行文件播放。
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
