[asterisk-commits] kharwell: branch 11 r433445 - /branches/11/apps/app_confbridge.c

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Thu Mar 26 12:00:42 CDT 2015


Author: kharwell
Date: Thu Mar 26 12:00:39 2015
New Revision: 433445

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=433445
Log:
app_confbridge: file playback blocks dtmf

Attempting to execute DTMF in a confbridge while file playback (prompt,
announcement, etc) is occurring is not allowed. You have to wait until
the sound file has completed before entering DTMF. This patch fixes it
so that app_confbridge now monitors for dtmf key presses during menu
driven file playback. If a key is pressed playback stops and it executes
the matched menu option.

ASTERISK-24864 #close
Reported by: Steve Pitts
Review: https://reviewboard.asterisk.org/r/4477/

Modified:
    branches/11/apps/app_confbridge.c

Modified: branches/11/apps/app_confbridge.c
URL: http://svnview.digium.com/svn/asterisk/branches/11/apps/app_confbridge.c?view=diff&rev=433445&r1=433444&r2=433445
==============================================================================
--- branches/11/apps/app_confbridge.c (original)
+++ branches/11/apps/app_confbridge.c Thu Mar 26 12:00:39 2015
@@ -658,6 +658,41 @@
 	);
 }
 
+/* \brief Playback the given filename and monitor for any dtmf interrupts.
+ *
+ * Use this function to playback sound files to the given channel that can be
+ * interrupted by dtmf. Note, too this function can be used to playback a sound
+ * file without allowing interruptions.
+ *
+ * \retval -1 failure during playback, 0 on file was fully played, 1 on dtmf interrupt.
+ */
+static int play_file(struct ast_channel *channel, const char *filename, int allow_dtmf_interrupt)
+{
+	const char *stop_digits = allow_dtmf_interrupt ? AST_DIGIT_ANY : AST_DIGIT_NONE;
+	int digit;
+
+	digit = ast_stream_and_wait(channel, filename, stop_digits);
+	if (digit < 0) {
+		ast_log(LOG_WARNING, "Failed to playback file '%s' to channel\n", filename);
+		return -1;
+	}
+
+	if (digit > 0) {
+		/* file playback was interrupted by a key press, re-queue it */
+		struct ast_frame frame;
+
+		memset(&frame, 0, sizeof(frame));
+		frame.frametype = AST_FRAME_DTMF_END;
+		frame.subclass.integer = digit;
+
+		ast_stopstream(channel);
+		ast_queue_frame_head(channel, &frame);
+		return 1;
+	}
+
+	return 0;
+}
+
 /*!
  * \internal
  * \brief Complain if the given sound file does not exist.
@@ -680,11 +715,13 @@
  *
  * \param conference_bridge Conference bridge to peek at
  * \param (OPTIONAL) conference_bridge_user Caller
+ * \param allow_dtmf_interrupt allow dtmf to interrupt playback
  *
  * \note if caller is NULL, the announcment will be sent to all participants in the conference.
  * \return Returns 0 on success, -1 if the user hung up
  */
