[asterisk-commits] jrose: branch jrose/bridge_projects r385267 - in /team/jrose/bridge_projects:...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Wed Apr 10 14:34:58 CDT 2013


Author: jrose
Date: Wed Apr 10 14:34:56 2013
New Revision: 385267

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=385267
Log:
Actually act on the various parked_____ options for parking lots

These include: parkedplay + courtesytone, parkedcalltransfers,
parkedcallreparking, parkedcallhangup, parkedcallrecording

Modified:
    team/jrose/bridge_projects/include/asterisk/features.h
    team/jrose/bridge_projects/main/features.c
    team/jrose/bridge_projects/res/parking/parking_applications.c
    team/jrose/bridge_projects/res/parking/parking_bridge.c
    team/jrose/bridge_projects/res/parking/parking_controller.c
    team/jrose/bridge_projects/res/parking/res_parking.h

Modified: team/jrose/bridge_projects/include/asterisk/features.h
URL: http://svnview.digium.com/svn/asterisk/team/jrose/bridge_projects/include/asterisk/features.h?view=diff&rev=385267&r1=385266&r2=385267
==============================================================================
--- team/jrose/bridge_projects/include/asterisk/features.h (original)
+++ team/jrose/bridge_projects/include/asterisk/features.h Wed Apr 10 14:34:56 2013
@@ -26,6 +26,7 @@
 
 #include "asterisk/pbx.h"
 #include "asterisk/linkedlists.h"
+#include "asterisk/bridging.h"
 
 #define FEATURE_MAX_LEN		11
 #define FEATURE_APP_LEN		64
@@ -181,6 +182,18 @@
  */
 void ast_bridge_end_dtmf(struct ast_channel *chan, char digit, struct timeval start, const char *why);
 
+/*!
+ * \brief Setup bridge channel features.
+ * \since 12.0.0
+ *
+ * \param features Bridge features to setup.
+ * \param flags DTMF features to enable.
+ *
+ * \retval 0 on success.
+ * \retval -1 on failure.
+ */
+int ast_setup_bridge_channel_features(struct ast_bridge_features *features, struct ast_flags *flags);
+
 /*! \brief Bridge a call, optionally allowing redirection */
 int ast_bridge_call(struct ast_channel *chan, struct ast_channel *peer,struct ast_bridge_config *config);
 

Modified: team/jrose/bridge_projects/main/features.c
URL: http://svnview.digium.com/svn/asterisk/team/jrose/bridge_projects/main/features.c?view=diff&rev=385267&r1=385266&r2=385267
==============================================================================
--- team/jrose/bridge_projects/main/features.c (original)
+++ team/jrose/bridge_projects/main/features.c Wed Apr 10 14:34:56 2013
@@ -4136,18 +4136,7 @@
 		digit, ast_channel_name(chan), why, duration);
 }
 
