[Asterisk-code-review] app confbridge: Wrong language on playback of some files (asterisk[11])

Kevin Harwell asteriskteam at digium.com
Tue Apr 21 12:51:22 CDT 2015


Kevin Harwell has uploaded a new change for review.

  https://gerrit.asterisk.org/185

Change subject: app_confbridge: Wrong language on playback of some files
......................................................................

app_confbridge: Wrong language on playback of some files

It is possible to configure a specific language for a confbridge. This language
option was not being honored during playback of some files. Namely all those
files not played on the confbridge's playback channel. Added a language
parameter to the various playback functions, so that the configured language
set on the confbridge is now used instead of the one designated on the channel.

ASTERISK-24749 #close
Reported by: philippebolduc

Change-Id: I09303f368b39da02c379ea364adcc36d1d76ab89
---
M apps/app_confbridge.c
M include/asterisk/app.h
M include/asterisk/file.h
M main/app.c
M main/file.c
5 files changed, 85 insertions(+), 38 deletions(-)


  git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/85/185/1

diff --git a/apps/app_confbridge.c b/apps/app_confbridge.c
index cd4c814..ddbd41d 100644
--- a/apps/app_confbridge.c
+++ b/apps/app_confbridge.c
@@ -666,12 +666,13 @@
  *
  * \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)
