[asterisk-commits] rmudgett: branch rmudgett/bridge_tasks r385007 - in /team/rmudgett/bridge_tas...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Mon Apr 8 14:51:35 CDT 2013


Author: rmudgett
Date: Mon Apr  8 14:51:31 2013
New Revision: 385007

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=385007
Log:
Add support for playing a file on a bridge channel.

* Added AST_BRIDGE_ACTION_PLAY_FILE.

* Refactored code to make it easier to put action frames onto the bridge
channel write queue.

Modified:
    team/rmudgett/bridge_tasks/bridges/bridge_builtin_interval_features.c
    team/rmudgett/bridge_tasks/bridges/bridge_softmix.c
    team/rmudgett/bridge_tasks/include/asterisk/bridging.h
    team/rmudgett/bridge_tasks/main/bridging.c

Modified: team/rmudgett/bridge_tasks/bridges/bridge_builtin_interval_features.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/bridge_tasks/bridges/bridge_builtin_interval_features.c?view=diff&rev=385007&r1=385006&r2=385007
==============================================================================
--- team/rmudgett/bridge_tasks/bridges/bridge_builtin_interval_features.c (original)
+++ team/rmudgett/bridge_tasks/bridges/bridge_builtin_interval_features.c Mon Apr  8 14:51:31 2013
@@ -98,7 +98,13 @@
 		ast_stream_and_wait(bridge_channel->chan, file, AST_DIGIT_NONE);
 	}
 
-	/* It may be necessary to resume music on hold after we finish playing the announcment. */
+	/*
+	 * It may be necessary to resume music on hold after we finish
+	 * playing the announcment.
+	 *
+	 * XXX We have no idea what MOH class was in use before playing
+	 * the file.
+	 */
 	if (ast_test_flag(ast_channel_flags(bridge_channel->chan), AST_FLAG_MOH)) {
 		ast_moh_start(bridge_channel->chan, NULL, NULL);
 	}

Modified: team/rmudgett/bridge_tasks/bridges/bridge_softmix.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/bridge_tasks/bridges/bridge_softmix.c?view=diff&rev=385007&r1=385006&r2=385007
==============================================================================
--- team/rmudgett/bridge_tasks/bridges/bridge_softmix.c (original)
+++ team/rmudgett/bridge_tasks/bridges/bridge_softmix.c Mon Apr  8 14:51:31 2013
@@ -382,12 +382,7 @@
  */
 static void softmix_src_change(struct ast_bridge_channel *bridge_channel)
 {
-	struct ast_frame frame = {
-		.frametype = AST_FRAME_CONTROL,
-		.subclass.integer = AST_CONTROL_SRCCHANGE
-	};
-
-	ast_bridge_channel_queue_frame(bridge_channel, &frame);
+	ast_bridge_channel_queue_control_data(bridge_channel, AST_CONTROL_SRCCHANGE, NULL, 0);
 }
 
 /*! \brief Function called when a channel is joined into the bridge */

Modified: team/rmudgett/bridge_tasks/include/asterisk/bridging.h
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/bridge_tasks/include/asterisk/bridging.h?view=diff&rev=385007&r1=385006&r2=385007
==============================================================================
--- team/rmudgett/bridge_tasks/include/asterisk/bridging.h (original)
+++ team/rmudgett/bridge_tasks/include/asterisk/bridging.h Mon Apr  8 14:51:31 2013
@@ -190,6 +190,8 @@
 	AST_BRIDGE_ACTION_TALKING_START,
 	/*! Bridged channel is to indicate talking stop */
 	AST_BRIDGE_ACTION_TALKING_STOP,
+	/*! Bridge channel is to play the indicated sound file. */
+	AST_BRIDGE_ACTION_PLAY_FILE,
 	/*! Bridge channel is to run the indicated application. */
 	AST_BRIDGE_ACTION_RUN_APP,
 
