35 #include "include/confbridge.h"
711 static int verify_default_profiles(
void);
712 static void *bridge_profile_alloc(
const char *category);
716 static void bridge_profile_destructor(
void *obj)
719 ao2_cleanup(b_profile->sounds);
722 static void *bridge_profile_alloc(
const char *category)
726 if (!(b_profile = ao2_alloc(
sizeof(*b_profile), bridge_profile_destructor))) {
730 if (!(b_profile->sounds = bridge_profile_sounds_alloc())) {
742 return ao2_find(container, category,
OBJ_KEY);
745 static struct aco_type bridge_type = {
747 .name =
"bridge_profile",
749 .category =
"general",
750 .matchfield =
"type",
751 .matchvalue =
"bridge",
752 .item_alloc = bridge_profile_alloc,
753 .item_find = bridge_profile_find,
757 static void *user_profile_alloc(
const char *category);
759 static void user_profile_destructor(
void *obj)
764 static void *user_profile_alloc(
const char *category)
768 if (!(u_profile = ao2_alloc(
sizeof(*u_profile), user_profile_destructor))) {
779 return ao2_find(container, category,
OBJ_KEY);
782 static struct aco_type user_type = {
784 .name =
"user_profile",
786 .category =
"general",
787 .matchfield =
"type",
788 .matchvalue =
"user",
789 .item_alloc = user_profile_alloc,
790 .item_find = user_profile_find,
794 static void *menu_alloc(
const char *category);
796 static void menu_destructor(
void *obj);
798 static void *menu_alloc(
const char *category)
801 if (!(menu = ao2_alloc(
sizeof(*menu), menu_destructor))) {
810 return ao2_find(container, category,
OBJ_KEY);
813 static struct aco_type menu_type = {
817 .category =
"general",
818 .matchfield =
"type",
819 .matchvalue =
"menu",
820 .item_alloc = menu_alloc,
821 .item_find = menu_find,
831 static struct aco_type general_type = {
835 .category =
"general",
838 static struct aco_file confbridge_conf = {
840 .types =
ACO_TYPES(&bridge_type, &user_type, &menu_type, &general_type),
845 static void *confbridge_cfg_alloc(
void);
848 .files = ACO_FILES(&confbridge_conf),
849 .pre_apply_config = verify_default_profiles,
857 const char *right_name = arg;
863 right_name = right->name;
866 cmp = strcasecmp(left->name, right_name);
869 cmp = strncasecmp(left->name, right_name, strlen(right_name));
875 static int bridge_hash_cb(
const void *obj,
const int flags)
878 const char *name = obj;
884 name = b_profile->name;
903 const char *right_name = arg;
909 right_name = right->name;
912 cmp = strcasecmp(left->name, right_name);
915 cmp = strncasecmp(left->name, right_name, strlen(right_name));
921 static int menu_hash_cb(
const void *obj,
const int flags)
924 const char *name = obj;
944 static void menu_destructor(
void *obj)
960 const char *right_name = arg;
966 right_name = right->name;
969 cmp = strcasecmp(left->name, right_name);
972 cmp = strncasecmp(left->name, right_name, strlen(right_name));
978 static int user_hash_cb(
const void *obj,
const int flags)
981 const char *name = obj;
987 name = u_profile->name;
1023 static int set_sound(
const char *sound_name,
const char *sound_file,
struct bridge_profile *b_profile)
1026 if (ast_strlen_zero(sound_file)) {
1030 if (!strcasecmp(sound_name,
"sound_only_person")) {
1032 }
else if (!strcasecmp(sound_name,
"sound_only_one")) {
1034 }
else if (!strcasecmp(sound_name,
"sound_has_joined")) {
1036 }
else if (!strcasecmp(sound_name,
"sound_has_left")) {
1038 }
else if (!strcasecmp(sound_name,
"sound_kicked")) {
1040 }
else if (!strcasecmp(sound_name,
"sound_muted")) {
1042 }
else if (!strcasecmp(sound_name,
"sound_unmuted")) {
1044 }
else if (!strcasecmp(sound_name,
"sound_binaural_on")) {
1046 }
else if (!strcasecmp(sound_name,
"sound_binaural_off")) {
1048 }
else if (!strcasecmp(sound_name,
"sound_there_are")) {
1050 }
else if (!strcasecmp(sound_name,
"sound_other_in_party")) {
1052 }
else if (!strcasecmp(sound_name,
"sound_place_into_conference")) {
1053 static int deprecation_warning = 1;
1054 if (deprecation_warning) {
1055 ast_log(LOG_WARNING,
"sound_place_into_conference is deprecated"
1056 " and unused. Use sound_begin for similar functionality.");
1057 deprecation_warning = 0;
1060 }
else if (!strcasecmp(sound_name,
"sound_wait_for_leader")) {
1062 }
else if (!strcasecmp(sound_name,
"sound_leader_has_left")) {
1064 }
else if (!strcasecmp(sound_name,
"sound_get_pin")) {
1066 }
else if (!strcasecmp(sound_name,
"sound_invalid_pin")) {
1068 }
else if (!strcasecmp(sound_name,
"sound_locked")) {
1070 }
else if (!strcasecmp(sound_name,
"sound_unlocked_now")) {
1072 }
else if (!strcasecmp(sound_name,
"sound_locked_now")) {
1074 }
else if (!strcasecmp(sound_name,
"sound_error_menu")) {
1076 }
else if (!strcasecmp(sound_name,
"sound_join")) {
1078 }
else if (!strcasecmp(sound_name,
"sound_leave")) {
1080 }
else if (!strcasecmp(sound_name,
"sound_participants_muted")) {
1082 }
else if (!strcasecmp(sound_name,
"sound_participants_unmuted")) {
1084 }
else if (!strcasecmp(sound_name,
"sound_begin")) {
1106 ao2_cleanup(b_data->menu);
1110 static void func_confbridge_destroy_cb(
void *data)
1113 func_confbridge_data_destructor(b_data);
1117 .
type =
"confbridge",
1118 .destroy = func_confbridge_destroy_cb
1121 int func_confbridge_helper(
struct ast_channel *chan,
const char *cmd,
char *data,
const char *value)
1129 .file =
"CONFBRIDGE"
1137 ast_log(LOG_WARNING,
"No channel was provided to %s function.\n", cmd);
1142 if (ast_strlen_zero(data)) {
1147 if (ast_strlen_zero(args.type) || ast_strlen_zero(args.option)) {
1151 ast_channel_lock(chan);
1154 datastore = ast_datastore_alloc(&confbridge_datastore, NULL);
1156 ast_channel_unlock(chan);
1161 ast_channel_unlock(chan);
1165 datastore->
data = b_data;
1166 b_data->b_profile.sounds = bridge_profile_sounds_alloc();
1167 if (!b_data->b_profile.sounds) {
1168 ast_channel_unlock(chan);
1172 if (!(b_data->menu = menu_alloc(
"dialplan"))) {
1173 ast_channel_unlock(chan);
1179 b_data = datastore->
data;
1181 ast_channel_unlock(chan);
1187 tmpvar.
name = args.option;
1189 tmpvar.
file =
"CONFBRIDGE";
1190 if (!strcasecmp(args.type,
"bridge")) {
1191 if (!strcasecmp(args.option,
"clear")) {
1194 memset(&b_data->b_profile, 0,
sizeof(b_data->b_profile)) ;
1195 if (!(b_data->b_profile.sounds = bridge_profile_sounds_alloc())) {
1197 ast_channel_lock(chan);
1199 ast_channel_unlock(chan);
1205 if (b_data && !b_data->
b_usable && strcasecmp(args.option,
"template")) {
1206 template.value = DEFAULT_BRIDGE_PROFILE;
1207 aco_process_var(&bridge_type,
"dialplan", &
template, &b_data->b_profile);
1210 if (!
aco_process_var(&bridge_type,
"dialplan", &tmpvar, &b_data->b_profile)) {
1214 }
else if (!strcasecmp(args.type,
"user")) {
1215 if (!strcasecmp(args.option,
"clear")) {
1217 user_profile_destructor(&b_data->u_profile);
1218 memset(&b_data->u_profile, 0,
sizeof(b_data->u_profile));
1222 if (b_data && !b_data->
u_usable && strcasecmp(args.option,
"template")) {
1223 template.value = DEFAULT_USER_PROFILE;
1224 aco_process_var(&user_type,
"dialplan", &
template, &b_data->u_profile);
1227 if (!
aco_process_var(&user_type,
"dialplan", &tmpvar, &b_data->u_profile)) {
1231 }
else if (!strcasecmp(args.type,
"menu")) {
1232 if (!strcasecmp(args.option,
"clear")) {
1234 ao2_cleanup(b_data->menu);
1235 if (!(b_data->menu = menu_alloc(
"dialplan"))) {
1237 ast_channel_lock(chan);
1239 ast_channel_unlock(chan);
1245 if (b_data && !b_data->
m_usable && strcasecmp(args.option,
"template")) {
1246 template.value = DEFAULT_MENU_PROFILE;
1250 if (!
aco_process_var(&menu_type,
"dialplan", &tmpvar, b_data->menu)) {
1256 ast_log(LOG_WARNING,
"%s(%s,%s) cannot be set to '%s'. Invalid type, option, or value.\n",
1257 cmd, args.type, args.option, value);
1261 static int add_action_to_menu_entry(
struct conf_menu_entry *menu_entry,
enum conf_menu_action_id
id,
char *databuf)
1268 menu_action->id = id;
1271 case MENU_ACTION_NOOP:
1272 case MENU_ACTION_TOGGLE_MUTE:
1273 case MENU_ACTION_TOGGLE_BINAURAL:
1274 case MENU_ACTION_INCREASE_LISTENING:
1275 case MENU_ACTION_DECREASE_LISTENING:
1276 case MENU_ACTION_INCREASE_TALKING:
1277 case MENU_ACTION_DECREASE_TALKING:
1278 case MENU_ACTION_RESET_LISTENING:
1279 case MENU_ACTION_RESET_TALKING:
1280 case MENU_ACTION_ADMIN_TOGGLE_LOCK:
1281 case MENU_ACTION_ADMIN_TOGGLE_MUTE_PARTICIPANTS:
1282 case MENU_ACTION_PARTICIPANT_COUNT:
1283 case MENU_ACTION_ADMIN_KICK_LAST:
1284 case MENU_ACTION_LEAVE:
1285 case MENU_ACTION_SET_SINGLE_VIDEO_SRC:
1286 case MENU_ACTION_RELEASE_SINGLE_VIDEO_SRC:
1288 case MENU_ACTION_PLAYBACK:
1289 case MENU_ACTION_PLAYBACK_AND_CONTINUE:
1290 if (!(ast_strlen_zero(databuf))) {
1291 ast_copy_string(menu_action->data.playback_file, databuf,
sizeof(menu_action->data.playback_file));
1293 ast_free(menu_action);
1297 case MENU_ACTION_DIALPLAN_EXEC:
1298 if (!(ast_strlen_zero(databuf))) {
1305 if (!ast_strlen_zero(args.context)) {
1308 sizeof(menu_action->data.dialplan_args.context));
1310 if (!ast_strlen_zero(args.exten)) {
1313 sizeof(menu_action->data.dialplan_args.exten));
1315 menu_action->data.dialplan_args.priority = 1;
1316 if (!ast_strlen_zero(args.priority) &&
1317 (sscanf(args.priority,
"%30d", &menu_action->data.dialplan_args.priority) != 1)) {
1319 ast_free(menu_action);
1323 ast_free(menu_action);
1333 static int add_menu_entry(
struct conf_menu *menu,
const char *dtmf,
const char *action_names)
1337 char *tmp_action_names =
ast_strdupa(action_names);
1338 char *action = NULL;
1342 char *delimiter =
",";
1344 if (!(menu_entry =
ast_calloc(1,
sizeof(*menu_entry)))) {
1352 unsigned int action_len;
1354 if (ast_strlen_zero(tmp_action_names)) {
1357 startbrace = strchr(tmp_action_names,
'(');
1358 endbrace = strchr(tmp_action_names,
')');
1359 comma = strchr(tmp_action_names,
',');
1363 if (startbrace && endbrace && comma && (comma > startbrace && comma < endbrace)) {
1369 if (!(action = strsep(&tmp_action_names, delimiter))) {
1374 if (ast_strlen_zero(action)) {
1378 action_len = strlen(action);
1380 if (!strcasecmp(action,
"toggle_mute")) {
1381 res |= add_action_to_menu_entry(menu_entry, MENU_ACTION_TOGGLE_MUTE, NULL);
1382 }
else if (!strcasecmp(action,
"toggle_binaural")) {
1383 res |= add_action_to_menu_entry(menu_entry, MENU_ACTION_TOGGLE_BINAURAL, NULL);
1384 }
else if (!strcasecmp(action,
"no_op")) {
1385 res |= add_action_to_menu_entry(menu_entry, MENU_ACTION_NOOP, NULL);
1386 }
else if (!strcasecmp(action,
"increase_listening_volume")) {
1387 res |= add_action_to_menu_entry(menu_entry, MENU_ACTION_INCREASE_LISTENING, NULL);
1388 }
else if (!strcasecmp(action,
"decrease_listening_volume")) {
1389 res |= add_action_to_menu_entry(menu_entry, MENU_ACTION_DECREASE_LISTENING, NULL);
1390 }
else if (!strcasecmp(action,
"increase_talking_volume")) {
1391 res |= add_action_to_menu_entry(menu_entry, MENU_ACTION_INCREASE_TALKING, NULL);
1392 }
else if (!strcasecmp(action,
"reset_listening_volume")) {
1393 res |= add_action_to_menu_entry(menu_entry, MENU_ACTION_RESET_LISTENING, NULL);
1394 }
else if (!strcasecmp(action,
"reset_talking_volume")) {
1395 res |= add_action_to_menu_entry(menu_entry, MENU_ACTION_RESET_TALKING, NULL);
1396 }
else if (!strcasecmp(action,
"decrease_talking_volume")) {
1397 res |= add_action_to_menu_entry(menu_entry, MENU_ACTION_DECREASE_TALKING, NULL);
1398 }
else if (!strcasecmp(action,
"admin_toggle_conference_lock")) {
1399 res |= add_action_to_menu_entry(menu_entry, MENU_ACTION_ADMIN_TOGGLE_LOCK, NULL);
1400 }
else if (!strcasecmp(action,
"admin_toggle_mute_participants")) {
1401 res |= add_action_to_menu_entry(menu_entry, MENU_ACTION_ADMIN_TOGGLE_MUTE_PARTICIPANTS, NULL);
1402 }
else if (!strcasecmp(action,
"participant_count")) {
1403 res |= add_action_to_menu_entry(menu_entry, MENU_ACTION_PARTICIPANT_COUNT, NULL);
1404 }
else if (!strcasecmp(action,
"admin_kick_last")) {
1405 res |= add_action_to_menu_entry(menu_entry, MENU_ACTION_ADMIN_KICK_LAST, NULL);
1406 }
else if (!strcasecmp(action,
"leave_conference")) {
1407 res |= add_action_to_menu_entry(menu_entry, MENU_ACTION_LEAVE, NULL);
1408 }
else if (!strcasecmp(action,
"set_as_single_video_src")) {
1409 res |= add_action_to_menu_entry(menu_entry, MENU_ACTION_SET_SINGLE_VIDEO_SRC, NULL);
1410 }
else if (!strcasecmp(action,
"release_as_single_video_src")) {
1411 res |= add_action_to_menu_entry(menu_entry, MENU_ACTION_RELEASE_SINGLE_VIDEO_SRC, NULL);
1412 }
else if (!strncasecmp(action,
"dialplan_exec(", 14)) {
1415 if ((action_args = strchr(action,
'('))) {
1421 if ((tmp = strchr(action,
')'))) {
1424 res |= add_action_to_menu_entry(menu_entry, MENU_ACTION_DIALPLAN_EXEC, action_args);
1425 }
else if (action_len >= 21 && !strncasecmp(action,
"playback_and_continue(", 22)) {
1428 if ((action_args = strchr(action,
'(')) && (tmp = strrchr(action_args,
')'))) {
1432 res |= add_action_to_menu_entry(menu_entry, MENU_ACTION_PLAYBACK_AND_CONTINUE, action_args);
1433 }
else if (action_len >= 8 && !strncasecmp(action,
"playback(", 9)) {
1436 if ((action_args = strchr(action,
'(')) && (tmp = strrchr(action_args,
')'))) {
1440 res |= add_action_to_menu_entry(menu_entry, MENU_ACTION_PLAYBACK, action_args);
1447 ast_free(menu_entry);
1453 if (!strcasecmp(cur->dtmf, menu_entry->
dtmf)) {
1467 static char *complete_user_profile_name(
const char *line,
const char *word,
int pos,
int state)
1471 int wordlen = strlen(word);
1481 while ((u_profile = ao2_iterator_next(&i))) {
1482 if (!strncasecmp(u_profile->name, word, wordlen) && ++which > state) {
1502 e->
command =
"confbridge show profile users";
1504 "Usage: confbridge show profile users\n";
1514 ast_cli(a->fd,
"--------- User Profiles -----------\n");
1515 ao2_lock(cfg->user_profiles);
1517 while ((u_profile = ao2_iterator_next(&it))) {
1518 ast_cli(a->fd,
"%s\n", u_profile->name);
1522 ao2_unlock(cfg->user_profiles);
1532 e->
command =
"confbridge show profile user";
1534 "Usage: confbridge show profile user [<profile name>]\n";
1538 return complete_user_profile_name(a->line, a->word, a->pos, a->n);
1544 return CLI_SHOWUSAGE;
1548 ast_cli(a->fd,
"No conference user profile named '%s' found!\n", a->argv[4]);
1552 ast_cli(a->fd,
"--------------------------------------------\n");
1553 ast_cli(a->fd,
"Name: %s\n",
1555 ast_cli(a->fd,
"Admin: %s\n",
1556 u_profile.flags & USER_OPT_ADMIN ?
1558 ast_cli(a->fd,
"Send Events: %s\n",
1559 u_profile.flags & USER_OPT_SEND_EVENTS ?
1561 ast_cli(a->fd,
"Echo Events: %s\n",
1562 u_profile.flags & USER_OPT_ECHO_EVENTS ?
1564 ast_cli(a->fd,
"Marked User: %s\n",
1565 u_profile.flags & USER_OPT_MARKEDUSER ?
1567 ast_cli(a->fd,
"Start Muted: %s\n",
1568 u_profile.flags & USER_OPT_STARTMUTED?
1570 ast_cli(a->fd,
"MOH When Empty: %s\n",
1571 u_profile.flags & USER_OPT_MUSICONHOLD ?
1572 "enabled" :
"disabled");
1573 ast_cli(a->fd,
"MOH Class: %s\n",
1574 ast_strlen_zero(u_profile.moh_class) ?
1575 "default" : u_profile.moh_class);
1576 ast_cli(a->fd,
"Announcement: %s\n",
1577 u_profile.announcement);
1578 ast_cli(a->fd,
"Quiet: %s\n",
1579 u_profile.flags & USER_OPT_QUIET ?
1580 "enabled" :
"disabled");
1581 ast_cli(a->fd,
"Hear Join: %s\n",
1582 u_profile.flags & USER_OPT_HEAR_OWN_JOIN_SOUND ?
1583 "enabled" :
"disabled");
1584 ast_cli(a->fd,
"Wait Marked: %s\n",
1585 u_profile.flags & USER_OPT_WAITMARKED ?
1586 "enabled" :
"disabled");
1587 ast_cli(a->fd,
"END Marked (All): %s\n",
1588 u_profile.flags & USER_OPT_ENDMARKED ?
1589 "enabled" :
"disabled");
1590 ast_cli(a->fd,
"END Marked (Any): %s\n",
1591 u_profile.flags & USER_OPT_ENDMARKEDANY ?
1592 "enabled" :
"disabled");
1593 ast_cli(a->fd,
"Drop_silence: %s\n",
1594 u_profile.flags & USER_OPT_DROP_SILENCE ?
1595 "enabled" :
"disabled");
1596 ast_cli(a->fd,
"Silence Threshold: %ums\n",
1598 ast_cli(a->fd,
"Talking Threshold: %u\n",
1600 ast_cli(a->fd,
"Denoise: %s\n",
1601 u_profile.flags & USER_OPT_DENOISE ?
1602 "enabled" :
"disabled");
1603 ast_cli(a->fd,
"Jitterbuffer: %s\n",
1604 u_profile.flags & USER_OPT_JITTERBUFFER ?
1605 "enabled" :
"disabled");
1606 ast_cli(a->fd,
"Talk Detect Events: %s\n",
1607 u_profile.flags & USER_OPT_TALKER_DETECT ?
1608 "enabled" :
"disabled");
1609 ast_cli(a->fd,
"DTMF Pass Through: %s\n",
1610 u_profile.flags & USER_OPT_DTMF_PASS ?
1611 "enabled" :
"disabled");
1612 ast_cli(a->fd,
"PIN: %s\n",
1613 ast_strlen_zero(u_profile.pin) ?
1614 "None" : u_profile.pin);
1615 ast_cli(a->fd,
"Announce User Count: %s\n",
1616 u_profile.flags & USER_OPT_ANNOUNCEUSERCOUNT ?
1617 "enabled" :
"disabled");
1618 ast_cli(a->fd,
"Announce join/leave: %s\n",
1619 u_profile.flags & (USER_OPT_ANNOUNCE_JOIN_LEAVE | USER_OPT_ANNOUNCE_JOIN_LEAVE_REVIEW) ?
1620 u_profile.flags & USER_OPT_ANNOUNCE_JOIN_LEAVE_REVIEW ?
1621 "enabled (with review)" :
"enabled" :
"disabled");
1622 ast_cli(a->fd,
"Announce User Count all: %s\n",
1623 u_profile.flags & USER_OPT_ANNOUNCEUSERCOUNTALL ?
1624 "enabled" :
"disabled");
1625 ast_cli(a->fd,
"Text Messaging: %s\n",
1626 u_profile.flags & USER_OPT_TEXT_MESSAGING ?
1627 "enabled" :
"disabled");
1628 ast_cli(a->fd,
"Answer Channel: %s\n",
1629 u_profile.flags & USER_OPT_ANSWER_CHANNEL ?
1631 ast_cli(a->fd,
"\n");
1636 static char *complete_bridge_profile_name(
const char *line,
const char *word,
int pos,
int state)
1640 int wordlen = strlen(word);
1650 while ((b_profile = ao2_iterator_next(&i))) {
1651 if (!strncasecmp(b_profile->name, word, wordlen) && ++which > state) {
1671 e->
command =
"confbridge show profile bridges";
1673 "Usage: confbridge show profile bridges\n";
1683 ast_cli(a->fd,
"--------- Bridge Profiles -----------\n");
1684 ao2_lock(cfg->bridge_profiles);
1686 while ((b_profile = ao2_iterator_next(&it))) {
1687 ast_cli(a->fd,
"%s\n", b_profile->name);
1691 ao2_unlock(cfg->bridge_profiles);
1703 e->
command =
"confbridge show profile bridge";
1705 "Usage: confbridge show profile bridge <profile name>\n";
1709 return complete_bridge_profile_name(a->line, a->word, a->pos, a->n);
1715 return CLI_SHOWUSAGE;
1719 ast_cli(a->fd,
"No conference bridge profile named '%s' found!\n", a->argv[4]);
1723 ast_cli(a->fd,
"--------------------------------------------\n");
1724 ast_cli(a->fd,
"Name: %s\n", b_profile.name);
1725 ast_cli(a->fd,
"Language: %s\n", b_profile.
language);
1732 ast_cli(a->fd,
"Internal Sample Rate: %s\n", tmp);
1739 ast_cli(a->fd,
"Maximum Sample Rate: %s\n", tmp);
1742 ast_cli(a->fd,
"Mixing Interval: %u\n", b_profile.
mix_interval);
1744 ast_cli(a->fd,
"Mixing Interval: Default 20ms\n");
1747 ast_cli(a->fd,
"Record Conference: %s\n",
1748 b_profile.flags & BRIDGE_OPT_RECORD_CONFERENCE ?
1751 ast_cli(a->fd,
"Record File Append: %s\n",
1752 b_profile.flags & BRIDGE_OPT_RECORD_FILE_APPEND ?
1755 ast_cli(a->fd,
"Record File Timestamp: %s\n",
1756 b_profile.flags & BRIDGE_OPT_RECORD_FILE_TIMESTAMP ?
1759 ast_cli(a->fd,
"Record File: %s\n",
1760 ast_strlen_zero(b_profile.rec_file) ?
"Auto Generated" :
1761 b_profile.rec_file);
1763 ast_cli(a->fd,
"Record Options: %s\n",
1764 b_profile.rec_options);
1766 ast_cli(a->fd,
"Record Command: %s\n",
1767 b_profile.rec_command);
1770 ast_cli(a->fd,
"Max Members: %u\n", b_profile.
max_members);
1772 ast_cli(a->fd,
"Max Members: No Limit\n");
1775 ast_cli(a->fd,
"Registration context: %s\n", b_profile.regcontext);
1777 switch (b_profile.flags
1778 & (BRIDGE_OPT_VIDEO_SRC_LAST_MARKED |
1779 BRIDGE_OPT_VIDEO_SRC_FIRST_MARKED |
1780 BRIDGE_OPT_VIDEO_SRC_FOLLOW_TALKER |
1781 BRIDGE_OPT_VIDEO_SRC_SFU)) {
1782 case BRIDGE_OPT_VIDEO_SRC_LAST_MARKED:
1783 ast_cli(a->fd,
"Video Mode: last_marked\n");
1785 case BRIDGE_OPT_VIDEO_SRC_FIRST_MARKED:
1786 ast_cli(a->fd,
"Video Mode: first_marked\n");
1788 case BRIDGE_OPT_VIDEO_SRC_FOLLOW_TALKER:
1789 ast_cli(a->fd,
"Video Mode: follow_talker\n");
1791 case BRIDGE_OPT_VIDEO_SRC_SFU:
1792 ast_cli(a->fd,
"Video Mode: sfu\n");
1795 ast_cli(a->fd,
"Video Mode: no video\n");
1806 switch (b_profile.flags
1807 & (BRIDGE_OPT_REMB_BEHAVIOR_AVERAGE | BRIDGE_OPT_REMB_BEHAVIOR_LOWEST
1808 | BRIDGE_OPT_REMB_BEHAVIOR_HIGHEST | BRIDGE_OPT_REMB_BEHAVIOR_AVERAGE_ALL
1809 | BRIDGE_OPT_REMB_BEHAVIOR_LOWEST_ALL | BRIDGE_OPT_REMB_BEHAVIOR_LOWEST_ALL)) {
1810 case BRIDGE_OPT_REMB_BEHAVIOR_AVERAGE:
1811 ast_cli(a->fd,
"REMB Behavior: average\n");
1813 case BRIDGE_OPT_REMB_BEHAVIOR_LOWEST:
1814 ast_cli(a->fd,
"REMB Behavior: lowest\n");
1816 case BRIDGE_OPT_REMB_BEHAVIOR_HIGHEST:
1817 ast_cli(a->fd,
"REMB Behavior: highest\n");
1819 case BRIDGE_OPT_REMB_BEHAVIOR_AVERAGE_ALL:
1820 ast_cli(a->fd,
"REMB Behavior: average_all\n");
1822 case BRIDGE_OPT_REMB_BEHAVIOR_LOWEST_ALL:
1823 ast_cli(a->fd,
"REMB Behavior: lowest_all\n");
1825 case BRIDGE_OPT_REMB_BEHAVIOR_HIGHEST_ALL:
1826 ast_cli(a->fd,
"REMB Behavior: highest_all\n");
1833 ast_cli(a->fd,
"Enable Events: %s\n",
1834 b_profile.flags & BRIDGE_OPT_ENABLE_EVENTS ?
1837 ast_cli(a->fd,
"sound_only_person: %s\n",
conf_get_sound(CONF_SOUND_ONLY_PERSON, b_profile.sounds));
1838 ast_cli(a->fd,
"sound_only_one: %s\n",
conf_get_sound(CONF_SOUND_ONLY_ONE, b_profile.sounds));
1839 ast_cli(a->fd,
"sound_has_joined: %s\n",
conf_get_sound(CONF_SOUND_HAS_JOINED, b_profile.sounds));
1840 ast_cli(a->fd,
"sound_has_left: %s\n",
conf_get_sound(CONF_SOUND_HAS_LEFT, b_profile.sounds));
1841 ast_cli(a->fd,
"sound_kicked: %s\n",
conf_get_sound(CONF_SOUND_KICKED, b_profile.sounds));
1842 ast_cli(a->fd,
"sound_muted: %s\n",
conf_get_sound(CONF_SOUND_MUTED, b_profile.sounds));
1843 ast_cli(a->fd,
"sound_unmuted: %s\n",
conf_get_sound(CONF_SOUND_UNMUTED, b_profile.sounds));
1844 ast_cli(a->fd,
"sound_binaural_on: %s\n",
conf_get_sound(CONF_SOUND_BINAURAL_ON, b_profile.sounds));
1845 ast_cli(a->fd,
"sound_binaural_off: %s\n",
conf_get_sound(CONF_SOUND_BINAURAL_OFF, b_profile.sounds));
1846 ast_cli(a->fd,
"sound_there_are: %s\n",
conf_get_sound(CONF_SOUND_THERE_ARE, b_profile.sounds));
1847 ast_cli(a->fd,
"sound_other_in_party: %s\n",
conf_get_sound(CONF_SOUND_OTHER_IN_PARTY, b_profile.sounds));
1848 ast_cli(a->fd,
"sound_place_into_conference: %s\n",
conf_get_sound(CONF_SOUND_PLACE_IN_CONF, b_profile.sounds));
1849 ast_cli(a->fd,
"sound_wait_for_leader: %s\n",
conf_get_sound(CONF_SOUND_WAIT_FOR_LEADER, b_profile.sounds));
1850 ast_cli(a->fd,
"sound_leader_has_left: %s\n",
conf_get_sound(CONF_SOUND_LEADER_HAS_LEFT, b_profile.sounds));
1851 ast_cli(a->fd,
"sound_get_pin: %s\n",
conf_get_sound(CONF_SOUND_GET_PIN, b_profile.sounds));
1852 ast_cli(a->fd,
"sound_invalid_pin: %s\n",
conf_get_sound(CONF_SOUND_INVALID_PIN, b_profile.sounds));
1853 ast_cli(a->fd,
"sound_locked: %s\n",
conf_get_sound(CONF_SOUND_LOCKED, b_profile.sounds));
1854 ast_cli(a->fd,
"sound_unlocked_now: %s\n",
conf_get_sound(CONF_SOUND_UNLOCKED_NOW, b_profile.sounds));
1855 ast_cli(a->fd,
"sound_lockednow: %s\n",
conf_get_sound(CONF_SOUND_LOCKED_NOW, b_profile.sounds));
1856 ast_cli(a->fd,
"sound_error_menu: %s\n",
conf_get_sound(CONF_SOUND_ERROR_MENU, b_profile.sounds));
1857 ast_cli(a->fd,
"sound_join: %s\n",
conf_get_sound(CONF_SOUND_JOIN, b_profile.sounds));
1858 ast_cli(a->fd,
"sound_leave: %s\n",
conf_get_sound(CONF_SOUND_LEAVE, b_profile.sounds));
1859 ast_cli(a->fd,
"sound_participants_muted: %s\n",
conf_get_sound(CONF_SOUND_PARTICIPANTS_MUTED, b_profile.sounds));
1860 ast_cli(a->fd,
"sound_participants_unmuted: %s\n",
conf_get_sound(CONF_SOUND_PARTICIPANTS_UNMUTED, b_profile.sounds));
1861 ast_cli(a->fd,
"sound_begin: %s\n",
conf_get_sound(CONF_SOUND_BEGIN, b_profile.sounds));
1862 ast_cli(a->fd,
"\n");
1868 static char *complete_menu_name(
const char *line,
const char *word,
int pos,
int state)
1872 int wordlen = strlen(word);
1882 while ((menu = ao2_iterator_next(&i))) {
1883 if (!strncasecmp(menu->name, word, wordlen) && ++which > state) {
1903 e->
command =
"confbridge show menus";
1905 "Usage: confbridge show profile menus\n";
1915 ast_cli(a->fd,
"--------- Menus -----------\n");
1916 ao2_lock(cfg->menus);
1918 while ((menu = ao2_iterator_next(&it))) {
1919 ast_cli(a->fd,
"%s\n", menu->name);
1923 ao2_unlock(cfg->menus);
1937 e->
command =
"confbridge show menu";
1939 "Usage: confbridge show menu [<menu name>]\n";
1943 return complete_menu_name(a->line, a->word, a->pos, a->n);
1949 return CLI_SHOWUSAGE;
1956 if (!(menu = menu_find(cfg->menus, a->argv[3]))) {
1957 ast_cli(a->fd,
"No conference menu named '%s' found!\n", a->argv[3]);
1962 ast_cli(a->fd,
"Name: %s\n", menu->name);
1965 ast_cli(a->fd,
"%s=", menu_entry->
dtmf);
1968 ast_cli(a->fd,
", ");
1970 switch (menu_action->id) {
1971 case MENU_ACTION_TOGGLE_MUTE:
1972 ast_cli(a->fd,
"toggle_mute");
1974 case MENU_ACTION_TOGGLE_BINAURAL:
1975 ast_cli(a->fd,
"toggle_binaural");
1977 case MENU_ACTION_NOOP:
1978 ast_cli(a->fd,
"no_op");
1980 case MENU_ACTION_INCREASE_LISTENING:
1981 ast_cli(a->fd,
"increase_listening_volume");
1983 case MENU_ACTION_DECREASE_LISTENING:
1984 ast_cli(a->fd,
"decrease_listening_volume");
1986 case MENU_ACTION_RESET_LISTENING:
1987 ast_cli(a->fd,
"reset_listening_volume");
1989 case MENU_ACTION_RESET_TALKING:
1990 ast_cli(a->fd,
"reset_talking_volume");
1992 case MENU_ACTION_INCREASE_TALKING:
1993 ast_cli(a->fd,
"increase_talking_volume");
1995 case MENU_ACTION_DECREASE_TALKING:
1996 ast_cli(a->fd,
"decrease_talking_volume");
1998 case MENU_ACTION_PLAYBACK:
1999 ast_cli(a->fd,
"playback(%s)", menu_action->data.playback_file);
2001 case MENU_ACTION_PLAYBACK_AND_CONTINUE:
2002 ast_cli(a->fd,
"playback_and_continue(%s)", menu_action->data.playback_file);
2004 case MENU_ACTION_DIALPLAN_EXEC:
2005 ast_cli(a->fd,
"dialplan_exec(%s,%s,%d)",
2006 menu_action->data.dialplan_args.context,
2007 menu_action->data.dialplan_args.exten,
2008 menu_action->data.dialplan_args.priority);
2010 case MENU_ACTION_ADMIN_TOGGLE_LOCK:
2011 ast_cli(a->fd,
"admin_toggle_conference_lock");
2013 case MENU_ACTION_ADMIN_TOGGLE_MUTE_PARTICIPANTS:
2014 ast_cli(a->fd,
"admin_toggle_mute_participants");
2016 case MENU_ACTION_PARTICIPANT_COUNT:
2017 ast_cli(a->fd,
"participant_count");
2019 case MENU_ACTION_ADMIN_KICK_LAST:
2020 ast_cli(a->fd,
"admin_kick_last");
2022 case MENU_ACTION_LEAVE:
2023 ast_cli(a->fd,
"leave_conference");
2025 case MENU_ACTION_SET_SINGLE_VIDEO_SRC:
2026 ast_cli(a->fd,
"set_as_single_video_src");
2028 case MENU_ACTION_RELEASE_SINGLE_VIDEO_SRC:
2029 ast_cli(a->fd,
"release_as_single_video_src");
2034 ast_cli(a->fd,
"\n");
2043 AST_CLI_DEFINE(handle_cli_confbridge_show_user_profile,
"Show a conference user profile."),
2044 AST_CLI_DEFINE(handle_cli_confbridge_show_bridge_profile,
"Show a conference bridge profile."),
2045 AST_CLI_DEFINE(handle_cli_confbridge_show_menu,
"Show a conference menu"),
2046 AST_CLI_DEFINE(handle_cli_confbridge_show_user_profiles,
"Show a list of conference user profiles."),
2047 AST_CLI_DEFINE(handle_cli_confbridge_show_bridge_profiles,
"Show a list of conference bridge profiles."),
2048 AST_CLI_DEFINE(handle_cli_confbridge_show_menus,
"Show a list of conference menus"),
2052 static void confbridge_cfg_destructor(
void *obj)
2055 ao2_cleanup(cfg->user_profiles);
2056 ao2_cleanup(cfg->bridge_profiles);
2057 ao2_cleanup(cfg->menus);
2060 void *confbridge_cfg_alloc(
void)
2064 if (!(cfg = ao2_alloc(
sizeof(*cfg), confbridge_cfg_destructor))) {
2070 if (!cfg->user_profiles) {
2076 if (!cfg->bridge_profiles) {
2092 static int announce_user_count_all_handler(
const struct aco_option *opt,
struct ast_variable *var,
void *obj)
2096 if (strcasecmp(var->
name,
"announce_user_count_all")) {
2100 u_profile->flags = u_profile->flags | USER_OPT_ANNOUNCEUSERCOUNTALL;
2102 u_profile->flags = u_profile->flags & ~USER_OPT_ANNOUNCEUSERCOUNTALL;
2103 }
else if (sscanf(var->
value,
"%30u", &u_profile->announce_user_count_all_after) == 1) {
2104 u_profile->flags = u_profile->flags | USER_OPT_ANNOUNCEUSERCOUNTALL;
2115 if (strcasecmp(var->
name,
"mixing_interval")) {
2136 if (strcasecmp(var->
name,
"video_mode")) {
2139 if (!strcasecmp(var->
value,
"first_marked")) {
2140 ast_set_flags_to(b_profile,
2141 BRIDGE_OPT_VIDEO_SRC_FIRST_MARKED
2142 | BRIDGE_OPT_VIDEO_SRC_LAST_MARKED
2143 | BRIDGE_OPT_VIDEO_SRC_FOLLOW_TALKER
2144 | BRIDGE_OPT_VIDEO_SRC_SFU,
2145 BRIDGE_OPT_VIDEO_SRC_FIRST_MARKED);
2146 }
else if (!strcasecmp(var->
value,
"last_marked")) {
2147 ast_set_flags_to(b_profile,
2148 BRIDGE_OPT_VIDEO_SRC_FIRST_MARKED
2149 | BRIDGE_OPT_VIDEO_SRC_LAST_MARKED
2150 | BRIDGE_OPT_VIDEO_SRC_FOLLOW_TALKER
2151 | BRIDGE_OPT_VIDEO_SRC_SFU,
2152 BRIDGE_OPT_VIDEO_SRC_LAST_MARKED);
2153 }
else if (!strcasecmp(var->
value,
"follow_talker")) {
2154 ast_set_flags_to(b_profile,
2155 BRIDGE_OPT_VIDEO_SRC_FIRST_MARKED
2156 | BRIDGE_OPT_VIDEO_SRC_LAST_MARKED
2157 | BRIDGE_OPT_VIDEO_SRC_FOLLOW_TALKER
2158 | BRIDGE_OPT_VIDEO_SRC_SFU,
2159 BRIDGE_OPT_VIDEO_SRC_FOLLOW_TALKER);
2160 }
else if (!strcasecmp(var->
value,
"sfu")) {
2161 ast_set_flags_to(b_profile,
2162 BRIDGE_OPT_VIDEO_SRC_FIRST_MARKED
2163 | BRIDGE_OPT_VIDEO_SRC_LAST_MARKED
2164 | BRIDGE_OPT_VIDEO_SRC_FOLLOW_TALKER
2165 | BRIDGE_OPT_VIDEO_SRC_SFU,
2166 BRIDGE_OPT_VIDEO_SRC_SFU);
2167 }
else if (!strcasecmp(var->
value,
"none")) {
2168 ast_clear_flag(b_profile,
2169 BRIDGE_OPT_VIDEO_SRC_FIRST_MARKED
2170 | BRIDGE_OPT_VIDEO_SRC_LAST_MARKED
2171 | BRIDGE_OPT_VIDEO_SRC_FOLLOW_TALKER
2172 | BRIDGE_OPT_VIDEO_SRC_SFU);
2183 if (strcasecmp(var->
name,
"remb_behavior")) {
2187 ast_clear_flag(b_profile, BRIDGE_OPT_REMB_BEHAVIOR_AVERAGE |
2188 BRIDGE_OPT_REMB_BEHAVIOR_LOWEST |
2189 BRIDGE_OPT_REMB_BEHAVIOR_HIGHEST |
2190 BRIDGE_OPT_REMB_BEHAVIOR_AVERAGE_ALL |
2191 BRIDGE_OPT_REMB_BEHAVIOR_LOWEST_ALL |
2192 BRIDGE_OPT_REMB_BEHAVIOR_HIGHEST_ALL |
2193 BRIDGE_OPT_REMB_BEHAVIOR_FORCE
2196 if (!strcasecmp(var->
value,
"average")) {
2197 ast_set_flag(b_profile, BRIDGE_OPT_REMB_BEHAVIOR_AVERAGE);
2198 }
else if (!strcasecmp(var->
value,
"lowest")) {
2199 ast_set_flag(b_profile, BRIDGE_OPT_REMB_BEHAVIOR_LOWEST);
2200 }
else if (!strcasecmp(var->
value,
"highest")) {
2201 ast_set_flag(b_profile, BRIDGE_OPT_REMB_BEHAVIOR_HIGHEST);
2202 }
else if (!strcasecmp(var->
value,
"average_all")) {
2203 ast_set_flag(b_profile, BRIDGE_OPT_REMB_BEHAVIOR_AVERAGE_ALL);
2204 }
else if (!strcasecmp(var->
value,
"lowest_all")) {
2205 ast_set_flag(b_profile, BRIDGE_OPT_REMB_BEHAVIOR_LOWEST_ALL);
2206 }
else if (!strcasecmp(var->
value,
"highest_all")) {
2207 ast_set_flag(b_profile, BRIDGE_OPT_REMB_BEHAVIOR_HIGHEST_ALL);
2208 }
else if (!strcasecmp(var->
value,
"force")) {
2209 ast_set_flag(b_profile, BRIDGE_OPT_REMB_BEHAVIOR_FORCE);
2228 if (!strcasecmp(var->
name,
"internal_sample_rate")) {
2230 if (!strcasecmp(var->
value,
"auto")) {
2234 }
else if (!strcasecmp(var->
name,
"maximum_sample_rate")) {
2236 if (!strcasecmp(var->
value,
"none")) {
2287 ao2_ref(b_profile->sounds, -1);
2289 b_profile->sounds =
sounds;
2303 if (!(new_menu_action =
ast_calloc(1,
sizeof(*new_menu_action)))) {
2306 memcpy(new_menu_action, menu_action,
sizeof(*new_menu_action));
2326 if (copy_menu_entry(cpy, cur)) {
2347 if (!(src_menu = ao2_find(cfg->menus, var->
value,
OBJ_KEY))) {
2351 if (conf_menu_profile_copy(dst_menu, src_menu)) {
2366 add_menu_entry(obj, var->
name, var->
value);
2370 static int verify_default_profiles(
void)
2388 ast_log(AST_LOG_NOTICE,
"Adding %s profile to app_confbridge\n", DEFAULT_BRIDGE_PROFILE);
2395 user_profile = user_profile_alloc(DEFAULT_USER_PROFILE);
2399 ast_log(AST_LOG_NOTICE,
"Adding %s profile to app_confbridge\n", DEFAULT_USER_PROFILE);
2404 menu_profile = ao2_find(cfg->menus, DEFAULT_MENU_PROFILE,
OBJ_KEY);
2405 if (!menu_profile) {
2406 menu_profile = menu_alloc(DEFAULT_MENU_PROFILE);
2407 if (!menu_profile) {
2410 ast_log(AST_LOG_NOTICE,
"Adding %s menu to app_confbridge\n", DEFAULT_MENU_PROFILE);
2412 ao2_link(cfg->menus, menu_profile);
2434 aco_option_register_custom(&cfg_info,
"announce_user_count_all", ACO_EXACT, user_types,
"no", announce_user_count_all_handler, 0);
2528 if (chan && ast_strlen_zero(user_profile_name)) {
2529 ast_channel_lock(chan);
2531 ast_channel_unlock(chan);
2533 b_data = datastore->
data;
2535 conf_user_profile_copy(result, &b_data->u_profile);
2544 if (ast_strlen_zero(user_profile_name)) {
2545 user_profile_name = DEFAULT_USER_PROFILE;
2547 if (!(tmp2 = ao2_find(cfg->user_profiles, user_profile_name,
OBJ_KEY))) {
2551 conf_user_profile_copy(result, tmp2);
2568 if (b_profile->sounds) {
2569 ao2_ref(b_profile->sounds, -1);
2570 b_profile->sounds = NULL;
2581 if (chan && ast_strlen_zero(bridge_profile_name)) {
2582 ast_channel_lock(chan);
2584 ast_channel_unlock(chan);
2586 b_data = datastore->
data;
2597 if (ast_strlen_zero(bridge_profile_name)) {
2598 bridge_profile_name = DEFAULT_BRIDGE_PROFILE;
2600 if (!(tmp2 = ao2_find(cfg->bridge_profiles, bridge_profile_name,
OBJ_KEY))) {
2617 static void menu_hook_destroy(
void *hook_pvt)
2622 ao2_cleanup(pvt->menu);
2630 static int menu_hook_callback(
struct ast_bridge_channel *bridge_channel,
void *hook_pvt)
2634 return conf_handle_dtmf(bridge_channel, pvt->user, &pvt->menu_entry, pvt->menu);
2641 ast_free(menu_action);
2651 if (!strcasecmp(menu_entry->
dtmf, dtmf_sequence)) {
2652 copy_menu_entry(result, menu_entry);
2676 if (copy_menu_entry(&pvt->menu_entry, menu_entry)) {
2677 menu_hook_destroy(pvt);
2682 menu_hook_callback, pvt, menu_hook_destroy, 0)) {
2683 menu_hook_destroy(pvt);
2696 if (chan && ast_strlen_zero(menu_profile_name)) {
2700 ast_channel_lock(chan);
2702 ast_channel_unlock(chan);
2705 b_data = datastore->
data;
2708 return apply_menu_to_user(user, menu);
2718 if (ast_strlen_zero(menu_profile_name)) {
2719 menu_profile_name = DEFAULT_MENU_PROFILE;
2722 if (!(menu = ao2_find(cfg->menus, menu_profile_name,
OBJ_KEY))) {
2726 return apply_menu_to_user(user, menu);
Main Channel structure associated with a channel.
static int user_cmp_cb(void *obj, void *arg, int flags)
Asterisk main include file. File version handling, generic pbx functions.
int ast_parse_arg(const char *arg, enum ast_parse_flags flags, void *p_result,...)
The argument parsing routine.
#define aco_option_register_custom(info, name, matchtype, types, default_val, handler, flags)
Register a config option.
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
const char * conf_get_sound(enum conf_sounds sound, struct bridge_profile_sounds *custom_sounds)
Looks to see if sound file is stored in bridge profile sounds, if not default sound is provided...
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
descriptor for a cli entry.
static const int DEFAULT_SILENCE_THRESHOLD
The default silence threshold we will use if an alternate configured value is not present or is inval...
const struct user_profile * conf_find_user_profile(struct ast_channel *chan, const char *user_profile_name, struct user_profile *result)
find a user profile given a user profile's name and store that profile in result structure.
#define aco_option_register(info, name, matchtype, types, default_val, opt_type, flags,...)
Register a config option.
Structure for variables, used for configurations and for channel variables.
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
void conf_menu_entry_destroy(struct conf_menu_entry *menu_entry)
Destroys and frees all the actions stored in a menu_entry structure.
#define CHARFLDSET(type, field)
A helper macro to pass the appropriate arguments to aco_option_register for OPT_CHAR_ARRAY_T.
Type for a default handler that should do nothing.
Structure for a data store type.
#define ast_cli_register_multiple(e, len)
Register multiple commands.
enum aco_process_status aco_process_config(struct aco_info *info, int reload)
Process a config info via the options registered with an aco_info.
#define ao2_global_obj_ref(holder)
Get a reference to the object stored in the global holder.
void ao2_iterator_destroy(struct ao2_iterator *iter)
Destroy a container iterator.
unsigned int silence_threshold
Type for default option handler for bools (ast_true/ast_false) that are stored in a flag...
#define ast_strdup(str)
A wrapper for strdup()
Structure for a data store object.
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
The representation of a single configuration file to be processed.
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
#define ACO_TYPES(...)
A helper macro to ensure that aco_info types always have a sentinel.
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
void conf_bridge_profile_copy(struct bridge_profile *dst, struct bridge_profile *src)
copies a bridge profile
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Type for default option handler for character array strings.
Configuration File Parser.
#define FLDSET(type,...)
Convert a struct and list of fields to an argument list of field offsets.
int aco_info_init(struct aco_info *info)
Initialize an aco_info structure.
static void bridge_profile_sounds_destroy_cb(void *obj)
void * aco_pending_config(struct aco_info *info)
Get pending config changes.
Type for default option handler for unsigned integers.
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
#define ast_strdupa(s)
duplicate a string in memory from the stack
int conf_handle_dtmf(struct ast_bridge_channel *bridge_channel, struct confbridge_user *user, struct conf_menu_entry *menu_entry, struct conf_menu *menu)
Once a DTMF sequence matches a sequence in the user's DTMF menu, this function will get called to per...
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
void conf_bridge_profile_destroy(struct bridge_profile *b_profile)
Destroy a bridge profile found by 'conf_find_bridge_profile'.
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
int conf_reload_config(void)
reload confbridge.conf file
struct ao2_container * container
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
char language[MAX_LANGUAGE]
unsigned int maximum_sample_rate
Core PBX routines and definitions.
unsigned int internal_sample_rate
static struct stasis_rest_handlers sounds
REST handler for /api-docs/sounds.json.
Their was an error and no changes were applied.
static int menu_cmp_cb(void *obj, void *arg, int flags)
Configuration option-handling.
unsigned int video_update_discard
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Allocate and initialize a hash container with the desired number of buckets.
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
void conf_destroy_config(void)
destroy the information loaded from the confbridge.conf file
void aco_info_destroy(struct aco_info *info)
Destroy an initialized aco_info struct.
#define ao2_global_obj_release(holder)
Release the ao2 object held in the global holder.
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
unsigned int talking_threshold
int conf_set_menu_to_user(struct ast_channel *chan, struct confbridge_user *user, const char *menu_profile_name)
find a menu profile given a menu profile's name and apply the menu in DTMF hooks. ...
#define SCOPED_AO2LOCK(varname, obj)
scoped lock specialization for ao2 mutexes.
#define ast_calloc(num, len)
A wrapper for calloc()
static int user_hash_cb(const void *obj, const int flags)
int aco_set_defaults(struct aco_type *type, const char *category, void *obj)
Set all default options of obj.
struct ast_bridge_features features
Support for logging to various files, console and syslog Configuration in file logger.conf.
int conf_find_menu_entry_by_sequence(const char *dtmf_sequence, struct conf_menu *menu, struct conf_menu_entry *result)
Finds a menu_entry in a menu structure matched by DTMF sequence.
structure to hold users read from users.conf
int ast_bridge_dtmf_hook(struct ast_bridge_features *features, const char *dtmf, ast_bridge_hook_callback callback, void *hook_pvt, ast_bridge_hook_pvt_destructor destructor, enum ast_bridge_hook_remove_flags remove_flags)
Attach a DTMF hook to a bridge features structure.
#define AST_LIST_HEAD_INIT_NOLOCK(head)
Initializes a list head structure.
Structure that contains information regarding a channel in a bridge.
char menu_name[MAX_PROFILE_NAME]
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Standard Command Line Interface.
Type information about a category-level configurable object.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
static int bridge_cmp_cb(void *obj, void *arg, int flags)
int attribute_pure ast_false(const char *val)
Make sure something is false. Determine if a string containing a boolean value is "false"...
The structure that represents a conference bridge user.
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
int conf_load_config(void)
load confbridge.conf file
int aco_process_var(struct aco_type *type, const char *cat, struct ast_variable *var, void *obj)
Parse a single ast_variable and apply it to an object.
#define AO2_GLOBAL_OBJ_STATIC(name)
Define a global object holder to be used to hold an ao2 object, statically initialized.
unsigned int remb_send_interval
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
unsigned int mix_interval
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
#define CONFIG_INFO_STANDARD(name, arr, alloc,...)
Declare an aco_info struct with default module and preload values.
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags) attribute_warn_unused_result
Create an iterator for a container.
int ast_channel_datastore_remove(struct ast_channel *chan, struct ast_datastore *datastore)
Remove a datastore from a channel.
static force_inline int attribute_pure ast_str_case_hash(const char *str)
Compute a hash value on a case-insensitive string.
#define AST_APP_ARG(name)
Define an application argument.
const struct bridge_profile * conf_find_bridge_profile(struct ast_channel *chan, const char *bridge_profile_name, struct bridge_profile *result)
Find a bridge profile given a bridge profile's name and store that profile in result structure...
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
#define ao2_link(container, obj)
Add an object to a container.