-static int announce_user_count(struct conference_bridge *conference_bridge, struct conference_bridge_user *conference_bridge_user)
+static int announce_user_count(struct conference_bridge *conference_bridge, struct conference_bridge_user *conference_bridge_user,
+			       int allow_dtmf_interrupt)
 {
 	const char *other_in_party = conf_get_sound(CONF_SOUND_OTHER_IN_PARTY, conference_bridge->b_profile.sounds);
 	const char *only_one = conf_get_sound(CONF_SOUND_ONLY_ONE, conference_bridge->b_profile.sounds);
@@ -696,9 +733,7 @@
 	} else if (conference_bridge->activeusers == 2) {
 		if (conference_bridge_user) {
 			/* Eep, there is one other person */
-			if (ast_stream_and_wait(conference_bridge_user->chan,
-				only_one,
-				"")) {
+			if (play_file(conference_bridge_user->chan, only_one, allow_dtmf_interrupt) < 0) {
 				return -1;
 			}
 		} else {
@@ -715,9 +750,7 @@
 			if (ast_say_number(conference_bridge_user->chan, conference_bridge->activeusers - 1, "", ast_channel_language(conference_bridge_user->chan), NULL)) {
 				return -1;
 			}
-			if (ast_stream_and_wait(conference_bridge_user->chan,
-				other_in_party,
-				"")) {
+			if (play_file(conference_bridge_user->chan, other_in_party, allow_dtmf_interrupt) < 0) {
 				return -1;
 			}
 		} else if (sound_file_exists(there_are) && sound_file_exists(other_in_party)) {
@@ -1241,7 +1274,7 @@
 
 	/* Announce number of users if need be */
 	if (ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_ANNOUNCEUSERCOUNT)) {
-		if (announce_user_count(conference_bridge, conference_bridge_user)) {
+		if (announce_user_count(conference_bridge, conference_bridge_user, 0)) {
 			leave_conference(conference_bridge_user);
 			return NULL;
 		}
@@ -1256,7 +1289,7 @@
 		 * joined the conference yet.
 		 */
 		ast_autoservice_start(conference_bridge_user->chan);
-		user_count_res = announce_user_count(conference_bridge, NULL);
+		user_count_res = announce_user_count(conference_bridge, NULL, 0);
 		ast_autoservice_stop(conference_bridge_user->chan);
 		if (user_count_res) {
 			leave_conference(conference_bridge_user);
@@ -1772,10 +1805,9 @@
 		conference_bridge_user->b_profile.name,
 		ast_channel_name(chan));
 
-	return ast_stream_and_wait(chan, (mute ?
+	return play_file(chan, (mute ?
 		conf_get_sound(CONF_SOUND_MUTED, conference_bridge_user->b_profile.sounds) :
-		conf_get_sound(CONF_SOUND_UNMUTED, conference_bridge_user->b_profile.sounds)),
-		"");
+		conf_get_sound(CONF_SOUND_UNMUTED, conference_bridge_user->b_profile.sounds)), 1) < 0;
 }
 
 static int action_toggle_mute_participants(struct conference_bridge *conference_bridge, struct conference_bridge_user *conference_bridge_user)
@@ -1900,18 +1932,16 @@
 }
 
 static int action_kick_last(struct conference_bridge *conference_bridge,
-	struct ast_bridge_channel *bridge_channel,
 	struct conference_bridge_user *conference_bridge_user)
 {
 	struct conference_bridge_user *last_participant = NULL;
 	int isadmin = ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_ADMIN);
 
 	if (!isadmin) {
-		ast_stream_and_wait(bridge_channel->chan,
-			conf_get_sound(CONF_SOUND_ERROR_MENU, conference_bridge_user->b_profile.sounds),
-			"");
+		play_file(conference_bridge_user->chan,
+			conf_get_sound(CONF_SOUND_ERROR_MENU, conference_bridge_user->b_profile.sounds), 1);
 		ast_log(LOG_WARNING, "Only admin users can use the kick_last menu action. Channel %s of conf %s is not an admin.\n",
-			ast_channel_name(bridge_channel->chan),
+			ast_channel_name(conference_bridge_user->chan),
 			conference_bridge->name);
 		return -1;
 	}
@@ -1920,9 +1950,8 @@
 	if (((last_participant = AST_LIST_LAST(&conference_bridge->active_list)) == conference_bridge_user)
 		|| (ast_test_flag(&last_participant->u_profile, USER_OPT_ADMIN))) {
 		ao2_unlock(conference_bridge);
-		ast_stream_and_wait(bridge_channel->chan,
-			conf_get_sound(CONF_SOUND_ERROR_MENU, conference_bridge_user->b_profile.sounds),
-			"");
+		play_file(conference_bridge_user->chan,
+			conf_get_sound(CONF_SOUND_ERROR_MENU, conference_bridge_user->b_profile.sounds), 1);
 	} else if (last_participant && !last_participant->kicked) {
 		last_participant->kicked = 1;
 		ast_bridge_remove(conference_bridge->bridge, last_participant->chan);
@@ -2000,7 +2029,7 @@
 			action_toggle_mute_participants(conference_bridge, conference_bridge_user);
 			break;
 		case MENU_ACTION_PARTICIPANT_COUNT:
-			announce_user_count(conference_bridge, conference_bridge_user);
+			announce_user_count(conference_bridge, conference_bridge_user, 1);
 			break;
 		case MENU_ACTION_PLAYBACK:
 			if (!stop_prompts) {
@@ -2048,15 +2077,13 @@
 				break;
 			}
 			conference_bridge->locked = (!conference_bridge->locked ? 1 : 0);
-			res |= ast_stream_and_wait(bridge_channel->chan,
+			res |= play_file(bridge_channel->chan,
 				(conference_bridge->locked ?
 				conf_get_sound(CONF_SOUND_LOCKED_NOW, conference_bridge_user->b_profile.sounds) :
-				conf_get_sound(CONF_SOUND_UNLOCKED_NOW, conference_bridge_user->b_profile.sounds)),
-				"");
-
+				conf_get_sound(CONF_SOUND_UNLOCKED_NOW, conference_bridge_user->b_profile.sounds)), 1) < 0;
 			break;
 		case MENU_ACTION_ADMIN_KICK_LAST:
-			res |= action_kick_last(conference_bridge, bridge_channel, conference_bridge_user);
+			res |= action_kick_last(conference_bridge, conference_bridge_user);
 			break;
 		case MENU_ACTION_LEAVE:
 			ao2_lock(conference_bridge);




More information about the asterisk-commits mailing list