[asterisk-commits] jrose: branch group/bridge_construction r388929 - in /team/group/bridge_const...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Thu May 16 11:58:28 CDT 2013


Author: jrose
Date: Thu May 16 11:58:25 2013
New Revision: 388929

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=388929
Log:
app_confbridge: Refactor confbridge events to use stasis

(closes issue ASTERISK-21468)
Reported by: Matt Jordan
Review: https://reviewboard.asterisk.org/r/2510/

Added:
    team/group/bridge_construction/apps/confbridge/confbridge_manager.c   (with props)
Modified:
    team/group/bridge_construction/apps/app_confbridge.c
    team/group/bridge_construction/apps/confbridge/include/confbridge.h

Modified: team/group/bridge_construction/apps/app_confbridge.c
URL: http://svnview.digium.com/svn/asterisk/team/group/bridge_construction/apps/app_confbridge.c?view=diff&rev=388929&r1=388928&r2=388929
==============================================================================
--- team/group/bridge_construction/apps/app_confbridge.c (original)
+++ team/group/bridge_construction/apps/app_confbridge.c Thu May 16 11:58:25 2013
@@ -67,6 +67,9 @@
 #include "asterisk/paths.h"
 #include "asterisk/manager.h"
 #include "asterisk/test.h"
+#include "asterisk/stasis.h"
+#include "asterisk/stasis_bridging.h"
+#include "asterisk/json.h"
 
 /*** DOCUMENTATION
 	<application name="ConfBridge" language="en_US">
@@ -412,183 +415,77 @@
 	return "";
 }
 
-static void send_conf_start_event(const char *conf_name)
-{
-	/*** DOCUMENTATION
-		<managerEventInstance>
-			<synopsis>Raised when a conference starts.</synopsis>
-			<syntax>
-				<parameter name="Conference">
-					<para>The name of the Confbridge conference.</para>
-				</parameter>
-			</syntax>
-			<see-also>
-				<ref type="managerEvent">ConfbridgeEnd</ref>
-				<ref type="application">ConfBridge</ref>
-			</see-also>
-		</managerEventInstance>
-	***/
-	manager_event(EVENT_FLAG_CALL, "ConfbridgeStart", "Conference: %s\r\n", conf_name);
-}
-
-static void send_conf_end_event(const char *conf_name)
-{
-	/*** DOCUMENTATION
-		<managerEventInstance>
-			<synopsis>Raised when a conference ends.</synopsis>
-			<syntax>
-				<xi:include xpointer="xpointer(/docs/managerEvent[@name='ConfbridgeStart']/managerEventInstance/syntax/parameter[@name='Conference'])" />
-			</syntax>
-			<see-also>
-				<ref type="managerEvent">ConfbridgeStart</ref>
-			</see-also>
-		</managerEventInstance>
-	***/
-	manager_event(EVENT_FLAG_CALL, "ConfbridgeEnd", "Conference: %s\r\n", conf_name);
-}
-
-static void send_join_event(struct ast_channel *chan, const char *conf_name)
-{
-	/*** DOCUMENTATION
-		<managerEventInstance>
-			<synopsis>Raised when a channel joins a Confbridge conference.</synopsis>
-			<syntax>
-				<xi:include xpointer="xpointer(/docs/managerEvent[@name='ConfbridgeStart']/managerEventInstance/syntax/parameter[@name='Conference'])" />
-			</syntax>
-			<see-also>
-				<ref type="managerEvent">ConfbridgeLeave</ref>
-				<ref type="application">ConfBridge</ref>
-			</see-also>
-		</managerEventInstance>
-	***/
-	ast_manager_event(chan, EVENT_FLAG_CALL, "ConfbridgeJoin",
-		"Channel: %s\r\n"
-		"Uniqueid: %s\r\n"
-		"Conference: %s\r\n"
-		"CallerIDnum: %s\r\n"
-		"CallerIDname: %s\r\n",
-		ast_channel_name(chan),
-		ast_channel_uniqueid(chan),
-		conf_name,
-		S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, "<unknown>"),
-		S_COR(ast_channel_caller(chan)->id.name.valid, ast_channel_caller(chan)->id.name.str, "<unknown>")
-	);
-}
-
-static void send_leave_event(struct ast_channel *chan, const char *conf_name)
-{
-	/*** DOCUMENTATION
-		<managerEventInstance>
-			<synopsis>Raised when a channel leaves a Confbridge conference.</synopsis>
-			<syntax>
-				<xi:include xpointer="xpointer(/docs/managerEvent[@name='ConfbridgeStart']/managerEventInstance/syntax/parameter[@name='Conference'])" />
-			</syntax>
-			<see-also>
-				<ref type="managerEvent">ConfbridgeJoin</ref>
-			</see-also>
-		</managerEventInstance>
-	***/
-	ast_manager_event(chan, EVENT_FLAG_CALL, "ConfbridgeLeave",
-		"Channel: %s\r\n"
-		"Uniqueid: %s\r\n"
-		"Conference: %s\r\n"
-		"CallerIDnum: %s\r\n"
-		"CallerIDname: %s\r\n",
-		ast_channel_name(chan),
-		ast_channel_uniqueid(chan),
-		conf_name,
-		S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, "<unknown>"),
-		S_COR(ast_channel_caller(chan)->id.name.valid, ast_channel_caller(chan)->id.name.str, "<unknown>")
-	);
-}
-
-static void send_start_record_event(const char *conf_name)
-{
-	/*** DOCUMENTATION
-		<managerEventInstance>
-			<synopsis>Raised when a conference recording starts.</synopsis>
-			<syntax>
-				<xi:include xpointer="xpointer(/docs/managerEvent[@name='ConfbridgeStart']/managerEventInstance/syntax/parameter[@name='Conference'])" />
-			</syntax>
-			<see-also>
-				<ref type="managerEvent">ConfbridgeStopRecord</ref>
-				<ref type="application">ConfBridge</ref>
-			</see-also>
-		</managerEventInstance>
-	***/
-
-	manager_event(EVENT_FLAG_CALL, "ConfbridgeStartRecord", "Conference: %s\r\n", conf_name);
-}
-
-static void send_stop_record_event(const char *conf_name)
-{
-	/*** DOCUMENTATION
-		<managerEventInstance>
-			<synopsis>Raised when a conference recording stops.</synopsis>
-			<syntax>
-				<xi:include xpointer="xpointer(/docs/managerEvent[@name='ConfbridgeStart']/managerEventInstance/syntax/parameter[@name='Conference'])" />
-			</syntax>
-			<see-also>
-				<ref type="managerEvent">ConfbridgeStartRecord</ref>
-			</see-also>
-		</managerEventInstance>
-	***/
-	manager_event(EVENT_FLAG_CALL, "ConfbridgeStopRecord", "Conference: %s\r\n", conf_name);
-}
-
-static void send_mute_event(struct ast_channel *chan, const char *conf_name)
-{
-	/*** DOCUMENTATION
-		<managerEventInstance>
-			<synopsis>Raised when a Confbridge participant mutes.</synopsis>
-			<syntax>
-				<xi:include xpointer="xpointer(/docs/managerEvent[@name='ConfbridgeStart']/managerEventInstance/syntax/parameter[@name='Conference'])" />
-			</syntax>
-			<see-also>
-				<ref type="managerEvent">ConfbridgeUnmute</ref>
-				<ref type="application">ConfBridge</ref>
-			</see-also>
-		</managerEventInstance>
-	***/
-	ast_manager_event(chan, EVENT_FLAG_CALL, "ConfbridgeMute",
-		"Channel: %s\r\n"
-		"Uniqueid: %s\r\n"
-		"Conference: %s\r\n"
-		"CallerIDnum: %s\r\n"
-		"CallerIDname: %s\r\n",
-		ast_channel_name(chan),
-		ast_channel_uniqueid(chan),
-		conf_name,
-		S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, "<unknown>"),
-		S_COR(ast_channel_caller(chan)->id.name.valid, ast_channel_caller(chan)->id.name.str, "<unknown>")
-	);
-}
-
-static void send_unmute_event(struct ast_channel *chan, const char *conf_name)
-{
-	/*** DOCUMENTATION
-		<managerEventInstance>
-			<synopsis>Raised when a Confbridge participant unmutes.</synopsis>
-			<syntax>
-				<xi:include xpointer="xpointer(/docs/managerEvent[@name='ConfbridgeStart']/managerEventInstance/syntax/parameter[@name='Conference'])" />
-			</syntax>
-			<see-also>
-				<ref type="managerEvent">ConfbridgeMute</ref>
-			</see-also>
-		</managerEventInstance>
-	***/
-	ast_manager_event(chan, EVENT_FLAG_CALL, "ConfbridgeUnmute",
-		"Channel: %s\r\n"
-		"Uniqueid: %s\r\n"
-		"Conference: %s\r\n"
-		"CallerIDnum: %s\r\n"
-		"CallerIDname: %s\r\n",
-		ast_channel_name(chan),
-		ast_channel_uniqueid(chan),
-		conf_name,
-		S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, "<unknown>"),
-		S_COR(ast_channel_caller(chan)->id.name.valid, ast_channel_caller(chan)->id.name.str, "<unknown>")
-	);
+static void send_conf_stasis(struct confbridge_conference *conference, struct ast_channel *chan, const char *type, struct ast_json *extras, int channel_topic)
+{
+	RAII_VAR(struct stasis_message *, msg, NULL, ao2_cleanup);
+	RAII_VAR(struct ast_json *, json_object, NULL, ast_json_unref);
+
+	json_object = ast_json_pack("{s: s, s: s}",
+		"type", type,
+		"conference", conference->name);
+
+	if (!json_object) {
+		return;
+	}
+
+	if (extras) {
+		ast_json_object_update(json_object, extras);
+	}
+
+	msg = ast_bridge_blob_create(confbridge_message_type(),
+					 conference->bridge,
+					 chan,
+					 json_object);
+	if (!msg) {
+		return;
+	}
+
+	if (channel_topic) {
+		stasis_publish(ast_channel_topic(chan), msg);
+	} else {
+		stasis_publish(ast_bridge_topic(conference->bridge), msg);
+	}
+
+}
+
+static void send_conf_start_event(struct confbridge_conference *conference)
+{
+	send_conf_stasis(conference, NULL, "confbridge_start", NULL, 0);
+}
+
+static void send_conf_end_event(struct confbridge_conference *conference)
+{
+	send_conf_stasis(conference, NULL, "confbridge_end", NULL, 0);
+}
+
+static void send_join_event(struct ast_channel *chan, struct confbridge_conference *conference)
+{
+	send_conf_stasis(conference, chan, "confbridge_join", NULL, 0);
+}
+
+static void send_leave_event(struct ast_channel *chan, struct confbridge_conference *conference)
+{
+	send_conf_stasis(conference, chan, "confbridge_leave", NULL, 0);
+}
+
+static void send_start_record_event(struct confbridge_conference *conference)
+{
+	send_conf_stasis(conference, NULL, "confbridge_record", NULL, 0);
+}
+
+static void send_stop_record_event(struct confbridge_conference *conference)
+{
+	send_conf_stasis(conference, NULL, "confbridge_stop_record", NULL, 0);
+}
+
+static void send_mute_event(struct ast_channel *chan, struct confbridge_conference *conference)
+{
+	send_conf_stasis(conference, chan, "confbridge_mute", NULL, 1);
+}
+
+static void send_unmute_event(struct ast_channel *chan, struct confbridge_conference *conference)
+{
+	send_conf_stasis(conference, chan, "confbridge_unmute", NULL, 1);
 }
 
 