@@ -900,6 +902,32 @@
 int ast_bridge_channel_queue_frame(struct ast_bridge_channel *bridge_channel, struct ast_frame *fr);
 
 /*!
+ * \brief Used to queue an action frame onto a bridge channel and write an action frame into a bridge.
+ * \since 12.0.0
+ *
+ * \param bridge_channel Which channel work with.
+ * \param action Type of bridge action frame.
+ * \param data Frame payload data to pass.
+ * \param datalen Frame payload data length to pass.
+ *
+ * \return Nothing
+ */
+typedef void (*ast_bridge_channel_post_action_data)(struct ast_bridge_channel *bridge_channel, enum ast_bridge_action_type action, const void *data, size_t datalen);
+
+/*!
+ * \brief Queue an action frame onto the bridge channel with data.
+ * \since 12.0.0
+ *
+ * \param bridge_channel Which channel to queue the frame onto.
+ * \param action Type of bridge action frame.
+ * \param data Frame payload data to pass.
+ * \param datalen Frame payload data length to pass.
+ *
+ * \return Nothing
+ */
+void ast_bridge_channel_queue_action_data(struct ast_bridge_channel *bridge_channel, enum ast_bridge_action_type action, const void *data, size_t datalen);
+
+/*!
  * \brief Write an action frame into the bridge with data.
  * \since 12.0.0
  *
@@ -911,6 +939,19 @@
  * \return Nothing
  */
 void ast_bridge_channel_write_action_data(struct ast_bridge_channel *bridge_channel, enum ast_bridge_action_type action, const void *data, size_t datalen);
+
+/*!
+ * \brief Queue a control frame onto the bridge channel with data.
+ * \since 12.0.0
+ *
+ * \param bridge_channel Which channel to queue the frame onto.
+ * \param control Type of control frame.
+ * \param data Frame payload data to pass.
+ * \param datalen Frame payload data length to pass.
+ *
+ * \return Nothing
+ */
+void ast_bridge_channel_queue_control_data(struct ast_bridge_channel *bridge_channel, enum ast_control_frame_type control, const void *data, size_t datalen);
 
 /*!
  * \brief Write a control frame into the bridge with data.
@@ -960,6 +1001,74 @@
 void ast_bridge_channel_write_app(struct ast_bridge_channel *bridge_channel, const char *app_name, const char *app_args, const char *moh_class);
 
 /*!
+ * \brief Queue a bridge action run application frame onto the bridge channel.
+ * \since 12.0.0
+ *
+ * \param bridge_channel Which channel to put the frame onto
+ * \param app_name Dialplan application name.
+ * \param app_args Arguments for the application. (NULL or empty for no arguments)
+ * \param moh_class MOH class to request bridge peers to hear while application is running.
+ *     NULL if no MOH.
+ *     Empty if default MOH class.
+ *
+ * \note This is intended to be called by bridge hooks.
+ *
+ * \return Nothing
+ */
+void ast_bridge_channel_queue_app(struct ast_bridge_channel *bridge_channel, const char *app_name, const char *app_args, const char *moh_class);
+
+/*!
+ * \brief Play a file on the bridge channel.
+ * \since 12.0.0
+ *
+ * \param bridge_channel Which channel to play the file on
+ * \param custom_play Call this function to play the playfile. (NULL if normal sound file to play)
+ * \param playfile Sound filename to play.
+ * \param moh_class MOH class to request bridge peers to hear while file is played.
+ *     NULL if no MOH.
+ *     Empty if default MOH class.
+ *
+ * \note This is intended to be called by bridge hooks.
+ *
+ * \return Nothing
+ */
+void ast_bridge_channel_playfile(struct ast_bridge_channel *bridge_channel, void (*custom_play)(const char *playfile), const char *playfile, const char *moh_class);
+
+/*!
+ * \brief Write a bridge action play file frame into the bridge.
+ * \since 12.0.0
+ *
+ * \param bridge_channel Which channel is putting the frame into the bridge
+ * \param custom_play Call this function to play the playfile. (NULL if normal sound file to play)
+ * \param playfile Sound filename to play.
+ * \param moh_class MOH class to request bridge peers to hear while file is played.
+ *     NULL if no MOH.
+ *     Empty if default MOH class.
+ *
+ * \note This is intended to be called by bridge hooks.
+ *
+ * \return Nothing
+ */
+void ast_bridge_channel_write_playfile(struct ast_bridge_channel *bridge_channel, void (*custom_play)(const char *playfile), const char *playfile, const char *moh_class);
+
+/*!
+ * \brief Queue a bridge action play file frame onto the bridge channel.
+ * \since 12.0.0
+ *
+ * \param bridge_channel Which channel to put the frame onto.
+ * \param custom_play Call this function to play the playfile. (NULL if normal sound file to play)
+ * \param playfile Sound filename to play.
+ * \param moh_class MOH class to request bridge peers to hear while file is played.
+ *     NULL if no MOH.
+ *     Empty if default MOH class.
+ *
+ * \note This is intended to be called by bridge hooks.
+ *
+ * \return Nothing
+ */
+void ast_bridge_channel_queue_playfile(struct ast_bridge_channel *bridge_channel, void (*custom_play)(const char *playfile), const char *playfile, const char *moh_class);
+
+/*!
  * \brief Restore the formats of a bridge channel's channel to how they were before bridge_channel_join
  * \since 12.0.0
  *

Modified: team/rmudgett/bridge_tasks/main/bridging.c
URL: http://svnview.digium.com/svn/asterisk/team/rmudgett/bridge_tasks/main/bridging.c?view=diff&rev=385007&r1=385006&r2=385007
==============================================================================
--- team/rmudgett/bridge_tasks/main/bridging.c (original)
+++ team/rmudgett/bridge_tasks/main/bridging.c Mon Apr  8 14:51:31 2013
@@ -331,6 +331,30 @@
 	return 0;
 }
 
+void ast_bridge_channel_queue_action_data(struct ast_bridge_channel *bridge_channel, enum ast_bridge_action_type action, const void *data, size_t datalen)
+{
+	struct ast_frame frame = {
+		.frametype = AST_FRAME_BRIDGE_ACTION,
+		.subclass.integer = action,
+		.datalen = datalen,
+		.data.ptr = (void *) data,
+	};
+
+	ast_bridge_channel_queue_frame(bridge_channel, &frame);
+}
+
+void ast_bridge_channel_queue_control_data(struct ast_bridge_channel *bridge_channel, enum ast_control_frame_type control, const void *data, size_t datalen)
+{
+	struct ast_frame frame = {
+		.frametype = AST_FRAME_CONTROL,
+		.subclass.integer = control,
+		.datalen = datalen,
+		.data.ptr = (void *) data,
+	};
+
+	ast_bridge_channel_queue_frame(bridge_channel, &frame);
+}
+
 void ast_bridge_channel_restore_formats(struct ast_bridge_channel *bridge_channel)
 {
 	/* Restore original formats of the channel as they came in */
