summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES9
-rw-r--r--apps/app_confbridge.c49
-rw-r--r--apps/confbridge/conf_config_parser.c25
-rw-r--r--apps/confbridge/include/confbridge.h7
-rw-r--r--configs/confbridge.conf.sample9
-rw-r--r--contrib/realtime/mysql/sipfriends.sql97
6 files changed, 192 insertions, 4 deletions
diff --git a/CHANGES b/CHANGES
index 04de88c6e..4d106f6bb 100644
--- a/CHANGES
+++ b/CHANGES
@@ -12,6 +12,15 @@
--- Functionality changes from Asterisk 10 to Asterisk 11 --------------------
------------------------------------------------------------------------------
+ConfBridge
+-------------------
+ * Added menu action admin_toggle_mute_participants. This will mute / unmute
+ all non-admin participants on a conference. The confbridge configuration file
+ also allows for the default sounds played to all conference users when this
+ occurs to be overriden using sound_participants_unmuted and sound_participants_muted.
+ * Added menu action participant_count. This will playback the number of current
+ participants in a conference.
+
SIP Changes
-----------
* Asterisk will no longer substitute CID number for CID name into display
diff --git a/apps/app_confbridge.c b/apps/app_confbridge.c
index 42c0a4ce7..f0b80967d 100644
--- a/apps/app_confbridge.c
+++ b/apps/app_confbridge.c
@@ -340,6 +340,10 @@ const char *conf_get_sound(enum conf_sounds sound, struct bridge_profile_sounds
return S_OR(custom_sounds->join, "confbridge-join");
case CONF_SOUND_LEAVE:
return S_OR(custom_sounds->leave, "confbridge-leave");
+ case CONF_SOUND_PARTICIPANTS_MUTED:
+ return S_OR(custom_sounds->participantsmuted, "conf-now-muted");
+ case CONF_SOUND_PARTICIPANTS_UNMUTED:
+ return S_OR(custom_sounds->participantsunmuted, "conf-now-unmuted");
}
return "";
@@ -1548,6 +1552,37 @@ static int action_toggle_mute(struct conference_bridge *conference_bridge,
"");
}
+static int action_toggle_mute_participants(struct conference_bridge *conference_bridge, struct conference_bridge_user *conference_bridge_user)
+{
+ struct conference_bridge_user *participant = NULL;
+ const char *sound_to_play;
+
+ ao2_lock(conference_bridge);
+
+ /* If already muted, then unmute */
+ conference_bridge->muted = conference_bridge->muted ? 0 : 1;
+ sound_to_play = conf_get_sound((conference_bridge->muted ? CONF_SOUND_PARTICIPANTS_MUTED : CONF_SOUND_PARTICIPANTS_UNMUTED),
+ conference_bridge_user->b_profile.sounds);
+
+ AST_LIST_TRAVERSE(&conference_bridge->users_list, participant, list) {
+ if (!ast_test_flag(&participant->u_profile, USER_OPT_ADMIN)) {
+ participant->features.mute = conference_bridge->muted;
+ }
+ }
+
+ ao2_unlock(conference_bridge);
+
+ /* The host needs to hear it seperately, as they don't get the audio from play_sound_helper */
+ ast_stream_and_wait(conference_bridge_user->chan, sound_to_play, "");
+
+ /* Announce to the group that all participants are muted */
+ ast_autoservice_start(conference_bridge_user->chan);
+ play_sound_helper(conference_bridge, sound_to_play, 0);
+ ast_autoservice_stop(conference_bridge_user->chan);
+
+ return 0;
+}
+
static int action_playback(struct ast_bridge_channel *bridge_channel, const char *playback_file)
{
char *file_copy = ast_strdupa(playback_file);
@@ -1727,6 +1762,15 @@ static int execute_menu_entry(struct conference_bridge *conference_bridge,
conference_bridge_user,
bridge_channel->chan);
break;
+ case MENU_ACTION_ADMIN_TOGGLE_MUTE_PARTICIPANTS:
+ if (!isadmin) {
+ break;
+ }
+ action_toggle_mute_participants(conference_bridge, conference_bridge_user);
+ break;
+ case MENU_ACTION_PARTICIPANT_COUNT:
+ announce_user_count(conference_bridge, conference_bridge_user);
+ break;
case MENU_ACTION_PLAYBACK:
if (!stop_prompts) {
res |= action_playback(bridge_channel, menu_action->data.playback_file);
@@ -1944,14 +1988,15 @@ static char *handle_cli_confbridge_list(struct ast_cli_entry *e, int cmd, struct
ast_cli(a->fd, "No conference bridge named '%s' found!\n", a->argv[2]);
return CLI_SUCCESS;
}
- ast_cli(a->fd, "Channel User Profile Bridge Profile Menu\n");
- ast_cli(a->fd, "============================= ================ ================ ================\n");
+ ast_cli(a->fd, "Channel User Profile Bridge Profile Menu CallerID\n");
+ ast_cli(a->fd, "============================= ================ ================ ================ ================\n");
ao2_lock(bridge);
AST_LIST_TRAVERSE(&bridge->users_list, participant, list) {
ast_cli(a->fd, "%-29s ", participant->chan->name);
ast_cli(a->fd, "%-17s", participant->u_profile.name);
ast_cli(a->fd, "%-17s", participant->b_profile.name);
ast_cli(a->fd, "%-17s", participant->menu_name);
+ ast_cli(a->fd, "%-17s", S_COR(participant->chan->caller.id.number.valid, participant->chan->caller.id.number.str, "<unknown>"));
ast_cli(a->fd, "\n");
}
ao2_unlock(bridge);
diff --git a/apps/confbridge/conf_config_parser.c b/apps/confbridge/conf_config_parser.c
index d11b82582..a2b52bea7 100644
--- a/apps/confbridge/conf_config_parser.c
+++ b/apps/confbridge/conf_config_parser.c
@@ -253,6 +253,10 @@ static int set_sound(const char *sound_name, const char *sound_file, struct brid
ast_string_field_set(sounds, join, sound_file);
} else if (!strcasecmp(sound_name, "sound_leave")) {
ast_string_field_set(sounds, leave, sound_file);
+ } else if (!strcasecmp(sound_name, "sound_participants_muted")) {
+ ast_string_field_set(sounds, participantsmuted, sound_file);
+ } else if (!strcasecmp(sound_name, "sound_participants_unmuted")) {
+ ast_string_field_set(sounds, participantsunmuted, sound_file);
} else {
return -1;
}
@@ -315,7 +319,7 @@ static int set_bridge_option(const char *name, const char *value, struct bridge_
}
/* Using a bridge profile as a template is a little complicated due to the sounds. Since the sounds
* structure of a dynamic profile will need to be altered, a completely new sounds structure must be
- * create instead of simply holding a reference to the one built by the config file. */
+ * created instead of simply holding a reference to the one built by the config file. */
ast_string_field_set(sounds, onlyperson, tmp->sounds->onlyperson);
ast_string_field_set(sounds, hasjoin, tmp->sounds->hasjoin);
ast_string_field_set(sounds, hasleft, tmp->sounds->hasleft);
@@ -332,6 +336,8 @@ static int set_bridge_option(const char *name, const char *value, struct bridge_
ast_string_field_set(sounds, unlockednow, tmp->sounds->unlockednow);
ast_string_field_set(sounds, lockednow, tmp->sounds->lockednow);
ast_string_field_set(sounds, errormenu, tmp->sounds->errormenu);
+ ast_string_field_set(sounds, participantsmuted, tmp->sounds->participantsmuted);
+ ast_string_field_set(sounds, participantsunmuted, tmp->sounds->participantsunmuted);
ao2_ref(tmp->sounds, -1); /* sounds struct copied over to it from the template by reference only. */
ao2_ref(oldsounds,-1); /* original sounds struct we don't need anymore */
@@ -540,6 +546,8 @@ static int add_action_to_menu_entry(struct conf_menu_entry *menu_entry, enum con
case MENU_ACTION_RESET_LISTENING:
case MENU_ACTION_RESET_TALKING:
case MENU_ACTION_ADMIN_TOGGLE_LOCK:
+ case MENU_ACTION_ADMIN_TOGGLE_MUTE_PARTICIPANTS:
+ case MENU_ACTION_PARTICIPANT_COUNT:
case MENU_ACTION_ADMIN_KICK_LAST:
case MENU_ACTION_LEAVE:
case MENU_ACTION_SET_SINGLE_VIDEO_SRC:
@@ -655,6 +663,10 @@ static int add_menu_entry(struct conf_menu *menu, const char *dtmf, const char *
res |= add_action_to_menu_entry(menu_entry, MENU_ACTION_DECREASE_TALKING, NULL);
} else if (!strcasecmp(action, "admin_toggle_conference_lock")) {
res |= add_action_to_menu_entry(menu_entry, MENU_ACTION_ADMIN_TOGGLE_LOCK, NULL);
+ } else if (!strcasecmp(action, "admin_toggle_mute_participants")) {
+ res |= add_action_to_menu_entry(menu_entry, MENU_ACTION_ADMIN_TOGGLE_MUTE_PARTICIPANTS, NULL);
+ } else if (!strcasecmp(action, "participant_count")) {
+ res |= add_action_to_menu_entry(menu_entry, MENU_ACTION_PARTICIPANT_COUNT, NULL);
} else if (!strcasecmp(action, "admin_kick_last")) {
res |= add_action_to_menu_entry(menu_entry, MENU_ACTION_ADMIN_KICK_LAST, NULL);
} else if (!strcasecmp(action, "leave_conference")) {
@@ -1025,6 +1037,8 @@ static char *handle_cli_confbridge_show_bridge_profile(struct ast_cli_entry *e,
ast_cli(a->fd,"sound_unlocked_now: %s\n", conf_get_sound(CONF_SOUND_UNLOCKED_NOW, b_profile.sounds));
ast_cli(a->fd,"sound_lockednow: %s\n", conf_get_sound(CONF_SOUND_LOCKED_NOW, b_profile.sounds));
ast_cli(a->fd,"sound_error_menu: %s\n", conf_get_sound(CONF_SOUND_ERROR_MENU, b_profile.sounds));
+ ast_cli(a->fd,"sound_participants_muted: %s\n", conf_get_sound(CONF_SOUND_PARTICIPANTS_MUTED, b_profile.sounds));
+ ast_cli(a->fd,"sound_participants_unmuted: %s\n", conf_get_sound(CONF_SOUND_PARTICIPANTS_UNMUTED, b_profile.sounds));
ast_cli(a->fd,"\n");
conf_bridge_profile_destroy(&b_profile);
@@ -1160,6 +1174,12 @@ static char *handle_cli_confbridge_show_menu(struct ast_cli_entry *e, int cmd, s
case MENU_ACTION_ADMIN_TOGGLE_LOCK:
ast_cli(a->fd, "admin_toggle_conference_lock");
break;
+ case MENU_ACTION_ADMIN_TOGGLE_MUTE_PARTICIPANTS:
+ ast_cli(a->fd, "admin_toggle_mute_participants");
+ break;
+ case MENU_ACTION_PARTICIPANT_COUNT:
+ ast_cli(a->fd, "participant_count");
+ break;
case MENU_ACTION_ADMIN_KICK_LAST:
ast_cli(a->fd, "admin_kick_last");
break;
@@ -1360,8 +1380,9 @@ const struct bridge_profile *conf_find_bridge_profile(struct ast_channel *chan,
conf_bridge_profile_copy(result, &b_data->b_profile);
return result;
}
+ } else {
+ ast_channel_unlock(chan);
}
- ast_channel_unlock(chan);
}
if (ast_strlen_zero(bridge_profile_name)) {
bridge_profile_name = DEFAULT_BRIDGE_PROFILE;
diff --git a/apps/confbridge/include/confbridge.h b/apps/confbridge/include/confbridge.h
index ab4a8c4b0..5337e22aa 100644
--- a/apps/confbridge/include/confbridge.h
+++ b/apps/confbridge/include/confbridge.h
@@ -83,6 +83,8 @@ enum conf_menu_action_id {
MENU_ACTION_NOOP,
MENU_ACTION_SET_SINGLE_VIDEO_SRC,
MENU_ACTION_RELEASE_SINGLE_VIDEO_SRC,
+ MENU_ACTION_PARTICIPANT_COUNT,
+ MENU_ACTION_ADMIN_TOGGLE_MUTE_PARTICIPANTS,
};
/*! The conference menu action contains both
@@ -156,6 +158,8 @@ enum conf_sounds {
CONF_SOUND_ERROR_MENU,
CONF_SOUND_JOIN,
CONF_SOUND_LEAVE,
+ CONF_SOUND_PARTICIPANTS_MUTED,
+ CONF_SOUND_PARTICIPANTS_UNMUTED,
};
struct bridge_profile_sounds {
@@ -180,6 +184,8 @@ struct bridge_profile_sounds {
AST_STRING_FIELD(errormenu);
AST_STRING_FIELD(leave);
AST_STRING_FIELD(join);
+ AST_STRING_FIELD(participantsmuted);
+ AST_STRING_FIELD(participantsunmuted);
);
};
@@ -202,6 +208,7 @@ struct conference_bridge {
unsigned int users; /*!< Number of users present */
unsigned int markedusers; /*!< Number of marked users present */
unsigned int locked:1; /*!< Is this conference bridge locked? */
+ unsigned int muted:1; /*!< Is this conference bridge muted? */
struct ast_channel *playback_chan; /*!< Channel used for playback into the conference bridge */
struct ast_channel *record_chan; /*!< Channel used for recording the conference */
pthread_t record_thread; /*!< The thread the recording chan lives in */
diff --git a/configs/confbridge.conf.sample b/configs/confbridge.conf.sample
index 31060ecab..d113825d2 100644
--- a/configs/confbridge.conf.sample
+++ b/configs/confbridge.conf.sample
@@ -306,6 +306,15 @@ type=bridge
; to whatever operation the video_mode option is set to
; upon release of the video src.
+; admin_toggle_mute_participants ; This action allows an administrator to toggle the mute
+ ; state for all non-admins within a conference. All
+ ; admin users are unaffected by this option. Note that all
+ ; users, regardless of their admin status, are notified
+ ; that the conference is muted.
+
+; participant_count ; This action plays back the number of participants currently
+ ; in a conference
+
[sample_user_menu]
type=menu
*=playback_and_continue(conf-usermenu)
diff --git a/contrib/realtime/mysql/sipfriends.sql b/contrib/realtime/mysql/sipfriends.sql
new file mode 100644
index 000000000..07cd8788a
--- /dev/null
+++ b/contrib/realtime/mysql/sipfriends.sql
@@ -0,0 +1,97 @@
+#
+# Table structure for table `sipfriends`
+#
+
+CREATE TABLE IF NOT EXISTS `sipfriends` (
+ `id` int(11) NOT NULL AUTO_INCREMENT,
+ `name` varchar(10) NOT NULL,
+ `ipaddr` varchar(15) DEFAULT NULL,
+ `port` int(5) DEFAULT NULL,
+ `regseconds` int(11) DEFAULT NULL,
+ `defaultuser` varchar(10) DEFAULT NULL,
+ `fullcontact` varchar(35) DEFAULT NULL,
+ `regserver` varchar(20) DEFAULT NULL,
+ `useragent` varchar(20) DEFAULT NULL,
+ `lastms` int(11) DEFAULT NULL,
+ `host` varchar(40) DEFAULT NULL,
+ `type` enum('friend','user','peer') DEFAULT NULL,
+ `context` varchar(40) DEFAULT NULL,
+ `permit` varchar(40) DEFAULT NULL,
+ `deny` varchar(40) DEFAULT NULL,
+ `secret` varchar(40) DEFAULT NULL,
+ `md5secret` varchar(40) DEFAULT NULL,
+ `remotesecret` varchar(40) DEFAULT NULL,
+ `transport` enum('udp','tcp','udp,tcp','tcp,udp') DEFAULT NULL,
+ `dtmfmode` enum('rfc2833','info','shortinfo','inband','auto') DEFAULT NULL,
+ `directmedia` enum('yes','no','nonat','update') DEFAULT NULL,
+ `nat` enum('yes','no','never','route') DEFAULT NULL,
+ `callgroup` varchar(40) DEFAULT NULL,
+ `pickupgroup` varchar(40) DEFAULT NULL,
+ `language` varchar(40) DEFAULT NULL,
+ `allow` varchar(200) DEFAULT NULL,
+ `insecure` varchar(40) DEFAULT NULL,
+ `trustrpid` enum('yes','no') DEFAULT NULL,
+ `progressinband` enum('yes','no','never') DEFAULT NULL,
+ `promiscredir` enum('yes','no') DEFAULT NULL,
+ `useclientcode` enum('yes','no') DEFAULT NULL,
+ `accountcode` varchar(40) DEFAULT NULL,
+ `setvar` varchar(40) DEFAULT NULL,
+ `callerid` varchar(40) DEFAULT NULL,
+ `amaflags` varchar(40) DEFAULT NULL,
+ `callcounter` enum('yes','no') DEFAULT NULL,
+ `busylevel` int(11) DEFAULT NULL,
+ `allowoverlap` enum('yes','no') DEFAULT NULL,
+ `allowsubscribe` enum('yes','no') DEFAULT NULL,
+ `videosupport` enum('yes','no') DEFAULT NULL,
+ `maxcallbitrate` int(11) DEFAULT NULL,
+ `rfc2833compensate` enum('yes','no') DEFAULT NULL,
+ `mailbox` varchar(40) DEFAULT NULL,
+ `session-timers` enum('accept','refuse','originate') DEFAULT NULL,
+ `session-expires` int(11) DEFAULT NULL,
+ `session-minse` int(11) DEFAULT NULL,
+ `session-refresher` enum('uac','uas') DEFAULT NULL,
+ `t38pt_usertpsource` varchar(40) DEFAULT NULL,
+ `regexten` varchar(40) DEFAULT NULL,
+ `fromdomain` varchar(40) DEFAULT NULL,
+ `fromuser` varchar(40) DEFAULT NULL,
+ `qualify` varchar(40) DEFAULT NULL,
+ `defaultip` varchar(40) DEFAULT NULL,
+ `rtptimeout` int(11) DEFAULT NULL,
+ `rtpholdtimeout` int(11) DEFAULT NULL,
+ `sendrpid` enum('yes','no') DEFAULT NULL,
+ `outboundproxy` varchar(40) DEFAULT NULL,
+ `callbackextension` varchar(40) DEFAULT NULL,
+ `registertrying` enum('yes','no') DEFAULT NULL,
+ `timert1` int(11) DEFAULT NULL,
+ `timerb` int(11) DEFAULT NULL,
+ `qualifyfreq` int(11) DEFAULT NULL,
+ `constantssrc` enum('yes','no') DEFAULT NULL,
+ `contactpermit` varchar(40) DEFAULT NULL,
+ `contactdeny` varchar(40) DEFAULT NULL,
+ `usereqphone` enum('yes','no') DEFAULT NULL,
+ `textsupport` enum('yes','no') DEFAULT NULL,
+ `faxdetect` enum('yes','no') DEFAULT NULL,
+ `buggymwi` enum('yes','no') DEFAULT NULL,
+ `auth` varchar(40) DEFAULT NULL,
+ `fullname` varchar(40) DEFAULT NULL,
+ `trunkname` varchar(40) DEFAULT NULL,
+ `cid_number` varchar(40) DEFAULT NULL,
+ `callingpres` enum('allowed_not_screened','allowed_passed_screen','allowed_failed_screen','allowed','prohib_not_screened','prohib_passed_screen','prohib_failed_screen','prohib') DEFAULT NULL,
+ `mohinterpret` varchar(40) DEFAULT NULL,
+ `mohsuggest` varchar(40) DEFAULT NULL,
+ `parkinglot` varchar(40) DEFAULT NULL,
+ `hasvoicemail` enum('yes','no') DEFAULT NULL,
+ `subscribemwi` enum('yes','no') DEFAULT NULL,
+ `vmexten` varchar(40) DEFAULT NULL,
+ `autoframing` enum('yes','no') DEFAULT NULL,
+ `rtpkeepalive` int(11) DEFAULT NULL,
+ `call-limit` int(11) DEFAULT NULL,
+ `g726nonstandard` enum('yes','no') DEFAULT NULL,
+ `ignoresdpversion` enum('yes','no') DEFAULT NULL,
+ `allowtransfer` enum('yes','no') DEFAULT NULL,
+ `dynamic` enum('yes','no') DEFAULT NULL,
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `name` (`name`),
+ KEY `ipaddr` (`ipaddr`,`port`),
+ KEY `host` (`host`,`port`)
+) ENGINE=MyISAM;