-/*!
- * \internal
- * \brief Setup bridge channel features.
- * \since 12.0.0
- *
- * \param features Bridge features to setup.
- * \param flags DTMF features to enable.
- *
- * \retval 0 on success.
- * \retval -1 on failure.
- */
-static int setup_bridge_channel_features(struct ast_bridge_features *features, struct ast_flags *flags)
+int ast_setup_bridge_channel_features(struct ast_bridge_features *features, struct ast_flags *flags)
 {
 	struct ast_call_feature *dtmf;
 	int res = 0;
@@ -4386,8 +4375,8 @@
 	res = ast_bridge_features_init(&chan_features);
 	peer_features = ast_bridge_features_new();
 	if (res || !peer_features
-		|| setup_bridge_channel_features(peer_features, &config->features_callee)
-		|| setup_bridge_channel_features(&chan_features, &config->features_caller)) {
+		|| ast_setup_bridge_channel_features(peer_features, &config->features_callee)
+		|| ast_setup_bridge_channel_features(&chan_features, &config->features_caller)) {
 		ast_bridge_features_destroy(peer_features);
 		ast_bridge_features_cleanup(&chan_features);
 		bridge_failed_peer_goto(chan, peer);

Modified: team/jrose/bridge_projects/res/parking/parking_applications.c
URL: http://svnview.digium.com/svn/asterisk/team/jrose/bridge_projects/res/parking/parking_applications.c?view=diff&rev=385267&r1=385266&r2=385267
==============================================================================
--- team/jrose/bridge_projects/res/parking/parking_applications.c (original)
+++ team/jrose/bridge_projects/res/parking/parking_applications.c Wed Apr 10 14:34:56 2013
@@ -37,6 +37,7 @@
 #include "asterisk/module.h"
 #include "asterisk/app.h"
 #include "asterisk/say.h"
+#include "asterisk/features.h"
 
 /*** DOCUMENTATION
 	<application name="Park" language="en_US">
@@ -217,13 +218,14 @@
 	return 0;
 }
 
-int park_common_setup(struct parking_lot_state **lot, struct ast_bridge **parking_bridge, struct parked_user **pu,
+int park_common_setup(struct parking_lot_state **lot_state, struct ast_bridge **parking_bridge, struct parked_user **pu,
 		struct ast_channel *parker, struct ast_channel *parkee, const char *app_data)
 {
 	int silence_announcements = 0;
 	int use_ringing = 0;
 	int randomize = 0;
 	int time_limit = -1;
+	int find_lot_mode = 0;
 	RAII_VAR(char *, comeback_override, NULL, ast_free);
 	RAII_VAR(char *, lot_name, NULL, ast_free);
 
@@ -232,22 +234,28 @@
 		park_app_parse_data(app_data, &silence_announcements, &use_ringing, &randomize, &time_limit, &comeback_override, &lot_name);
 	}
 
-	/* Now find out which parking lot we want to park it into. */
+	/* Now find out which parking lot_state we want to park it into. */
 	if (ast_strlen_zero(lot_name)) {
-		*lot = channel_find_parking_lot_state(parker);
+		*lot_state = channel_find_parking_lot_state(parker);
 	} else {
-		*lot = parking_lot_state_find_by_name(lot_name);
-	}
-
-	if (!*lot) {
-		ast_log(LOG_ERROR, "Could not find the requested parking lot\n");
+		*lot_state = parking_lot_state_find_by_name(lot_name);
+		find_lot_mode = 1;
+	}
+
+	if (!*lot_state) {
+		if (find_lot_mode) {
+			ast_log(LOG_ERROR, "Could not find requested parking lot: '%s'\n", lot_name);
+		} else {
+			ast_log(LOG_ERROR, "Could not find parking lot specified by channel variable PARKINGLOT "
+				"(or 'default' if that variable does not exist for channel '%s')\n", ast_channel_name(parker));
+		}
 		ast_stream_and_wait(parker, "pbx-parkingfailed", "");
 		return -1;
 	}
 
-	ao2_lock(*lot);
-	*parking_bridge = parking_lot_state_get_bridge(*lot);
-	ao2_unlock(*lot);
+	ao2_lock(*lot_state);
+	*parking_bridge = parking_lot_state_get_bridge(*lot_state);
+	ao2_unlock(*lot_state);
 
 	if (!*parking_bridge) {
 		ast_log(LOG_ERROR, "Could not acquire holding bridge to park into\n");
@@ -255,7 +263,7 @@
 		return -1;
 	}
 
-	*pu = generate_parked_user(*lot, parkee, parker, randomize, time_limit);
+	*pu = generate_parked_user(*lot_state, parkee, parker, randomize, time_limit);
 
 	if (!*pu) {
 		ast_log(LOG_ERROR, "Failed to create parked user for channel %s, can not park.\n", ast_channel_name(parkee));
@@ -269,7 +277,7 @@
 	}
 
 	/* Apply relevant bridge roles and such to the parking channel */
-	parking_channel_set_roles(parkee, *lot, use_ringing);
+	parking_channel_set_roles(parkee, *lot_state, use_ringing);
 
 	/* If we need to go somewhere special after timeout, set special comeback arguments */
 	if (!ast_strlen_zero(comeback_override)) {
@@ -281,7 +289,7 @@
 
 int park_app_exec(struct ast_channel *chan, const char *data)
 {
-	RAII_VAR(struct parking_lot_state *, lot, NULL, ao2_cleanup);
+	RAII_VAR(struct parking_lot_state *, lot_state, NULL, ao2_cleanup);
 	RAII_VAR(struct parked_user *, pu, NULL, ao2_cleanup);
 	RAII_VAR(struct ast_bridge *, parking_bridge, NULL, ao2_cleanup);
 
@@ -294,12 +302,18 @@
 	}
 
 	/* Handle all the common aprking setup stuff */
-	if (park_common_setup(&lot, &parking_bridge, &pu, chan, chan, data)) {
+	if (park_common_setup(&lot_state, &parking_bridge, &pu, chan, chan, data)) {
+		return -1;
+	}
+
+	/* Initialize bridge features for the channel. */
+	res = ast_bridge_features_init(&chan_features);
+	if (res) {
+		ast_bridge_features_cleanup(&chan_features);
 		return -1;
 	}
 
 	/* Now for the fun part... park it! */
-	ast_bridge_features_init(&chan_features);
 	ast_bridge_join(parking_bridge, chan, NULL, &chan_features, NULL, 0);
 
 	/*
@@ -322,14 +336,13 @@
 
 int parked_call_app_exec(struct ast_channel *chan, const char *data)
 {
-	RAII_VAR(struct parking_lot_state *, lot, NULL, ao2_cleanup);
+	RAII_VAR(struct parking_lot_state *, lot_state, NULL, ao2_cleanup);
 	RAII_VAR(struct parked_user *, pu, NULL, ao2_cleanup); /* Parked user being retrieved */
 	RAII_VAR(struct ast_bridge *, parking_bridge, NULL, ao2_cleanup);
+	struct ast_bridge *retrieval_bridge;
+	int res;
 	int target_space = -1;
-
-	struct ast_bridge *bridge;
-
-	//struct ast_bridge_features chan_features;
+	struct ast_bridge_features chan_features;
 	char *parse;
 
 	AST_DECLARE_APP_ARGS(args,
@@ -341,13 +354,18 @@
 	parse = ast_strdupa(data);
 	AST_STANDARD_APP_ARGS(args, parse);
 
+	/* Answer the channel if needed */
+	if (ast_channel_state(chan) != AST_STATE_UP) {
+		ast_answer(chan);
+	}
+
+	/* Figure out which parking lot we should be retrieving from and if it exists. */
 	if (ast_strlen_zero(args.lot_name)) {
-		lot = channel_find_parking_lot_state(chan);
+		lot_state = channel_find_parking_lot_state(chan);
 	} else {
-		lot = parking_lot_state_find_by_name(args.lot_name);
-	}
-
-	if (!lot) {
+		lot_state = parking_lot_state_find_by_name(args.lot_name);
+	}
+	if (!lot_state) {
 		ast_log(LOG_ERROR, "Could not find the requested parking lot\n");
 		ast_stream_and_wait(chan, "pbx-invalidpark", "");
 		return -1;
@@ -361,34 +379,46 @@
 		}
 	}
 
-	bridge = ast_bridge_base_new(
+	/* Attempt to get the parked user from the parking lot */
+	pu = parking_lot_state_retrieve_parked_user(lot_state, target_space);
+	if (!pu) {
+		ast_stream_and_wait(chan, "pbx-invalidpark", "");
+		return -1;
+	}
+
+	/* Create bridge */
+	retrieval_bridge = ast_bridge_base_new(
 		AST_BRIDGE_CAPABILITY_NATIVE | AST_BRIDGE_CAPABILITY_1TO1MIX | AST_BRIDGE_CAPABILITY_MULTIMIX,
 		AST_BRIDGE_FLAG_DISSOLVE_HANGUP | AST_BRIDGE_FLAG_SMART);
-
-	if (!bridge) {
-		return -1;
-	}
-
-	/* answer the channel if needed */
-	if (ast_channel_state(chan) != AST_STATE_UP) {
-		ast_answer(chan);
-	}
-
-	pu = parking_lot_state_retrieve_parked_user(lot, target_space);
-
-	if (!pu) {
-		ast_stream_and_wait(chan, "pbx-invalidpark", "");
+	if (!retrieval_bridge) {
 		return -1;
 	}
 
 	/* Move the parkee into the new bridge */
-	if (ast_bridge_move(lot->parking_bridge, bridge, pu->chan)) {
-		ast_bridge_destroy(bridge);
-		return -1;
+	if (ast_bridge_move(lot_state->parking_bridge, retrieval_bridge, pu->chan)) {
+		ast_bridge_destroy(retrieval_bridge);
+		return -1;
+	}
+
+	/* Initialize our bridge features */
+	res = ast_bridge_features_init(&chan_features);
+	if (res) {
+		ast_bridge_features_cleanup(&chan_features);
+		return -1;
+	}
+
+	/* Set the features */
+	parked_call_retrieve_enable_features(&chan_features, lot_state, AST_FEATURE_FLAG_BYCALLER);
+
+	/* If the parkedplay option is set for the caller to hear, play that tone now. */
+	if (lot_state->parkedplay & AST_FEATURE_FLAG_BYCALLER) {
+		ast_stream_and_wait(chan, lot_state->courtesytone, NULL);
 	}
 
 	/* Now we should try to join the new bridge ourselves... */
-	ast_bridge_join(bridge, chan, NULL, /* XXX features go here! */ NULL, NULL, 1);
+	ast_bridge_join(retrieval_bridge, chan, NULL, &chan_features, NULL, 1);
+
+	ast_bridge_features_cleanup(&chan_features);
 
 	return 0;
 }

Modified: team/jrose/bridge_projects/res/parking/parking_bridge.c
URL: http://svnview.digium.com/svn/asterisk/team/jrose/bridge_projects/res/parking/parking_bridge.c?view=diff&rev=385267&r1=385266&r2=385267
==============================================================================
--- team/jrose/bridge_projects/res/parking/parking_bridge.c (original)
+++ team/jrose/bridge_projects/res/parking/parking_bridge.c Wed Apr 10 14:34:56 2013
@@ -27,6 +27,7 @@
 #include "asterisk/logger.h"
 #include "res_parking.h"
 #include "asterisk/astobj2.h"
+#include "asterisk/features.h"
 
 struct ast_bridge_parking
 {
@@ -124,10 +125,8 @@
 	}
 
 	/* Apply parking duration limits */
-	if (bridge_channel->features) {
-		reset_parked_time(pu);
-		parking_set_duration(bridge_channel->features, pu);
-	}
+	reset_parked_time(pu);
+	parking_set_duration(bridge_channel->features, pu);
 
 	/* Set this to the bridge pvt so that we don't have to refind the parked user associated with this bridge channel again. */
 	bridge_channel->bridge_pvt = pu;
@@ -154,6 +153,7 @@
 static void bridge_parking_pull(struct ast_bridge_parking *self, struct ast_bridge_channel *bridge_channel)
 {
 	struct parked_user *pu = bridge_channel->bridge_pvt;
+	struct ast_bridge_features *features = bridge_channel->features;
 	ast_bridge_base_v_table.pull(&self->base, bridge_channel);
 
 	/* This should only happen if the exiting channel was swapped out */
@@ -186,8 +186,14 @@
 		return;
 	case PARK_ANSWERED:
 		/* If answered or forced, the channel should be pulled from the bridge as part of that process and unlinked from
-		 * the parking lot afterwards. */
+		 * the parking lot afterwards. We do need to apply bridge features though and play the courtesy tone if set. */
 		publish_parked_call(pu, PARKED_CALL_UNPARKED);
+		parked_call_retrieve_enable_features(features, pu->lot_state, AST_FEATURE_FLAG_BYCALLEE);
+
+		if (pu->lot_state->parkedplay & AST_FEATURE_FLAG_BYCALLEE) {
+			ast_bridge_channel_queue_playfile(bridge_channel, NULL, pu->lot_state->courtesytone, NULL);
+		}
+
 		return;
 	case PARK_TIMEOUT:
 		/* Timeout is similar to abandon because it simply sets the bridge state to end and doesn't

Modified: team/jrose/bridge_projects/res/parking/parking_controller.c
URL: http://svnview.digium.com/svn/asterisk/team/jrose/bridge_projects/res/parking/parking_controller.c?view=diff&rev=385267&r1=385266&r2=385267
==============================================================================
--- team/jrose/bridge_projects/res/parking/parking_controller.c (original)
+++ team/jrose/bridge_projects/res/parking/parking_controller.c Wed Apr 10 14:34:56 2013
@@ -30,6 +30,7 @@
 #include "asterisk/utils.h"
 #include "asterisk/manager.h"
 #include "asterisk/test.h"
+#include "asterisk/features.h"
 
 struct ast_bridge *parking_lot_state_get_bridge(struct parking_lot_state *state)
 {
@@ -187,6 +188,37 @@
 	/* Bump the ref count by 1 since the RAII_VAR will eat the reference otherwise */
 	ao2_ref(user, +1);
 	return user;
+}
+
+void parked_call_retrieve_enable_features(struct ast_bridge_features *features, struct parking_lot_state *lot_state, int recipient_mode)
+{
+	struct ast_flags feature_flags = { 0 };
+
+	if (lot_state->parkedcalltransfers & recipient_mode) {
+		ast_set_flag(&feature_flags, AST_FEATURE_REDIRECT);
+		ast_set_flag(&feature_flags, AST_FEATURE_ATXFER);
+	}
+
+	if (lot_state->parkedcallreparking & recipient_mode) {
+		ast_set_flag(&feature_flags, AST_FEATURE_PARKCALL);
+	}
+
+	if (lot_state->parkedcallhangup & recipient_mode) {
+		ast_set_flag(&feature_flags, AST_FEATURE_DISCONNECT);
+	}
+
+	if (lot_state->parkedcallrecording & recipient_mode) {
+		ast_set_flag(&feature_flags, AST_FEATURE_AUTOMON);
+		ast_set_flag(&feature_flags, AST_FEATURE_AUTOMIXMON);
+	}
+
+	if (ast_setup_bridge_channel_features(features, &feature_flags)) {
+		/* Some features were applied that weren't explicitly mapped. We can safely ignore this. */
+		ast_debug(10, "One or more features could not be applied because they weren't mapped. "
+			"Check debug output for ast_bridge_features_enable in bridging.c to see which ones.\n");
+	}
+
+	return;
 }
 
 static void destroy_parked_user(void *obj)

Modified: team/jrose/bridge_projects/res/parking/res_parking.h
URL: http://svnview.digium.com/svn/asterisk/team/jrose/bridge_projects/res/parking/res_parking.h?view=diff&rev=385267&r1=385266&r2=385267
==============================================================================
--- team/jrose/bridge_projects/res/parking/res_parking.h (original)
+++ team/jrose/bridge_projects/res/parking/res_parking.h Wed Apr 10 14:34:56 2013
@@ -209,6 +209,17 @@
 
 /*!
  * \since 12
+ * \brief Apply features based on the parking lot feature options
+ *
+ * \param features Which feature set is being modified
+ * \param lot_state parking lot state which establishes the features used
+ * \param recipient_mode AST_FEATURE_FLAG_BYCALLER if the user is the retriever
+ *                       AST_FEATURE_FLAG_BYCALLEE if the user is the parkee
+ */
+void parked_call_retrieve_enable_features(struct ast_bridge_features *features, struct parking_lot_state *lot_state, int recipient_mode);
+
+/*!
+ * \since 12
  * \brief Set necessary bridge roles on a channel that is about to enter a parking lot
  *
  * \param chan Entering channel




More information about the asterisk-commits mailing list