@@ -768,7 +792,8 @@
 		data->moh_offset ? &data->app_name[data->moh_offset] : NULL);
 }
 
-void ast_bridge_channel_write_app(struct ast_bridge_channel *bridge_channel, const char *app_name, const char *app_args, const char *moh_class)
+static void payload_helper_app(ast_bridge_channel_post_action_data post_it,
+	struct ast_bridge_channel *bridge_channel, const char *app_name, const char *app_args, const char *moh_class)
 {
 	struct bridge_run_app *app_data;
 	size_t len_name = strlen(app_name) + 1;
@@ -788,8 +813,109 @@
 		strcpy(&app_data->app_name[app_data->moh_offset], moh_class);/* Safe */
 	}
 
-	ast_bridge_channel_write_action_data(bridge_channel,
-		AST_BRIDGE_ACTION_RUN_APP, app_data, len_data);
+	post_it(bridge_channel, AST_BRIDGE_ACTION_RUN_APP, app_data, len_data);
+}
+
+void ast_bridge_channel_write_app(struct ast_bridge_channel *bridge_channel, const char *app_name, const char *app_args, const char *moh_class)
+{
+	payload_helper_app(ast_bridge_channel_write_action_data,
+		bridge_channel, app_name, app_args, moh_class);
+}
+
+void ast_bridge_channel_queue_app(struct ast_bridge_channel *bridge_channel, const char *app_name, const char *app_args, const char *moh_class)
+{
+	payload_helper_app(ast_bridge_channel_queue_action_data,
+		bridge_channel, app_name, app_args, moh_class);
+}
+
+void ast_bridge_channel_playfile(struct ast_bridge_channel *bridge_channel, void (*custom_play)(const char *playfile), const char *playfile, const char *moh_class)
+{
+	if (moh_class) {
+		if (ast_strlen_zero(moh_class)) {
+			ast_bridge_channel_write_control_data(bridge_channel, AST_CONTROL_HOLD,
+				NULL, 0);
+		} else {
+			ast_bridge_channel_write_control_data(bridge_channel, AST_CONTROL_HOLD,
+				moh_class, strlen(moh_class) + 1);
+		}
+	}
+	if (custom_play) {
+		custom_play(playfile);
+	} else {
+		ast_stream_and_wait(bridge_channel->chan, playfile, AST_DIGIT_NONE);
+	}
+	if (moh_class) {
+		ast_bridge_channel_write_control_data(bridge_channel, AST_CONTROL_UNHOLD,
+			NULL, 0);
+	}
+
+	/*
+	 * It may be necessary to resume music on hold after we finish
+	 * playing the announcment.
+	 *
+	 * XXX We have no idea what MOH class was in use before playing
+	 * the file.
+	 */
+	if (ast_test_flag(ast_channel_flags(bridge_channel->chan), AST_FLAG_MOH)) {
+		ast_moh_start(bridge_channel->chan, NULL, NULL);
+	}
+}
+
+struct bridge_playfile {
+	/*! Call this function to play the playfile. (NULL if normal sound file to play) */
+	void (*custom_play)(const char *playfile);
+	/*! Offset into playfile[] where the MOH class name starts.  (zero if no MOH)*/
+	int moh_offset;
+	/*! Filename to play. */
+	char playfile[0];
+};
+
+/*!
+ * \internal
+ * \brief Handle the playfile bridge action.
+ * \since 12.0.0
+ *
+ * \param bridge_channel Which channel to play a file on.
+ * \param payload Action frame payload to play a file.
+ *
+ * \return Nothing
+ */
+static void bridge_channel_playfile(struct ast_bridge_channel *bridge_channel, struct bridge_playfile *payload)
+{
+	ast_bridge_channel_playfile(bridge_channel, payload->custom_play, payload->playfile,
+		payload->moh_offset ? &payload->playfile[payload->moh_offset] : NULL);
+}
+
+static void payload_helper_playfile(ast_bridge_channel_post_action_data post_it,
+	struct ast_bridge_channel *bridge_channel, void (*custom_play)(const char *playfile), const char *playfile, const char *moh_class)
+{
+	struct bridge_playfile *payload;
+	size_t len_name = strlen(playfile) + 1;
+	size_t len_moh = !moh_class ? 0 : strlen(moh_class) + 1;
+	size_t len_payload = sizeof(*payload) + len_name + len_moh;
+
+	/* Fill in play file frame data. */
+	payload = alloca(len_payload);
+	payload->custom_play = custom_play;
+	payload->moh_offset = len_moh ? len_name : 0;
+	strcpy(payload->playfile, playfile);/* Safe */
+	if (moh_class) {
+		strcpy(&payload->playfile[payload->moh_offset], moh_class);/* Safe */
+	}
+
+	post_it(bridge_channel, AST_BRIDGE_ACTION_PLAY_FILE, payload, len_payload);
+}
+
+void ast_bridge_channel_write_playfile(struct ast_bridge_channel *bridge_channel, void (*custom_play)(const char *playfile), const char *playfile, const char *moh_class)
+{
+	payload_helper_playfile(ast_bridge_channel_write_action_data,
+		bridge_channel, custom_play, playfile, moh_class);
+}
+
+void ast_bridge_channel_queue_playfile(struct ast_bridge_channel *bridge_channel, void (*custom_play)(const char *playfile), const char *playfile, const char *moh_class)
+{
+	payload_helper_playfile(ast_bridge_channel_queue_action_data,
+		bridge_channel, custom_play, playfile, moh_class);
 }
 
 /*!
@@ -1875,6 +2001,13 @@
 	case AST_BRIDGE_ACTION_TALKING_STOP:
 		bridge_channel_talking(bridge_channel,
 			action->subclass.integer == AST_BRIDGE_ACTION_TALKING_START);
+		break;
+	case AST_BRIDGE_ACTION_PLAY_FILE:
+		bridge_channel_suspend(bridge_channel);
+		ast_indicate(bridge_channel->chan, AST_CONTROL_SRCUPDATE);
+		bridge_channel_playfile(bridge_channel, action->data.ptr);
+		ast_indicate(bridge_channel->chan, AST_CONTROL_SRCUPDATE);
+		bridge_channel_unsuspend(bridge_channel);
 		break;
 	case AST_BRIDGE_ACTION_RUN_APP:
 		bridge_channel_suspend(bridge_channel);




More information about the asterisk-commits mailing list