@@ -747,7 +644,7 @@
 	ast_queue_frame(chan, &ast_null_frame);
 	chan = ast_channel_unref(chan);
 	ast_test_suite_event_notify("CONF_STOP_RECORD", "Message: stopped conference recording channel\r\nConference: %s", conference->b_profile.name);
-	send_stop_record_event(conference->name);
+	send_stop_record_event(conference);
 
 	return 0;
 }
@@ -821,7 +718,7 @@
 	ast_cond_signal(&conference->record_cond);
 	ast_mutex_unlock(&conference->record_lock);
 	ast_test_suite_event_notify("CONF_START_RECORD", "Message: started conference recording channel\r\nConference: %s", conference->b_profile.name);
-	send_start_record_event(conference->name);
+	send_start_record_event(conference);
 
 	return 0;
 }
@@ -1260,7 +1157,7 @@
 {
 	/* Called with a reference to conference */
 	ao2_unlink(conference_bridges, conference);
-	send_conf_end_event(conference->name);
+	send_conf_end_event(conference);
 	conf_stop_record_thread(conference);
 }
 
@@ -1361,7 +1258,7 @@
 			ao2_unlock(conference);
 		}
 
-		send_conf_start_event(conference->name);
+		send_conf_start_event(conference);
 		ast_debug(1, "Created conference '%s' and linked to container.\n", conference_name);
 	}
 