+static int play_file(struct conference_bridge_user *conference_bridge_user, const char *filename, int allow_dtmf_interrupt)
 {
 	const char *stop_digits = allow_dtmf_interrupt ? AST_DIGIT_ANY : AST_DIGIT_NONE;
 	int digit;
+	struct ast_channel *channel = conference_bridge_user->chan;
 
-	digit = ast_stream_and_wait(channel, filename, stop_digits);
+	digit = ast_stream_and_wait_with_language(channel, filename, stop_digits, conference_bridge_user->b_profile.language);
 	if (digit < 0) {
 		ast_log(LOG_WARNING, "Failed to playback file '%s' to channel\n", filename);
 		return -1;
@@ -733,7 +734,7 @@
 	} else if (conference_bridge->activeusers == 2) {
 		if (conference_bridge_user) {
 			/* Eep, there is one other person */
-			if (play_file(conference_bridge_user->chan, only_one, allow_dtmf_interrupt) < 0) {
+			if (play_file(conference_bridge_user, only_one, allow_dtmf_interrupt) < 0) {
 				return -1;
 			}
 		} else {
@@ -742,15 +743,15 @@
 	} else {
 		/* Alas multiple others in here */
 		if (conference_bridge_user) {
-			if (ast_stream_and_wait(conference_bridge_user->chan,
+			if (ast_stream_and_wait_with_language(conference_bridge_user->chan,
 				there_are,
-				"")) {
+				"", conference_bridge_user->b_profile.language)) {
 				return -1;
 			}
 			if (ast_say_number(conference_bridge_user->chan, conference_bridge->activeusers - 1, "", ast_channel_language(conference_bridge_user->chan), NULL)) {
 				return -1;
 			}
-			if (play_file(conference_bridge_user->chan, other_in_party, allow_dtmf_interrupt) < 0) {
+			if (play_file(conference_bridge_user, other_in_party, allow_dtmf_interrupt) < 0) {
 				return -1;
 			}
 		} else if (sound_file_exists(there_are) && sound_file_exists(other_in_party)) {
@@ -775,7 +776,7 @@
  */
 static int play_prompt_to_user(struct conference_bridge_user *cbu, const char *filename)
 {
-	return ast_stream_and_wait(cbu->chan, filename, "");
+	return ast_stream_and_wait_with_language(cbu->chan, filename, "", cbu->b_profile.language);
 }
 
 static void handle_video_on_join(struct conference_bridge *conference_bridge, struct ast_channel *chan, int marked)
@@ -1163,9 +1164,9 @@
 		ao2_unlock(conference_bridges);
 		ao2_ref(conference_bridge, -1);
 		ast_debug(1, "Conference '%s' is locked and caller is not an admin\n", name);
-		ast_stream_and_wait(conference_bridge_user->chan,
+		ast_stream_and_wait_with_language(conference_bridge_user->chan,
 				conf_get_sound(CONF_SOUND_LOCKED, conference_bridge_user->b_profile.sounds),
-				"");
+				"", conference_bridge_user->b_profile.language);
 		return NULL;
 	}
 
@@ -1524,7 +1525,7 @@
 		 "%s/confbridge-name-%s-%s", destdir,
 		 conf_name, ast_channel_uniqueid(user->chan));
 
-	res = ast_play_and_record(user->chan,
+	res = ast_play_and_record_with_language(user->chan,
 		"vm-rec-name",
 		user->name_rec_location,
 		10,
@@ -1533,7 +1534,8 @@
 		NULL,
 		ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE),
 		0,
-		NULL);
+		NULL,
+		user->b_profile.language);
 
 	if (res == -1) {
 		user->name_rec_location[0] = '\0';
@@ -1709,7 +1711,7 @@
 	if (!quiet) {
 		const char *join_sound = conf_get_sound(CONF_SOUND_JOIN, conference_bridge_user.b_profile.sounds);
 
-		ast_stream_and_wait(chan, join_sound, "");
+		ast_stream_and_wait_with_language(chan, join_sound, "", conference_bridge_user.b_profile.language);
 		ast_autoservice_start(chan);
 		play_sound_file(conference_bridge, join_sound);
 		ast_autoservice_stop(chan);
@@ -1762,9 +1764,9 @@
 
 	/* If the user was kicked from the conference play back the audio prompt for it */
 	if (!quiet && conference_bridge_user.kicked) {
-		res = ast_stream_and_wait(chan,
+		res = ast_stream_and_wait_with_language(chan,
 			conf_get_sound(CONF_SOUND_KICKED, conference_bridge_user.b_profile.sounds),
-			"");
+			"", conference_bridge_user.b_profile.language);
 	}
 
 	/* Restore volume adjustments to previous values in case they were changed */
@@ -1805,7 +1807,7 @@
 		conference_bridge_user->b_profile.name,
 		ast_channel_name(chan));
 
-	return play_file(chan, (mute ?
+	return play_file(conference_bridge_user, (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)), 1) < 0;
 }
@@ -1836,7 +1838,7 @@
 		conference_bridge_user->b_profile.sounds);
 
 	/* 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, "");
+	ast_stream_and_wait_with_language(conference_bridge_user->chan, sound_to_play, "", conference_bridge_user->b_profile.language);
 
 	/* Announce to the group that all participants are muted */
 	ast_autoservice_start(conference_bridge_user->chan);
@@ -1846,13 +1848,13 @@
 	return 0;
 }
 
-static int action_playback(struct ast_bridge_channel *bridge_channel, const char *playback_file)
+static int action_playback(struct conference_bridge_user *conference_bridge_user, const char *playback_file)
 {
 	char *file_copy = ast_strdupa(playback_file);
 	char *file = NULL;
 
 	while ((file = strsep(&file_copy, "&"))) {
-		if (ast_stream_and_wait(bridge_channel->chan, file, "")) {
+		if (ast_stream_and_wait_with_language(conference_bridge_user->chan, file, "", conference_bridge_user->b_profile.language)) {
 			ast_log(LOG_WARNING, "Failed to playback file %s to channel\n", file);
 			return -1;
 		}
@@ -1938,7 +1940,7 @@
 	int isadmin = ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_ADMIN);
 
 	if (!isadmin) {
-		play_file(conference_bridge_user->chan,
+		play_file(conference_bridge_user,
 			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(conference_bridge_user->chan),
@@ -1950,7 +1952,7 @@
 	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);
-		play_file(conference_bridge_user->chan,
+		play_file(conference_bridge_user,
 			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;
@@ -2033,7 +2035,7 @@
 			break;
 		case MENU_ACTION_PLAYBACK:
 			if (!stop_prompts) {
-				res |= action_playback(bridge_channel, menu_action->data.playback_file);
+				res |= action_playback( conference_bridge_user, menu_action->data.playback_file);
 			}
 			break;
 		case MENU_ACTION_RESET_LISTENING:
@@ -2077,7 +2079,7 @@
 				break;
 			}
 			conference_bridge->locked = (!conference_bridge->locked ? 1 : 0);
-			res |= play_file(bridge_channel->chan,
+			res |= play_file(conference_bridge_user,
 				(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)), 1) < 0;
diff --git a/include/asterisk/app.h b/include/asterisk/app.h
index d10a0a6..b76ffef 100644
--- a/include/asterisk/app.h
+++ b/include/asterisk/app.h
@@ -661,8 +661,12 @@
 	long *offsetms,
 	ast_waitstream_fr_cb cb);
 
+/*! \brief Play a stream and wait for a digit, returning the digit that was pressed. Use
+           the given language parameter to optionally override the channel's language */
+int ast_play_and_wait_with_language(struct ast_channel *chan, const char *fn, const char *language);
+
 /*! \brief Play a stream and wait for a digit, returning the digit that was pressed */
-int ast_play_and_wait(struct ast_channel *chan, const char *fn);
+#define ast_play_and_wait(chan, fn) ast_play_and_wait_with_language(chan, fn, NULL)
 
 /*!
  * \brief Record a file based on input from a channel
@@ -690,6 +694,30 @@
 
 /*!
  * \brief Record a file based on input from a channel. Use default accept and cancel DTMF.
+ *        This function will play "auth-thankyou" upon successful recording. Override the
+ *        Channel's language with the given one.
+ *
+ * \param chan the channel being recorded
+ * \param playfile Filename of sound to play before recording begins
+ * \param recordfile Filename to save the recording
+ * \param maxtime_sec Longest possible message length in seconds
+ * \param fmt string containing all formats to be recorded delimited by '|'
+ * \param duration pointer to integer for storing length of the recording
+ * \param sound_duration pointer to integer for storing length of the recording minus all silence
+ * \param silencethreshold tolerance of noise levels that can be considered silence for the purpose of silence timeout, -1 for default
+ * \param maxsilence_ms length of time in milliseconds which will trigger a timeout from silence, -1 for default
+ * \param path Optional filesystem path to unlock
+ * \param language Optional language to use (default: Channel's language)
+ *
+ * \retval -1 failure or hangup
+ * \retval 'S' Recording ended from silence timeout
+ * \retval 't' Recording ended from the message exceeding the maximum duration
+ * \retval dtmfchar Recording ended via the return value's DTMF character for either cancel or accept.
+ */
+int ast_play_and_record_with_language(struct ast_channel *chan, const char *playfile, const char *recordfile, int maxtime_sec, const char *fmt, int *duration, int *sound_duration, int silencethreshold, int maxsilence_ms, const char *path, const char *language);
+
+/*!
+ * \brief Record a file based on input from a channel. Use default accept and cancel DTMF.
  *        This function will play "auth-thankyou" upon successful recording.
  *
  * \param chan the channel being recorded
@@ -708,7 +736,8 @@
  * \retval 't' Recording ended from the message exceeding the maximum duration
  * \retval dtmfchar Recording ended via the return value's DTMF character for either cancel or accept.
  */
-int ast_play_and_record(struct ast_channel *chan, const char *playfile, const char *recordfile, int maxtime_sec, const char *fmt, int *duration, int *sound_duration, int silencethreshold, int maxsilence_ms, const char *path);
+#define ast_play_and_record(chan, playfile, recordfile, maxtime, fmt, duration, sound_duration, silence_threshold, maxsilence, path) \
+	ast_play_and_record_with_language(chan, playfile, recordfile, maxtime, fmt, duration, sound_duration, silence_threshold, maxsilence, path, NULL)
 
 /*!
  * \brief Record a file based on input frm a channel. Recording is performed in 'prepend' mode which works a little differently from normal recordings
diff --git a/include/asterisk/file.h b/include/asterisk/file.h
index ec2a38e..16c75d4 100644
--- a/include/asterisk/file.h
+++ b/include/asterisk/file.h
@@ -77,6 +77,20 @@
 int ast_streamfile(struct ast_channel *c, const char *filename, const char *preflang);
 
 /*!
+ * \brief Stream a file until digit
+ *
+ * If the file name is non-empty, try to play it. If the language is NULL
+ * default to using the channel's.
+ *
+ * \note If digits == "" then we can simply check for non-zero.
+ * \return 0 if success.
+ * \retval -1 if error.
+ * \retval digit if interrupted by a digit.
+ */
+int ast_stream_and_wait_with_language(struct ast_channel *chan, const char *file,
+				      const char *digits, const char *language);
+
+/*!
  * \brief stream file until digit
  * If the file name is non-empty, try to play it.
  * \note If digits == "" then we can simply check for non-zero.
@@ -84,7 +98,8 @@
  * \retval -1 if error.
  * \retval digit if interrupted by a digit.
  */
-int ast_stream_and_wait(struct ast_channel *chan, const char *file, const char *digits);
+#define ast_stream_and_wait(chan, file, digits) \
+	ast_stream_and_wait_with_language(chan, file, digits, NULL)
 
 /*! 
  * \brief Stops a stream 
diff --git a/main/app.c b/main/app.c
index a31fa0c..cedb71d 100644
--- a/main/app.c
+++ b/main/app.c
@@ -1081,11 +1081,11 @@
 	return control_streamfile(chan, file, fwd, rev, stop, suspend, restart, skipms, offsetms, NULL);
 }
 
-int ast_play_and_wait(struct ast_channel *chan, const char *fn)
+int ast_play_and_wait_with_language(struct ast_channel *chan, const char *fn, const char *language)
 {
 	int d = 0;
 
-	if ((d = ast_streamfile(chan, fn, ast_channel_language(chan)))) {
+	if ((d = ast_streamfile(chan, fn, language ?: ast_channel_language(chan)))) {
 		return d;
 	}
 
@@ -1115,13 +1115,14 @@
  * \param acceptdtmf DTMF digits that will end the recording.
  * \param canceldtmf DTMF digits that will cancel the recording.
  * \param skip_confirmation_sound If true, don't play auth-thankyou at end. Nice for custom recording prompts in apps.
+ * \param language Optional language to use for playback (default: channel's language)
  *
  * \retval -1 failure or hangup
  * \retval 'S' Recording ended from silence timeout
  * \retval 't' Recording ended from the message exceeding the maximum duration, or via DTMF in prepend mode
  * \retval dtmfchar Recording ended via the return value's DTMF character for either cancel or accept.
  */
-static int __ast_play_and_record(struct ast_channel *chan, const char *playfile, const char *recordfile, int maxtime, const char *fmt, int *duration, int *sound_duration, int beep, int silencethreshold, int maxsilence, const char *path, int prepend, const char *acceptdtmf, const char *canceldtmf, int skip_confirmation_sound)
+static int __ast_play_and_record(struct ast_channel *chan, const char *playfile, const char *recordfile, int maxtime, const char *fmt, int *duration, int *sound_duration, int beep, int silencethreshold, int maxsilence, const char *path, int prepend, const char *acceptdtmf, const char *canceldtmf, int skip_confirmation_sound, const char *language)
 {
 	int d = 0;
 	char *fmts;
@@ -1159,10 +1160,10 @@
 
 	if (playfile || beep) {
 		if (!beep) {
-			d = ast_play_and_wait(chan, playfile);
+			d = ast_play_and_wait_with_language(chan, playfile, language);
 		}
 		if (d > -1) {
-			d = ast_stream_and_wait(chan, "beep", "");
+			d = ast_stream_and_wait_with_language(chan, "beep", "", language);
 		}
 		if (d < 0) {
 			return -1;
@@ -1428,7 +1429,7 @@
 		ast_log(LOG_WARNING, "Unable to restore format %s to channel '%s'\n", ast_getformatname(&rfmt), ast_channel_name(chan));
 	}
 	if ((outmsg == 2) && (!skip_confirmation_sound)) {
-		ast_stream_and_wait(chan, "auth-thankyou", "");
+		ast_stream_and_wait_with_language(chan, "auth-thankyou", "", language);
 	}
 	if (sildet) {
 		ast_dsp_free(sildet);
@@ -1441,17 +1442,16 @@
 
 int ast_play_and_record_full(struct ast_channel *chan, const char *playfile, const char *recordfile, int maxtime, const char *fmt, int *duration, int *sound_duration, int silencethreshold, int maxsilence, const char *path, const char *acceptdtmf, const char *canceldtmf)
 {
-	return __ast_play_and_record(chan, playfile, recordfile, maxtime, fmt, duration, sound_duration, 0, silencethreshold, maxsilence, path, 0, S_OR(acceptdtmf, default_acceptdtmf), S_OR(canceldtmf, default_canceldtmf), 0);
+	return __ast_play_and_record(chan, playfile, recordfile, maxtime, fmt, duration, sound_duration, 0, silencethreshold, maxsilence, path, 0, S_OR(acceptdtmf, default_acceptdtmf), S_OR(canceldtmf, default_canceldtmf), 0, NULL);
 }
 
-int ast_play_and_record(struct ast_channel *chan, const char *playfile, const char *recordfile, int maxtime, const char *fmt, int *duration, int *sound_duration, int silencethreshold, int maxsilence, const char *path)
-{
-	return __ast_play_and_record(chan, playfile, recordfile, maxtime, fmt, duration, sound_duration, 0, silencethreshold, maxsilence, path, 0, default_acceptdtmf, default_canceldtmf, 0);
+int ast_play_and_record_with_language(struct ast_channel *chan, const char *playfile, const char *recordfile, int maxtime, const char *fmt, int *duration, int *sound_duration, int silencethreshold, int maxsilence, const char *path, const char *language) {
+	return __ast_play_and_record(chan, playfile, recordfile, maxtime, fmt, duration, sound_duration, 0, silencethreshold, maxsilence, path, 0, default_acceptdtmf, default_canceldtmf, 0, language);
 }
 
 int ast_play_and_prepend(struct ast_channel *chan, char *playfile, char *recordfile, int maxtime, char *fmt, int *duration, int *sound_duration, int beep, int silencethreshold, int maxsilence)
 {
-	return __ast_play_and_record(chan, playfile, recordfile, maxtime, fmt, duration, sound_duration, beep, silencethreshold, maxsilence, NULL, 1, default_acceptdtmf, default_canceldtmf, 1);
+	return __ast_play_and_record(chan, playfile, recordfile, maxtime, fmt, duration, sound_duration, beep, silencethreshold, maxsilence, NULL, 1, default_acceptdtmf, default_canceldtmf, 1, NULL);
 }
 
 /* Channel group core functions */
diff --git a/main/file.c b/main/file.c
index 436aae9..fb53fb3 100644
--- a/main/file.c
+++ b/main/file.c
@@ -1458,11 +1458,12 @@
  * Return 0 if success, -1 if error, digit if interrupted by a digit.
  * If digits == "" then we can simply check for non-zero.
  */
-int ast_stream_and_wait(struct ast_channel *chan, const char *file, const char *digits)
+int ast_stream_and_wait_with_language(struct ast_channel *chan, const char *file,
+				      const char *digits, const char *language)
 {
 	int res = 0;
 	if (!ast_strlen_zero(file)) {
-		res = ast_streamfile(chan, file, ast_channel_language(chan));
+		res = ast_streamfile(chan, file, language ?: ast_channel_language(chan));
 		if (!res) {
 			res = ast_waitstream(chan, digits);
 		}

-- 
To view, visit https://gerrit.asterisk.org/185
To unsubscribe, visit https://gerrit.asterisk.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I09303f368b39da02c379ea364adcc36d1d76ab89
Gerrit-PatchSet: 1
Gerrit-Project: asterisk
Gerrit-Branch: 11
Gerrit-Owner: Kevin Harwell <kharwell at digium.com>



More information about the asterisk-code-review mailing list