@@ -1563,31 +1460,22 @@
 static void conf_handle_talker_cb(struct ast_bridge_channel *bridge_channel, void *pvt_data, int talking)
 {
 	const char *conf_name = pvt_data;
-
-	/* notify AMI someone is has either started or stopped talking */
-	/*** DOCUMENTATION
-		<managerEventInstance>
-			<synopsis>Raised when a conference participant has started or stopped talking.</synopsis>
-			<syntax>
-				<xi:include xpointer="xpointer(/docs/managerEvent[@name='ConfbridgeStart']/managerEventInstance/syntax/parameter[@name='Conference'])" />
-				<parameter name="TalkingStatus">
-					<enumlist>
-						<enum name="on"/>
-						<enum name="off"/>
-					</enumlist>
-				</parameter>
-			</syntax>
-		</managerEventInstance>
-	***/
-	ast_manager_event(bridge_channel->chan, EVENT_FLAG_CALL, "ConfbridgeTalking",
-		"Channel: %s\r\n"
-		"Uniqueid: %s\r\n"
-		"Conference: %s\r\n"
-		"TalkingStatus: %s\r\n",
-		ast_channel_name(bridge_channel->chan),
-		ast_channel_uniqueid(bridge_channel->chan),
-		conf_name,
-		talking ? "on" : "off");
+	struct confbridge_conference *conference = ao2_find(conference_bridges, conf_name, OBJ_KEY);
+	struct ast_json *talking_extras;
+
+	if (!conference) {
+		return;
+	}
+
+	talking_extras = ast_json_pack("{s: s}",
+					 "talking_status", talking ? "on" : "off");
+
+	if (!talking_extras) {
+		return;
+	}
+
+	send_conf_stasis(conference, bridge_channel->chan, "confbridge_talking", talking_extras, 0);
+	ast_json_unref(talking_extras);
 }
 
 static int conf_get_pin(struct ast_channel *chan, struct confbridge_user *user)
@@ -1837,14 +1725,14 @@
 	conf_moh_unsuspend(&user);
 
 	/* Join our conference bridge for real */
-	send_join_event(user.chan, conference->name);
+	send_join_event(user.chan, conference);
 	ast_bridge_join(conference->bridge,
 		chan,
 		NULL,
 		&user.features,
 		&user.tech_args,
 		0);
-	send_leave_event(user.chan, conference->name);
+	send_leave_event(user.chan, conference);
 
 	/* if we're shutting down, don't attempt to do further processing */
 	if (ast_shutting_down()) {
@@ -1911,9 +1799,9 @@
 		user->features.mute = (!user->features.mute ? 1 : 0);
 		ast_test_suite_event_notify("CONF_MUTE", "Message: participant %s %s\r\nConference: %s\r\nChannel: %s", ast_channel_name(chan), user->features.mute ? "muted" : "unmuted", user->b_profile.name, ast_channel_name(chan));
 		if (user->features.mute) {
-			send_mute_event(chan, conference->name);
-		} else { 
-			send_unmute_event(chan, conference->name);
+			send_mute_event(chan, conference);
+		} else {
+			send_unmute_event(chan, conference);
 		}
 	}
 	return ast_stream_and_wait(chan, (user->features.mute ?
@@ -3234,6 +3122,9 @@
 	ast_manager_unregister("ConfbridgeStopRecord");
 	ast_manager_unregister("ConfbridgeSetSingleVideoSrc");
 
+	/* Unsubscribe from stasis confbridge message type and clean it up. */
+	manager_confbridge_shutdown();
+
 	/* Get rid of the conference bridges container. Since we only allow dynamic ones none will be active. */
 	ao2_cleanup(conference_bridges);
 	conference_bridges = NULL;
@@ -3283,6 +3174,9 @@
 		unload_module();
 		return AST_MODULE_LOAD_FAILURE;
 	}
+
+	/* Setup manager stasis subscriptions */
+	res |= manager_confbridge_init();
 
 	res |= ast_register_application_xml(app, confbridge_exec);
 

Added: team/group/bridge_construction/apps/confbridge/confbridge_manager.c
URL: http://svnview.digium.com/svn/asterisk/team/group/bridge_construction/apps/confbridge/confbridge_manager.c?view=auto&rev=388929
==============================================================================
--- team/group/bridge_construction/apps/confbridge/confbridge_manager.c (added)
+++ team/group/bridge_construction/apps/confbridge/confbridge_manager.c Thu May 16 11:58:25 2013
@@ -1,0 +1,339 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * Copyright (C) 2013, Digium, Inc.
+ *
+ * Jonathan Rose <jrose at digium.com>
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ */
+
+/*! \file
+ *
+ * \brief Confbridge manager events for stasis messages
+ *
+ * \author Jonathan Rose <jrose at digium.com>
+ */
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
+#include "asterisk/channel.h"
+#include "asterisk/bridging.h"
+#include "asterisk/stasis.h"
+#include "asterisk/stasis_channels.h"
+#include "asterisk/stasis_bridging.h"
+#include "asterisk/manager.h"
+#include "asterisk/stasis_message_router.h"
+#include "include/confbridge.h"
+
+/*** DOCUMENTATION
+	<managerEvent language="en_US" name="ConfbridgeStart">
+		<managerEventInstance class="EVENT_FLAG_CALL">
+			<synopsis>Raised when a conference starts.</synopsis>
+			<syntax>
+				<parameter name="Conference">
+					<para>The name of the Confbridge conference.</para>
+				</parameter>
+				<xi:include xpointer="xpointer(/docs/managerEvent[@name='BridgeCreate']/managerEventInstance/syntax/parameter)" />
+			</syntax>
+			<see-also>
+				<ref type="managerEvent">ConfbridgeEnd</ref>
+				<ref type="application">ConfBridge</ref>
+			</see-also>
+		</managerEventInstance>
+	</managerEvent>
+	<managerEvent language="en_US" name="ConfbridgeEnd">
+		<managerEventInstance class="EVENT_FLAG_CALL">
+			<synopsis>Raised when a conference ends.</synopsis>
+			<syntax>
+				<parameter name="Conference">
+					<para>The name of the Confbridge conference.</para>
+				</parameter>
+				<xi:include xpointer="xpointer(/docs/managerEvent[@name='BridgeCreate']/managerEventInstance/syntax/parameter)" />
+			</syntax>
+			<see-also>
+				<ref type="managerEvent">ConfbridgeStart</ref>
+				<ref type="application">ConfBridge</ref>
+			</see-also>
+		</managerEventInstance>
+	</managerEvent>
+	<managerEvent language="en_US" name="ConfbridgeJoin">
+		<managerEventInstance class="EVENT_FLAG_CALL">
+			<synopsis>Raised when a channel joins a Confbridge conference.</synopsis>
+			<syntax>
+				<parameter name="Conference">
+					<para>The name of the Confbridge conference.</para>
+				</parameter>
+				<xi:include xpointer="xpointer(/docs/managerEvent[@name='BridgeCreate']/managerEventInstance/syntax/parameter)" />
+				<xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" />
+			</syntax>
+			<see-also>
+				<ref type="managerEvent">ConfbridgeLeave</ref>
+				<ref type="application">ConfBridge</ref>
+			</see-also>
+		</managerEventInstance>
+	</managerEvent>
+	<managerEvent language="en_US" name="ConfbridgeLeave">
+		<managerEventInstance class="EVENT_FLAG_CALL">
+			<synopsis>Raised when a channel leaves a Confbridge conference.</synopsis>
+			<syntax>
+				<parameter name="Conference">
+					<para>The name of the Confbridge conference.</para>
+				</parameter>
+				<xi:include xpointer="xpointer(/docs/managerEvent[@name='BridgeCreate']/managerEventInstance/syntax/parameter)" />
+				<xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" />
+			</syntax>
+			<see-also>
+				<ref type="managerEvent">ConfbridgeJoin</ref>
+				<ref type="application">ConfBridge</ref>
+			</see-also>
+		</managerEventInstance>
+	</managerEvent>
+	<managerEvent language="en_US" name="ConfbridgeRecord">
+		<managerEventInstance class="EVENT_FLAG_CALL">
+			<synopsis>Raised when a conference starts recording.</synopsis>
+			<syntax>
+				<parameter name="Conference">
+					<para>The name of the Confbridge conference.</para>
+				</parameter>
+				<xi:include xpointer="xpointer(/docs/managerEvent[@name='BridgeCreate']/managerEventInstance/syntax/parameter)" />
+			</syntax>
+			<see-also>
+				<ref type="managerEvent">ConfbridgeStopRecord</ref>
+				<ref type="application">ConfBridge</ref>
+			</see-also>
+		</managerEventInstance>
+	</managerEvent>
+	<managerEvent language="en_US" name="ConfbridgeStopRecord">
+		<managerEventInstance class="EVENT_FLAG_CALL">
+			<synopsis>Raised when a conference that was recording stops recording.</synopsis>
+			<syntax>
+				<parameter name="Conference">
+					<para>The name of the Confbridge conference.</para>
+				</parameter>
+				<xi:include xpointer="xpointer(/docs/managerEvent[@name='BridgeCreate']/managerEventInstance/syntax/parameter)" />
+			</syntax>
+			<see-also>
+				<ref type="managerEvent">ConfbridgeRecord</ref>
+				<ref type="application">ConfBridge</ref>
+			</see-also>
+		</managerEventInstance>
+	</managerEvent>
+	<managerEvent language="en_US" name="ConfbridgeMute">
+		<managerEventInstance class="EVENT_FLAG_CALL">
+			<synopsis>Raised when a Confbridge participant mutes.</synopsis>
+			<syntax>
+				<parameter name="Conference">
+					<para>The name of the Confbridge conference.</para>
+				</parameter>
+				<xi:include xpointer="xpointer(/docs/managerEvent[@name='BridgeCreate']/managerEventInstance/syntax/parameter)" />
+				<xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" />
+			</syntax>
+			<see-also>
+				<ref type="managerEvent">ConfbridgeUnmute</ref>
+				<ref type="application">ConfBridge</ref>
+			</see-also>
+		</managerEventInstance>
+	</managerEvent>
+	<managerEvent language="en_US" name="ConfbridgeUnmute">
+		<managerEventInstance class="EVENT_FLAG_CALL">
+			<synopsis>Raised when a confbridge participant unmutes.</synopsis>
+			<syntax>
+				<parameter name="Conference">
+					<para>The name of the Confbridge conference.</para>
+				</parameter>
+				<xi:include xpointer="xpointer(/docs/managerEvent[@name='BridgeCreate']/managerEventInstance/syntax/parameter)" />
+				<xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" />
+			</syntax>
+			<see-also>
+				<ref type="managerEvent">ConfbridgeMute</ref>
+				<ref type="application">ConfBridge</ref>
+			</see-also>
+		</managerEventInstance>
+	</managerEvent>
+
+	<managerEvent language="en_US" name="ConfbridgeTalking">
+		<managerEventInstance class="EVENT_FLAG_CALL">
+			<synopsis>Raised when a confbridge participant unmutes.</synopsis>
+			<syntax>
+				<parameter name="Conference">
+					<para>The name of the Confbridge conference.</para>
+				</parameter>
+				<xi:include xpointer="xpointer(/docs/managerEvent[@name='BridgeCreate']/managerEventInstance/syntax/parameter)" />
+				<xi:include xpointer="xpointer(/docs/managerEvent[@name='Newchannel']/managerEventInstance/syntax/parameter)" />
+				<parameter name="TalkingStatus">
+					<enumlist>
+						<enum name="on"/>
+						<enum name="off"/>
+					</enumlist>
+				</parameter>
+			</syntax>
+			<see-also>
+				<ref type="application">ConfBridge</ref>
+			</see-also>
+		</managerEventInstance>
+	</managerEvent>
+***/
+
+static struct stasis_message_router *bridge_state_router;
+static struct stasis_message_router *channel_state_router;
+
+static void append_event_header(struct ast_str **fields_string,
+					const char *header, const char *value)
+{
+	struct ast_str *working_str = *fields_string;
+
+	if (!working_str) {
+		working_str = ast_str_create(128);
+		if (!working_str) {
+			return;
+		}
+		*fields_string = working_str;
+	}
+
+	ast_str_append(&working_str, 0,
+		"%s: %s\r\n",
+		header, value);
+}
+
+static void stasis_confbridge_cb(void *data, struct stasis_subscription *sub,
+					struct stasis_topic *topic,
+					struct stasis_message *message)
+{
+	struct ast_bridge_blob *blob = stasis_message_data(message);
+	const char *type = ast_bridge_blob_json_type(blob);
+	const char *conference_name;
+	RAII_VAR(struct ast_str *, bridge_text, NULL, ast_free);
+	RAII_VAR(struct ast_str *, channel_text, NULL, ast_free);
+	RAII_VAR(struct ast_str *, extra_text, NULL, ast_free);
+	char *event;
+
+	if (!blob || !type) {
+		ast_assert(0);
+		return;
+	}
+
+	if (!strcmp("confbridge_start", type)) {
+		event = "ConfbridgeStart";
+	} else if (!strcmp("confbridge_end", type)) {
+		event = "ConfbridgeEnd";
+	} else if (!strcmp("confbridge_leave", type)) {
+		event = "ConfbridgeLeave";
+	} else if (!strcmp("confbridge_join", type)) {
+		event = "ConfbridgeJoin";
+	} else if (!strcmp("confbridge_record", type)) {
+		event = "ConfbridgeRecord";
+	} else if (!strcmp("confbridge_stop_record", type)) {
+		event = "ConfbridgeStopRecord";
+	} else if (!strcmp("confbridge_mute", type)) {
+		event = "ConfbridgeMute";
+	} else if (!strcmp("confbridge_unmute", type)) {
+		event = "ConfbridgeUnmute";
+	} else if (!strcmp("confbridge_talking", type)) {
+		const char *talking_status = ast_json_string_get(ast_json_object_get(blob->blob, "talking_status"));
+		event = "ConfbridgeTalking";
+
+		if (!talking_status) {
+			return;
+		}
+
+		append_event_header(&extra_text, "TalkingStatus", talking_status);
+
+	} else {
+		return;
+	}
+
+	conference_name = ast_json_string_get(ast_json_object_get(blob->blob, "conference"));
+
+	if (!conference_name) {
+		ast_assert(0);
+		return;
+	}
+
+	bridge_text = ast_manager_build_bridge_state_string(blob->bridge, "");
+	if (blob->channel) {
+		channel_text = ast_manager_build_channel_state_string(blob->channel);
+	}
+
+	manager_event(EVENT_FLAG_CALL, event,
+		"Conference: %s\r\n"
+		"%s"
+		"%s"
+		"%s",
+		conference_name,
+		ast_str_buffer(bridge_text),
+		channel_text ? ast_str_buffer(channel_text) : "",
+		extra_text ? ast_str_buffer(extra_text) : "");
+}
+
+static struct stasis_message_type *confbridge_msg_type;
+
+struct stasis_message_type *confbridge_message_type(void)
+{
+	return confbridge_msg_type;
+}
+
+void manager_confbridge_shutdown(void) {
+	ao2_cleanup(confbridge_msg_type);
+	confbridge_msg_type = NULL;
+
+	if (bridge_state_router) {
+		stasis_message_router_unsubscribe(bridge_state_router);
+		bridge_state_router = NULL;
+	}
+
+	if (channel_state_router) {
+		stasis_message_router_unsubscribe(channel_state_router);
+		channel_state_router = NULL;
+	}
+}
+
+int manager_confbridge_init(void)
+{
+	if (!(confbridge_msg_type = stasis_message_type_create("confbridge"))) {
+		return -1;
+	}
+
+	bridge_state_router = stasis_message_router_create(
+		stasis_caching_get_topic(ast_bridge_topic_all_cached()));
+
+	if (!bridge_state_router) {
+		return -1;
+	}
+
+	if (stasis_message_router_add(bridge_state_router,
+					 confbridge_message_type(),
+					 stasis_confbridge_cb,
+					 NULL)) {
+		manager_confbridge_shutdown();
+		return -1;
+	}
+
+	channel_state_router = stasis_message_router_create(
+		stasis_caching_get_topic(ast_channel_topic_all_cached()));
+
+	if (!channel_state_router) {
+		manager_confbridge_shutdown();
+		return -1;
+	}
+
+	if (stasis_message_router_add(channel_state_router,
+					 confbridge_message_type(),
+					 stasis_confbridge_cb,
+					 NULL)) {
+		manager_confbridge_shutdown();
+		return -1;
+	}
+
+	return 0;
+}

Propchange: team/group/bridge_construction/apps/confbridge/confbridge_manager.c
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: team/group/bridge_construction/apps/confbridge/confbridge_manager.c
------------------------------------------------------------------------------
    svn:keywords = "Author Date Id Rev URL"

Propchange: team/group/bridge_construction/apps/confbridge/confbridge_manager.c
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: team/group/bridge_construction/apps/confbridge/include/confbridge.h
URL: http://svnview.digium.com/svn/asterisk/team/group/bridge_construction/apps/confbridge/include/confbridge.h?view=diff&rev=388929&r1=388928&r2=388929
==============================================================================
--- team/group/bridge_construction/apps/confbridge/include/confbridge.h (original)
+++ team/group/bridge_construction/apps/confbridge/include/confbridge.h Thu May 16 11:58:25 2013
@@ -460,4 +460,28 @@
  * \retval non-zero failure
  */
 int conf_add_post_join_action(struct confbridge_user *user, int (*func)(struct confbridge_user *user));
+
+/*!
+ * \since 12.0
+ * \brief get the confbridge stasis message type
+ *
+ * \retval stasis message type for confbridge messages if it's available
+ * \retval NULL if it isn't
+ */
+struct stasis_message_type *confbridge_message_type(void);
+
+/*!
+ * \since 12.0
+ * \brief register stasis message routers to handle manager events for confbridge messages
+ *
+ * \retval 0 success
+ * \retval non-zero failure
+ */
+int manager_confbridge_init(void);
+
+/*!
+ * \since 12.0
+ * \brief unregister stasis message routers to handle manager events for confbridge messages
+ */
+void manager_confbridge_shutdown(void);
 #endif




More information about the asterisk-commits mailing list