[asterisk-commits] file: branch file/res_xmpp r368711 - in /team/file/res_xmpp: ./ apps/ build_t...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Fri Jun 8 13:29:16 CDT 2012


Author: file
Date: Fri Jun  8 13:29:09 2012
New Revision: 368711

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=368711
Log:
Bring up to date.

Added:
    team/file/res_xmpp/channels/chan_sip.exports.in
      - copied unchanged from r368688, trunk/channels/chan_sip.exports.in
    team/file/res_xmpp/configs/app_skel.conf.sample
      - copied unchanged from r368688, trunk/configs/app_skel.conf.sample
    team/file/res_xmpp/configs/config_test.conf.sample
      - copied unchanged from r368688, trunk/configs/config_test.conf.sample
    team/file/res_xmpp/funcs/func_presencestate.c
      - copied unchanged from r368688, trunk/funcs/func_presencestate.c
    team/file/res_xmpp/include/asterisk/app_voicemail.h
      - copied unchanged from r368688, trunk/include/asterisk/app_voicemail.h
    team/file/res_xmpp/include/asterisk/config_options.h
      - copied unchanged from r368688, trunk/include/asterisk/config_options.h
    team/file/res_xmpp/include/asterisk/http_websocket.h
      - copied unchanged from r368688, trunk/include/asterisk/http_websocket.h
    team/file/res_xmpp/include/asterisk/presencestate.h
      - copied unchanged from r368688, trunk/include/asterisk/presencestate.h
    team/file/res_xmpp/include/asterisk/sip_api.h
      - copied unchanged from r368688, trunk/include/asterisk/sip_api.h
    team/file/res_xmpp/main/config_options.c
      - copied unchanged from r368688, trunk/main/config_options.c
    team/file/res_xmpp/main/presencestate.c
      - copied unchanged from r368688, trunk/main/presencestate.c
    team/file/res_xmpp/res/res_http_websocket.c
      - copied unchanged from r368688, trunk/res/res_http_websocket.c
    team/file/res_xmpp/res/res_http_websocket.exports.in
      - copied unchanged from r368688, trunk/res/res_http_websocket.exports.in
    team/file/res_xmpp/tests/test_voicemail_api.c
      - copied unchanged from r368688, trunk/tests/test_voicemail_api.c
Modified:
    team/file/res_xmpp/   (props changed)
    team/file/res_xmpp/CHANGES
    team/file/res_xmpp/Makefile
    team/file/res_xmpp/UPGRADE.txt
    team/file/res_xmpp/apps/app_dial.c
    team/file/res_xmpp/apps/app_meetme.c
    team/file/res_xmpp/apps/app_mixmonitor.c
    team/file/res_xmpp/apps/app_queue.c
    team/file/res_xmpp/apps/app_skel.c
    team/file/res_xmpp/apps/app_stack.c
    team/file/res_xmpp/apps/app_voicemail.c
    team/file/res_xmpp/apps/app_voicemail.exports.in
    team/file/res_xmpp/build_tools/make_version
    team/file/res_xmpp/channels/chan_agent.c
    team/file/res_xmpp/channels/chan_dahdi.c
    team/file/res_xmpp/channels/chan_iax2.c
    team/file/res_xmpp/channels/chan_local.c
    team/file/res_xmpp/channels/chan_sip.c
    team/file/res_xmpp/channels/chan_skinny.c
    team/file/res_xmpp/channels/chan_unistim.c
    team/file/res_xmpp/channels/sig_analog.c
    team/file/res_xmpp/channels/sig_pri.c
    team/file/res_xmpp/channels/sig_ss7.c
    team/file/res_xmpp/channels/sip/include/sip.h
    team/file/res_xmpp/configs/manager.conf.sample
    team/file/res_xmpp/configs/sip.conf.sample
    team/file/res_xmpp/configure
    team/file/res_xmpp/configure.ac
    team/file/res_xmpp/contrib/editors/asterisk.vim
    team/file/res_xmpp/contrib/realtime/mysql/voicemail_messages.sql
    team/file/res_xmpp/formats/format_ogg_vorbis.c
    team/file/res_xmpp/funcs/func_channel.c
    team/file/res_xmpp/funcs/func_math.c
    team/file/res_xmpp/include/asterisk/app.h
    team/file/res_xmpp/include/asterisk/astobj2.h
    team/file/res_xmpp/include/asterisk/callerid.h
    team/file/res_xmpp/include/asterisk/channel.h
    team/file/res_xmpp/include/asterisk/config.h
    team/file/res_xmpp/include/asterisk/event_defs.h
    team/file/res_xmpp/include/asterisk/file.h
    team/file/res_xmpp/include/asterisk/manager.h
    team/file/res_xmpp/include/asterisk/message.h
    team/file/res_xmpp/include/asterisk/pbx.h
    team/file/res_xmpp/include/asterisk/stringfields.h
    team/file/res_xmpp/include/asterisk/utils.h
    team/file/res_xmpp/main/app.c
    team/file/res_xmpp/main/asterisk.c
    team/file/res_xmpp/main/asterisk.exports.in
    team/file/res_xmpp/main/astobj2.c
    team/file/res_xmpp/main/callerid.c
    team/file/res_xmpp/main/channel.c
    team/file/res_xmpp/main/channel_internal_api.c
    team/file/res_xmpp/main/config.c
    team/file/res_xmpp/main/event.c
    team/file/res_xmpp/main/features.c
    team/file/res_xmpp/main/file.c
    team/file/res_xmpp/main/manager.c
    team/file/res_xmpp/main/message.c
    team/file/res_xmpp/main/pbx.c
    team/file/res_xmpp/main/tcptls.c
    team/file/res_xmpp/main/udptl.c
    team/file/res_xmpp/main/utils.c
    team/file/res_xmpp/makeopts.in
    team/file/res_xmpp/pbx/pbx_config.c
    team/file/res_xmpp/res/ael/pval.c
    team/file/res_xmpp/res/res_config_odbc.c
    team/file/res_xmpp/tests/test_config.c

Propchange: team/file/res_xmpp/
            ('branch-10-merged' removed)

Propchange: team/file/res_xmpp/
------------------------------------------------------------------------------
--- svnmerge-integrated (original)
+++ svnmerge-integrated Fri Jun  8 13:29:09 2012
@@ -1,1 +1,1 @@
-/trunk:1-367834
+/trunk:1-368710

Modified: team/file/res_xmpp/CHANGES
URL: http://svnview.digium.com/svn/asterisk/team/file/res_xmpp/CHANGES?view=diff&rev=368711&r1=368710&r2=368711
==============================================================================
--- team/file/res_xmpp/CHANGES (original)
+++ team/file/res_xmpp/CHANGES Fri Jun  8 13:29:09 2012
@@ -31,6 +31,13 @@
  * The minimum DTMF duration can now be configured in asterisk.conf
    as "mindtmfduration". The default value is (as before) set to 80 ms.
    (previously it was only available in source code)
+ * Each logging destination and console now have an independent notion of the
+   current verbosity level.  Logger.conf now allows an optional argument to
+   the 'verbose' specifier, indicating the level of verbosity sent to that
+   particular logging destination.  Additionally, remote consoles now each
+   have their own verbosity level.  The command 'core set verbose' will now set
+   a separate level for each remote console without affecting any other
+   console.
 
 CLI Changes
 -------------------
@@ -202,16 +209,6 @@
 -------------
  * Allow the built in variables ${NUMBER}, ${IPADDR} and ${SECRET} to be
    used within the dynamic weight attribute when specifying a mapping.
-
-Core changes
-------------
- * Each logging destination and console now have an independent notion of the
-   current verbosity level.  Logger.conf now allows an optional argument to
-   the 'verbose' specifier, indicating the level of verbosity sent to that
-   particular logging destination.  Additionally, remote consoles now each
-   have their own verbosity level.  The command 'core set verbose' will now set
-   a separate level for each remote console without affecting any other
-   console.
 
 Dialplan functions
 ------------------

Modified: team/file/res_xmpp/Makefile
URL: http://svnview.digium.com/svn/asterisk/team/file/res_xmpp/Makefile?view=diff&rev=368711&r1=368710&r2=368711
==============================================================================
--- team/file/res_xmpp/Makefile (original)
+++ team/file/res_xmpp/Makefile Fri Jun  8 13:29:09 2012
@@ -191,6 +191,7 @@
   _ASTCFLAGS+=-Wunused
   _ASTCFLAGS+=$(AST_DECLARATION_AFTER_STATEMENT)
   _ASTCFLAGS+=$(AST_FORTIFY_SOURCE)
+  _ASTCFLAGS+=$(AST_TRAMPOLINES)
   _ASTCFLAGS+=-Wundef
   _ASTCFLAGS+=-Wmissing-format-attribute
   _ASTCFLAGS+=-Wformat=2

Modified: team/file/res_xmpp/UPGRADE.txt
URL: http://svnview.digium.com/svn/asterisk/team/file/res_xmpp/UPGRADE.txt?view=diff&rev=368711&r1=368710&r2=368711
==============================================================================
--- team/file/res_xmpp/UPGRADE.txt (original)
+++ team/file/res_xmpp/UPGRADE.txt Fri Jun  8 13:29:09 2012
@@ -25,6 +25,11 @@
 Parking:
  - The comebacktoorigin setting must now be set per parking lot. The setting in
    the general section will not be applied automatically to each parking lot.
+ - The BLINDTRANSFER channel variable is deleted from a channel when it is
+   bridged to prevent subtle bugs in the parking feature.  The channel
+   variable is used by Asterisk internally for the Park application to work
+   properly.  If you were using it for your own purposes, copy it to your
+   own channel variable before the channel is bridged.
 
 res_ais:
  - Users of res_ais in versions of Asterisk prior to Asterisk 11 must change

Modified: team/file/res_xmpp/apps/app_dial.c
URL: http://svnview.digium.com/svn/asterisk/team/file/res_xmpp/apps/app_dial.c?view=diff&rev=368711&r1=368710&r2=368711
==============================================================================
--- team/file/res_xmpp/apps/app_dial.c (original)
+++ team/file/res_xmpp/apps/app_dial.c Fri Jun  8 13:29:09 2012
@@ -133,8 +133,7 @@
 					<para>Reset the call detail record (CDR) for this call.</para>
 				</option>
 				<option name="c">
-					<para>If the Dial() application cancels this call, always set the flag to tell the channel
-					driver that the call is answered elsewhere.</para>
+					<para>If the Dial() application cancels this call, always set HANGUPCAUSE to 'answered elsewhere'</para>
 				</option>
 				<option name="d">
 					<para>Allow the calling user to dial a 1 digit extension while waiting for
@@ -727,8 +726,6 @@
 		/* Hangup any existing lines we have open */
 		if (outgoing->chan && (outgoing->chan != exception)) {
 			if (answered_elsewhere) {
-				/* The flag is used for local channel inheritance and stuff */
-				ast_set_flag(ast_channel_flags(outgoing->chan), AST_FLAG_ANSWERED_ELSEWHERE);
 				/* This is for the channel drivers */
 				ast_channel_hangupcause_set(outgoing->chan, AST_CAUSE_ANSWERED_ELSEWHERE);
 			}
@@ -2515,12 +2512,12 @@
 		if (outbound_group)
 			ast_app_group_set_channel(tc, outbound_group);
 		/* If the calling channel has the ANSWERED_ELSEWHERE flag set, inherit it. This is to support local channels */
-		if (ast_test_flag(ast_channel_flags(chan), AST_FLAG_ANSWERED_ELSEWHERE))
-			ast_set_flag(ast_channel_flags(tc), AST_FLAG_ANSWERED_ELSEWHERE);
+		if (ast_channel_hangupcause(chan) == AST_CAUSE_ANSWERED_ELSEWHERE)
+			ast_channel_hangupcause_set(tc, AST_CAUSE_ANSWERED_ELSEWHERE);
 
 		/* Check if we're forced by configuration */
 		if (ast_test_flag64(&opts, OPT_CANCEL_ELSEWHERE))
-			 ast_set_flag(ast_channel_flags(tc), AST_FLAG_ANSWERED_ELSEWHERE);
+			 ast_channel_hangupcause_set(tc, AST_CAUSE_ANSWERED_ELSEWHERE);
 
 
 		/* Inherit context and extension */
@@ -3079,11 +3076,11 @@
 	}
 
 	ast_channel_early_bridge(chan, NULL);
-	hanguptree(&out_chans, NULL, 0); /* In this case, there's no answer anywhere */
+	hanguptree(&out_chans, NULL, ast_channel_hangupcause(chan)==AST_CAUSE_ANSWERED_ELSEWHERE ? 1 : 0 ); /* forward 'answered elsewhere' if we received it */
 	pbx_builtin_setvar_helper(chan, "DIALSTATUS", pa.status);
 	senddialendevent(chan, pa.status);
 	ast_debug(1, "Exiting with DIALSTATUS=%s.\n", pa.status);
-	
+
 	if ((ast_test_flag64(peerflags, OPT_GO_ON)) && !ast_check_hangup(chan) && (res != AST_PBX_INCOMPLETE)) {
 		if (!ast_tvzero(calldurationlimit))
 			memset(ast_channel_whentohangup(chan), 0, sizeof(*ast_channel_whentohangup(chan)));

Modified: team/file/res_xmpp/apps/app_meetme.c
URL: http://svnview.digium.com/svn/asterisk/team/file/res_xmpp/apps/app_meetme.c?view=diff&rev=368711&r1=368710&r2=368711
==============================================================================
--- team/file/res_xmpp/apps/app_meetme.c (original)
+++ team/file/res_xmpp/apps/app_meetme.c Fri Jun  8 13:29:09 2012
@@ -2180,12 +2180,12 @@
 static void send_talking_event(struct ast_channel *chan, struct ast_conference *conf, struct ast_conf_user *user, int talking)
 {
 	ast_manager_event(chan, EVENT_FLAG_CALL, "MeetmeTalking",
-	      "Channel: %s\r\n"
-	      "Uniqueid: %s\r\n"
-	      "Meetme: %s\r\n"
-	      "Usernum: %d\r\n"
-	      "Status: %s\r\n",
-	      ast_channel_name(chan), ast_channel_uniqueid(chan), conf->confno, user->user_no, talking ? "on" : "off");
+		"Channel: %s\r\n"
+		"Uniqueid: %s\r\n"
+		"Meetme: %s\r\n"
+		"Usernum: %d\r\n"
+		"Status: %s\r\n",
+		ast_channel_name(chan), ast_channel_uniqueid(chan), conf->confno, user->user_no, talking ? "on" : "off");
 }
 
 static void set_user_talking(struct ast_channel *chan, struct ast_conference *conf, struct ast_conf_user *user, int talking, int monitor)
@@ -3144,12 +3144,12 @@
 				}
 
 				ast_manager_event(chan, EVENT_FLAG_CALL, "MeetmeMute",
-						"Channel: %s\r\n"
-						"Uniqueid: %s\r\n"
-						"Meetme: %s\r\n"
-						"Usernum: %i\r\n"
-						"Status: on\r\n",
-						ast_channel_name(chan), ast_channel_uniqueid(chan), conf->confno, user->user_no);
+					"Channel: %s\r\n"
+					"Uniqueid: %s\r\n"
+					"Meetme: %s\r\n"
+					"Usernum: %d\r\n"
+					"Status: on\r\n",
+					ast_channel_name(chan), ast_channel_uniqueid(chan), conf->confno, user->user_no);
 			}
 
 			/* If I should be un-muted but am not talker, un-mute me */
@@ -3162,12 +3162,12 @@
 				}
 
 				ast_manager_event(chan, EVENT_FLAG_CALL, "MeetmeMute",
-						"Channel: %s\r\n"
-						"Uniqueid: %s\r\n"
-						"Meetme: %s\r\n"
-						"Usernum: %i\r\n"
-						"Status: off\r\n",
-						ast_channel_name(chan), ast_channel_uniqueid(chan), conf->confno, user->user_no);
+					"Channel: %s\r\n"
+					"Uniqueid: %s\r\n"
+					"Meetme: %s\r\n"
+					"Usernum: %d\r\n"
+					"Status: off\r\n",
+					ast_channel_name(chan), ast_channel_uniqueid(chan), conf->confno, user->user_no);
 			}
 			
 			if ((user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED)) && 
@@ -3175,12 +3175,12 @@
 				talkreq_manager = 1;
 
 				ast_manager_event(chan, EVENT_FLAG_CALL, "MeetmeTalkRequest",
-					      "Channel: %s\r\n"
-							      "Uniqueid: %s\r\n"
-							      "Meetme: %s\r\n"
-							      "Usernum: %i\r\n"
-							      "Status: on\r\n",
-							      ast_channel_name(chan), ast_channel_uniqueid(chan), conf->confno, user->user_no);
+					"Channel: %s\r\n"
+					"Uniqueid: %s\r\n"
+					"Meetme: %s\r\n"
+					"Usernum: %d\r\n"
+					"Status: on\r\n",
+					ast_channel_name(chan), ast_channel_uniqueid(chan), conf->confno, user->user_no);
 			}
 
 			
@@ -3188,12 +3188,12 @@
 				!(user->adminflags & ADMINFLAG_T_REQUEST) && (talkreq_manager)) {
 				talkreq_manager = 0;
 				ast_manager_event(chan, EVENT_FLAG_CALL, "MeetmeTalkRequest",
-					      "Channel: %s\r\n"
-							      "Uniqueid: %s\r\n"
-							      "Meetme: %s\r\n"
-							      "Usernum: %i\r\n"
-							      "Status: off\r\n",
-							     ast_channel_name(chan), ast_channel_uniqueid(chan), conf->confno, user->user_no);
+					"Channel: %s\r\n"
+					"Uniqueid: %s\r\n"
+					"Meetme: %s\r\n"
+					"Usernum: %d\r\n"
+					"Status: off\r\n",
+					ast_channel_name(chan), ast_channel_uniqueid(chan), conf->confno, user->user_no);
 			}
 
 			/* If user have been hung up, exit the conference */
@@ -4578,9 +4578,8 @@
 {
 	struct ast_conf_user *user = NULL;
 	int cid;
-	
-	sscanf(callerident, "%30i", &cid);
-	if (conf && callerident) {
+
+	if (conf && callerident && sscanf(callerident, "%30d", &cid) == 1) {
 		user = ao2_find(conf->usercontainer, &cid, 0);
 		/* reference decremented later in admin_exec */
 		return user;

Modified: team/file/res_xmpp/apps/app_mixmonitor.c
URL: http://svnview.digium.com/svn/asterisk/team/file/res_xmpp/apps/app_mixmonitor.c?view=diff&rev=368711&r1=368710&r2=368711
==============================================================================
--- team/file/res_xmpp/apps/app_mixmonitor.c (original)
+++ team/file/res_xmpp/apps/app_mixmonitor.c Fri Jun  8 13:29:09 2012
@@ -42,6 +42,7 @@
 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 
 #include "asterisk/paths.h"	/* use ast_config_AST_MONITOR_DIR */
+#include "asterisk/stringfields.h"
 #include "asterisk/file.h"
 #include "asterisk/audiohook.h"
 #include "asterisk/pbx.h"
@@ -51,6 +52,7 @@
 #include "asterisk/channel.h"
 #include "asterisk/autochan.h"
 #include "asterisk/manager.h"
+#include "asterisk/callerid.h"
 #include "asterisk/mod_format.h"
 #include "asterisk/linkedlists.h"
 
@@ -111,6 +113,12 @@
 					<option name="i">
 						<argument name="chanvar" required="true" />
 						<para>Stores the MixMonitor's ID on this channel variable.</para>
+					</option>
+					<option name="m">
+						<argument name="mailbox" required="true" />
+						<para>Create a copy of the recording as a voicemail in the indicated <emphasis>mailbox</emphasis>(es)
+						separated by commas eg. m(1111 at default,2222 at default,...).  Folders can be optionally specified using
+						the syntax: mailbox at context/folder</para>
 					</option>
 				</optionlist>
 			</parameter>
@@ -238,6 +246,17 @@
 
 static const char * const mixmonitor_spy_type = "MixMonitor";
 
+/*!
+ * \internal
+ * \brief This struct is a list item holds data needed to find a vm_recipient within voicemail
+ */
+struct vm_recipient {
+	char mailbox[AST_MAX_CONTEXT];
+	char context[AST_MAX_EXTENSION];
+	char folder[80];
+	AST_LIST_ENTRY(vm_recipient) list;
+};
+
 struct mixmonitor {
 	struct ast_audiohook audiohook;
 	struct ast_callid *callid;
@@ -249,6 +268,20 @@
 	unsigned int flags;
 	struct ast_autochan *autochan;
 	struct mixmonitor_ds *mixmonitor_ds;
+
+	/* the below string fields describe data used for creating voicemails from the recording */
+	AST_DECLARE_STRING_FIELDS(
+		AST_STRING_FIELD(call_context);
+		AST_STRING_FIELD(call_macrocontext);
+		AST_STRING_FIELD(call_extension);
+		AST_STRING_FIELD(call_callerchan);
+		AST_STRING_FIELD(call_callerid);
+	);
+	int call_priority;
+
+	/* FUTURE DEVELOPMENT NOTICE
+	 * recipient_list will need locks if we make it editable after the monitor is started */
+	AST_LIST_HEAD_NOLOCK(, vm_recipient) recipient_list;
 };
 
 enum mixmonitor_flags {
@@ -260,7 +293,8 @@
 	MUXFLAG_READ = (1 << 6),
 	MUXFLAG_WRITE = (1 << 7),
 	MUXFLAG_COMBINED = (1 << 8),
-        MUXFLAG_UID = (1 << 9),
+	MUXFLAG_UID = (1 << 9),
+	MUXFLAG_VMRECIPIENTS = (1 << 10),
 };
 
 enum mixmonitor_args {
@@ -269,7 +303,8 @@
 	OPT_ARG_VOLUME,
 	OPT_ARG_WRITENAME,
 	OPT_ARG_READNAME,
-        OPT_ARG_UID,
+	OPT_ARG_UID,
+	OPT_ARG_VMRECIPIENTS,
 	OPT_ARG_ARRAY_SIZE,	/* Always last element of the enum */
 };
 
@@ -282,6 +317,7 @@
 	AST_APP_OPTION_ARG('r', MUXFLAG_READ, OPT_ARG_READNAME),
 	AST_APP_OPTION_ARG('t', MUXFLAG_WRITE, OPT_ARG_WRITENAME),
 	AST_APP_OPTION_ARG('i', MUXFLAG_UID, OPT_ARG_UID),
+	AST_APP_OPTION_ARG('m', MUXFLAG_VMRECIPIENTS, OPT_ARG_VMRECIPIENTS),
 });
 
 struct mixmonitor_ds {
@@ -380,6 +416,70 @@
 		ast_softhangup(peer, AST_SOFTHANGUP_UNBRIDGE);	
 
 	return res;
+}
+
+/*!
+ * \internal
+ * \brief adds recipients to a mixmonitor's recipient list
+ * \param mixmonitor mixmonitor being affected
+ * \param vm_recipients string containing the desired recipients to add
+ */
+static void add_vm_recipients_from_string(struct mixmonitor *mixmonitor, const char *vm_recipients)
+{
+	/* recipients are in a single string with a format format resembling "mailbox at context/INBOX,mailbox2 at context2,mailbox3 at context3/Work" */
+	char *cur_mailbox = ast_strdupa(vm_recipients);
+	char *cur_context;
+	char *cur_folder;
+	char *next;
+	int elements_processed = 0;
+
+	while (!ast_strlen_zero(cur_mailbox)) {
+		ast_debug(3, "attempting to add next element %d from %s\n", elements_processed, cur_mailbox);
+		if ((next = strchr(cur_mailbox, ',')) || (next = strchr(cur_mailbox, '&'))) {
+			*(next++) = '\0';
+		}
+
+		if ((cur_folder = strchr(cur_mailbox, '/'))) {
+			*(cur_folder++) = '\0';
+		} else {
+			cur_folder = "INBOX";
+		}
+
+		if ((cur_context = strchr(cur_mailbox, '@'))) {
+			*(cur_context++) = '\0';
+		} else {
+			cur_context = "default";
+		}
+
+		if (!ast_strlen_zero(cur_mailbox) && !ast_strlen_zero(cur_context)) {
+			struct vm_recipient *recipient;
+			if (!(recipient = ast_malloc(sizeof(*recipient)))) {
+				ast_log(LOG_ERROR, "Failed to allocate recipient. Aborting function.\n");
+				return;
+			}
+			ast_copy_string(recipient->context, cur_context, sizeof(recipient->context));
+			ast_copy_string(recipient->mailbox, cur_mailbox, sizeof(recipient->mailbox));
+			ast_copy_string(recipient->folder, cur_folder, sizeof(recipient->folder));
+
+			/* Add to list */
+			ast_verb(5, "Adding %s@%s to recipient list\n", recipient->mailbox, recipient->context);
+			AST_LIST_INSERT_HEAD(&mixmonitor->recipient_list, recipient, list);
+		} else {
+			ast_log(LOG_ERROR, "Failed to properly parse extension and/or context from element %d of recipient string: %s\n", elements_processed, vm_recipients);
+		}
+
+		cur_mailbox = next;
+		elements_processed++;
+	}
+}
+
+static void clear_mixmonitor_recipient_list(struct mixmonitor *mixmonitor)
+{
+	struct vm_recipient *current;
+	while ((current = AST_LIST_REMOVE_HEAD(&mixmonitor->recipient_list, list))) {
+		/* Clear list element data */
+		ast_free(current);
+	}
 }
 
 #define SAMPLES_PER_FRAME 160
@@ -397,6 +497,12 @@
 			ast_free(mixmonitor->post_process);
 		}
 
+		/* Free everything in the recipient list */
+		clear_mixmonitor_recipient_list(mixmonitor);
+
+		/* clean stringfields */
+		ast_string_field_free_memory(mixmonitor);
+
 		if (mixmonitor->callid) {
 			ast_callid_unref(mixmonitor->callid);
 		}
@@ -404,10 +510,50 @@
 	}
 }
 
-static void mixmonitor_save_prep(struct mixmonitor *mixmonitor, char *filename, struct ast_filestream **fs, unsigned int *oflags, int *errflag)
+/*!
+ * \internal
+ * \brief Copies the mixmonitor to all voicemail recipients
+ * \param mixmonitor The mixmonitor that needs to forward its file to recipients
+ * \param ext Format of the file that was saved
+ */
+static void copy_to_voicemail(struct mixmonitor *mixmonitor, const char *ext, const char *filename)
+{
+	struct vm_recipient *recipient = NULL;
+	struct ast_vm_recording_data recording_data;
+	if (ast_string_field_init(&recording_data, 512)) {
+		ast_log(LOG_ERROR, "Failed to string_field_init, skipping copy_to_voicemail\n");
+		return;
+	}
+
+	/* Copy strings to stringfields that will be used for all recipients */
+	ast_string_field_set(&recording_data, recording_file, filename);
+	ast_string_field_set(&recording_data, recording_ext, ext);
+	ast_string_field_set(&recording_data, call_context, mixmonitor->call_context);
+	ast_string_field_set(&recording_data, call_macrocontext, mixmonitor->call_macrocontext);
+	ast_string_field_set(&recording_data, call_extension, mixmonitor->call_extension);
+	ast_string_field_set(&recording_data, call_callerchan, mixmonitor->call_callerchan);
+	ast_string_field_set(&recording_data, call_callerid, mixmonitor->call_callerid);
+	/* and call_priority gets copied too */
+	recording_data.call_priority = mixmonitor->call_priority;
+
+	AST_LIST_TRAVERSE(&mixmonitor->recipient_list, recipient, list) {
+		/* context, mailbox, and folder need to be set per recipient */
+		ast_string_field_set(&recording_data, context, recipient->context);
+		ast_string_field_set(&recording_data, mailbox, recipient->mailbox);
+		ast_string_field_set(&recording_data, folder, recipient->folder);
+
+		ast_verb(4, "MixMonitor attempting to send voicemail copy to %s@%s\n", recording_data.mailbox,
+			recording_data.context);
+		ast_app_copy_recording_to_vm(&recording_data);
+	}
+
+	/* Free the string fields for recording_data before exiting the function. */
+	ast_string_field_free_memory(&recording_data);
+}
+
+static void mixmonitor_save_prep(struct mixmonitor *mixmonitor, char *filename, struct ast_filestream **fs, unsigned int *oflags, int *errflag, char **ext)
 {
 	/* Initialize the file if not already done so */
-	char *ext = NULL;
 	char *last_slash = NULL;
 	if (!ast_strlen_zero(filename)) {
 		if (!*fs && !*errflag && !mixmonitor->mixmonitor_ds->fs_quit) {
@@ -416,14 +562,15 @@
 
 			last_slash = strrchr(filename, '/');
 
-			if ((ext = strrchr(filename, '.')) && (ext > last_slash)) {
-				*(ext++) = '\0';
+			if ((*ext = strrchr(filename, '.')) && (*ext > last_slash)) {
+				**ext = '\0';
+				*ext = *ext + 1;
 			} else {
-				ext = "raw";
+				*ext = "raw";
 			}
 
-			if (!(*fs = ast_writefile(filename, ext, NULL, *oflags, 0, 0666))) {
-				ast_log(LOG_ERROR, "Cannot open %s.%s\n", filename, ext);
+			if (!(*fs = ast_writefile(filename, *ext, NULL, *oflags, 0, 0666))) {
+				ast_log(LOG_ERROR, "Cannot open %s.%s\n", filename, *ext);
 				*errflag = 1;
 			} else {
 				struct ast_filestream *tmp = *fs;
@@ -436,6 +583,9 @@
 static void *mixmonitor_thread(void *obj) 
 {
 	struct mixmonitor *mixmonitor = obj;
+	char *fs_ext = "";
+	char *fs_read_ext = "";
+	char *fs_write_ext = "";
 
 	struct ast_filestream **fs = NULL;
 	struct ast_filestream **fs_read = NULL;
@@ -457,9 +607,9 @@
 	fs_write = &mixmonitor->mixmonitor_ds->fs_write;
 
 	ast_mutex_lock(&mixmonitor->mixmonitor_ds->lock);
-	mixmonitor_save_prep(mixmonitor, mixmonitor->filename, fs, &oflags, &errflag);
-	mixmonitor_save_prep(mixmonitor, mixmonitor->filename_read, fs_read, &oflags, &errflag);
-	mixmonitor_save_prep(mixmonitor, mixmonitor->filename_write, fs_write, &oflags, &errflag);
+	mixmonitor_save_prep(mixmonitor, mixmonitor->filename, fs, &oflags, &errflag, &fs_ext);
+	mixmonitor_save_prep(mixmonitor, mixmonitor->filename_read, fs_read, &oflags, &errflag, &fs_read_ext);
+	mixmonitor_save_prep(mixmonitor, mixmonitor->filename_write, fs_write, &oflags, &errflag, &fs_write_ext);
 
 	ast_format_set(&format_slin, ast_format_slin_by_rate(mixmonitor->mixmonitor_ds->samp_rate), 0);
 
@@ -554,6 +704,27 @@
 	}
 
 	ast_verb(2, "End MixMonitor Recording %s\n", mixmonitor->name);
+
+	if (!AST_LIST_EMPTY(&mixmonitor->recipient_list)) {
+		if (ast_strlen_zero(fs_ext)) {
+			ast_log(LOG_ERROR, "No file extension set for Mixmonitor %s. Skipping copy to voicemail.\n",
+				mixmonitor -> name);
+		} else {
+			ast_verb(3, "Copying recordings for Mixmonitor %s to voicemail recipients\n", mixmonitor->name);
+			copy_to_voicemail(mixmonitor, fs_ext, mixmonitor->filename);
+		}
+		if (!ast_strlen_zero(fs_read_ext)) {
+			ast_verb(3, "Copying read recording for Mixmonitor %s to voicemail recipients\n", mixmonitor->name);
+			copy_to_voicemail(mixmonitor, fs_read_ext, mixmonitor->filename_read);
+		}
+		if (!ast_strlen_zero(fs_write_ext)) {
+			ast_verb(3, "Copying write recording for Mixmonitor %s to voicemail recipients\n", mixmonitor->name);
+			copy_to_voicemail(mixmonitor, fs_write_ext, mixmonitor->filename_write);
+		}
+	} else {
+		ast_debug(3, "No recipients to forward monitor to, moving on.\n");
+	}
+
 	mixmonitor_free(mixmonitor);
 	return NULL;
 }
@@ -597,7 +768,8 @@
 static void launch_monitor_thread(struct ast_channel *chan, const char *filename,
 				  unsigned int flags, int readvol, int writevol,
 				  const char *post_process, const char *filename_write,
-				  char *filename_read, const char *uid_channel_var)
+				  char *filename_read, const char *uid_channel_var,
+				  const char *recipients)
 {
 	pthread_t thread;
 	struct mixmonitor *mixmonitor;
@@ -623,6 +795,12 @@
 		return;
 	}
 
+	/* Now that the struct has been calloced, go ahead and initialize the string fields. */
+	if (ast_string_field_init(mixmonitor, 512)) {
+		mixmonitor_free(mixmonitor);
+		return;
+	}
+
 	/* Setup the actual spy before creating our thread */
 	if (ast_audiohook_init(&mixmonitor->audiohook, AST_AUDIOHOOK_TYPE_SPY, mixmonitor_spy_type, 0)) {
 		mixmonitor_free(mixmonitor);
@@ -650,7 +828,6 @@
 	}
 	ast_free(datastore_id);
 
-
 	mixmonitor->name = ast_strdup(ast_channel_name(chan));
 
 	if (!ast_strlen_zero(postprocess2)) {
@@ -667,6 +844,35 @@
 
 	if (!ast_strlen_zero(filename_read)) {
 		mixmonitor->filename_read = ast_strdup(filename_read);
+	}
+
+	if (!ast_strlen_zero(recipients)) {
+		char callerid[256];
+		struct ast_party_connected_line *connected;
+
+		ast_channel_lock(chan);
+
+		/* We use the connected line of the invoking channel for caller ID. */
+
+		connected = ast_channel_connected(chan);
+		ast_debug(3, "Connected Line CID = %d - %s : %d - %s\n", connected->id.name.valid,
+			connected->id.name.str, connected->id.number.valid,
+			connected->id.number.str);
+		ast_callerid_merge(callerid, sizeof(callerid),
+			S_COR(connected->id.name.valid, connected->id.name.str, NULL),
+			S_COR(connected->id.number.valid, connected->id.number.str, NULL),
+			"Unknown");
+
+		ast_string_field_set(mixmonitor, call_context, ast_channel_context(chan));
+		ast_string_field_set(mixmonitor, call_macrocontext, ast_channel_macrocontext(chan));
+		ast_string_field_set(mixmonitor, call_extension, ast_channel_exten(chan));
+		ast_string_field_set(mixmonitor, call_callerchan, ast_channel_name(chan));
+		ast_string_field_set(mixmonitor, call_callerid, callerid);
+		mixmonitor->call_priority = ast_channel_priority(chan);
+
+		ast_channel_unlock(chan);
+
+		add_vm_recipients_from_string(mixmonitor, recipients);
 	}
 
 	ast_set_flag(&mixmonitor->audiohook, AST_AUDIOHOOK_TRIGGER_SYNC);
@@ -723,6 +929,7 @@
         char *uid_channel_var = NULL;
 
 	struct ast_flags flags = { 0 };
+	char *recipients = NULL;
 	char *parse;
 	AST_DECLARE_APP_ARGS(args,
 		AST_APP_ARG(filename);
@@ -774,6 +981,14 @@
 			}
 		}
 
+		if (ast_test_flag(&flags, MUXFLAG_VMRECIPIENTS)) {
+			if (ast_strlen_zero(opts[OPT_ARG_VMRECIPIENTS])) {
+				ast_log(LOG_WARNING, "No voicemail recipients were specified for the vm copy ('m') option.\n");
+			} else {
+				recipients = ast_strdupa(opts[OPT_ARG_VMRECIPIENTS]);
+			}
+		}
+
 		if (ast_test_flag(&flags, MUXFLAG_WRITE)) {
 			filename_write = ast_strdupa(filename_parse(opts[OPT_ARG_WRITENAME], filename_buffer, sizeof(filename_buffer)));
 		}
@@ -799,7 +1014,16 @@
 	}
 
 	pbx_builtin_setvar_helper(chan, "MIXMONITOR_FILENAME", args.filename);
-	launch_monitor_thread(chan, args.filename, flags.flags, readvol, writevol, args.post_process, filename_write, filename_read, uid_channel_var);
+	launch_monitor_thread(chan,
+			args.filename,
+			flags.flags,
+			readvol,
+			writevol,
+			args.post_process,
+			filename_write,
+			filename_read,
+			uid_channel_var,
+			recipients);
 
 	return 0;
 }

Modified: team/file/res_xmpp/apps/app_queue.c
URL: http://svnview.digium.com/svn/asterisk/team/file/res_xmpp/apps/app_queue.c?view=diff&rev=368711&r1=368710&r2=368711
==============================================================================
--- team/file/res_xmpp/apps/app_queue.c (original)
+++ team/file/res_xmpp/apps/app_queue.c Fri Jun  8 13:29:09 2012
@@ -1703,12 +1703,18 @@
 	return state;
 }
 
-static int extension_state_cb(const char *context, const char *exten, enum ast_extension_states state, void *data)
+static int extension_state_cb(char *context, char *exten, struct ast_state_cb_info *info, void *data)
 {
 	struct ao2_iterator miter, qiter;
 	struct member *m;
 	struct call_queue *q;
+	int state = info->exten_state;
 	int found = 0, device_state = extensionstate2devicestate(state);
+
+	/* only interested in extension state updates involving device states */
+	if (info->reason != AST_HINT_UPDATE_DEVICE) {
+		return 0;
+	}
 
 	qiter = ao2_iterator_init(queues, 0);
 	while ((q = ao2_t_iterator_next(&qiter, "Iterate through queues"))) {
@@ -2721,11 +2727,11 @@
 			 */
 			if (!inserted && (qe->prio >= cur->prio) && position && (position <= pos + 1)) {
 				insert_entry(q, prev, qe, &pos);
+				inserted = 1;
 				/*pos is incremented inside insert_entry, so don't need to add 1 here*/
 				if (position < pos) {
 					ast_log(LOG_NOTICE, "Asked to be inserted at position %d but forced into position %d due to higher priority callers\n", position, pos);
 				}
-				inserted = 1;
 			}
 			cur->pos = ++pos;
 			prev = cur;
@@ -3097,7 +3103,7 @@
 		/* Hangup any existing lines we have open */
 		if (outgoing->chan && (outgoing->chan != exception)) {
 			if (exception || cancel_answered_elsewhere) {
-				ast_set_flag(ast_channel_flags(outgoing->chan), AST_FLAG_ANSWERED_ELSEWHERE);
+				ast_channel_hangupcause_set(outgoing->chan, AST_CAUSE_ANSWERED_ELSEWHERE);
 			}
 			ast_hangup(outgoing->chan);
 		}
@@ -3294,7 +3300,7 @@
 		return 0;
 	}
 
-	if (tmp->member->ringinuse) {
+	if (!tmp->member->ringinuse) {
 		if (check_state_unknown && (tmp->member->status == AST_DEVICE_UNKNOWN)) {
 			newstate = ast_device_state(tmp->member->interface);
 			if (newstate != tmp->member->status) {
@@ -3351,7 +3357,7 @@
 	ast_channel_lock_both(tmp->chan, qe->chan);
 
 	if (qe->cancel_answered_elsewhere) {
-		ast_set_flag(ast_channel_flags(tmp->chan), AST_FLAG_ANSWERED_ELSEWHERE);
+		ast_channel_hangupcause_set(tmp->chan, AST_CAUSE_ANSWERED_ELSEWHERE);
 	}
 	ast_channel_appl_set(tmp->chan, "AppQueue");
 	ast_channel_data_set(tmp->chan, "(Outgoing Line)");
@@ -4819,10 +4825,10 @@
 		qe->cancel_answered_elsewhere = 1;
 	}
 
-	/* if the calling channel has the ANSWERED_ELSEWHERE flag set, make sure this is inherited. 
+	/* if the calling channel has AST_CAUSE_ANSWERED_ELSEWHERE set, make sure this is inherited.
 		(this is mainly to support chan_local)
 	*/
-	if (ast_test_flag(ast_channel_flags(qe->chan), AST_FLAG_ANSWERED_ELSEWHERE)) {
+	if (ast_channel_hangupcause(qe->chan) == AST_CAUSE_ANSWERED_ELSEWHERE) {
 		qe->cancel_answered_elsewhere = 1;
 	}
 
@@ -5851,7 +5857,7 @@
 /*!
  * \internal
  * \brief Sets members penalty, if queuename=NULL we set member penalty in all the queues.
- * \param[in] queuename If specified, only act on a mem`ber if it belongs to this queue
+ * \param[in] queuename If specified, only act on a member if it belongs to this queue
  * \param[in] interface Interface of queue member(s) having priority set.
  * \param[in] property Which queue property is being set
  * \param[in] penalty Value penalty is being changed to for each member
@@ -6374,6 +6380,18 @@
 	parse = ast_strdupa(data);
 	AST_STANDARD_APP_ARGS(args, parse);
 
+	ast_debug(1, "queue: %s, options: %s, url: %s, announce: %s, timeout: %s, agi: %s, macro: %s, gosub: %s, rule: %s, position: %s\n",
+		args.queuename,
+		S_OR(args.options, ""),
+		S_OR(args.url, ""),
+		S_OR(args.announceoverride, ""),
+		S_OR(args.queuetimeoutstr, ""),
+		S_OR(args.agi, ""),
+		S_OR(args.macro, ""),
+		S_OR(args.gosub, ""),
+		S_OR(args.rule, ""),
+		S_OR(args.position, ""));
+
 	if (!ast_strlen_zero(args.options)) {
 		ast_app_parse_options(queue_exec_options, &opts, opt_args, args.options);
 	}
@@ -6451,8 +6469,8 @@
 		}
 	}
 
-	ast_debug(1, "queue: %s, options: %s, url: %s, announce: %s, expires: %ld, priority: %d\n",
-		args.queuename, args.options, args.url, args.announceoverride, (long)qe.expire, prio);
+	ast_debug(1, "queue: %s, expires: %ld, priority: %d\n",
+		args.queuename, (long)qe.expire, prio);
 
 	qe.chan = chan;
 	qe.prio = prio;
@@ -6468,6 +6486,8 @@
 		set_queue_result(chan, reason);
 		return 0;
 	}
+	ast_assert(qe.parent != NULL);
+
 	ast_queue_log(args.queuename, ast_channel_uniqueid(chan), "NONE", "ENTERQUEUE", "%s|%s|%d",
 		S_OR(args.url, ""),
 		S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, ""),
@@ -6625,12 +6645,13 @@
 	if (reason != QUEUE_UNKNOWN)
 		set_queue_result(chan, reason);
 
-	if (qe.parent) {
-		/* every queue_ent is given a reference to it's parent call_queue when it joins the queue.
-		 * This ref must be taken away right before the queue_ent is destroyed.  In this case
-		 * the queue_ent is about to be returned on the stack */
-		qe.parent = queue_unref(qe.parent);
-	}
+	/*
+	 * every queue_ent is given a reference to it's parent
+	 * call_queue when it joins the queue.  This ref must be taken
+	 * away right before the queue_ent is destroyed.  In this case
+	 * the queue_ent is about to be returned on the stack
+	 */
+	qe.parent = queue_unref(qe.parent);
 
 	return res;
 }

Modified: team/file/res_xmpp/apps/app_skel.c
URL: http://svnview.digium.com/svn/asterisk/team/file/res_xmpp/apps/app_skel.c?view=diff&rev=368711&r1=368710&r2=368711
==============================================================================
--- team/file/res_xmpp/apps/app_skel.c (original)
+++ team/file/res_xmpp/apps/app_skel.c Fri Jun  8 13:29:09 2012
@@ -15,8 +15,8 @@
  * the GNU General Public License Version 2. See the LICENSE file
  * at the top of the source tree.
  *
- * Please follow coding guidelines 
- * http://svn.digium.com/view/asterisk/trunk/doc/CODING-GUIDELINES
+ * Please follow coding guidelines
+ * https://wiki.asterisk.org/wiki/display/AST/Coding+Guidelines
  */
 
 /*! \file
@@ -24,8 +24,8 @@
  * \brief Skeleton application
  *
  * \author\verbatim <Your Name Here> <<Your Email Here>> \endverbatim
- * 
- * This is a skeleton for development of an Asterisk application 
+ *
+ * This is a skeleton for development of an Asterisk application
  * \ingroup applications
  */
 
@@ -38,79 +38,306 @@
 
 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
 
+#include <math.h> /* log10 */
 #include "asterisk/file.h"
 #include "asterisk/channel.h"
 #include "asterisk/pbx.h"
 #include "asterisk/module.h"
 #include "asterisk/lock.h"
 #include "asterisk/app.h"
+#include "asterisk/config.h"
+#include "asterisk/config_options.h"
+#include "asterisk/say.h"
+#include "asterisk/astobj2.h"
+#include "asterisk/acl.h"
+#include "asterisk/netsock2.h"
+#include "asterisk/strings.h"
+#include "asterisk/cli.h"
 
 /*** DOCUMENTATION
-	<application name="Skel" language="en_US">
+	<application name="SkelGuessNumber" language="en_US">
 		<synopsis>
-			Simple one line explaination.
+			An example number guessing game
 		</synopsis>
 		<syntax>
-			<parameter name="dummy" required="true"/>
+			<parameter name="level" required="true"/>
 			<parameter name="options">
 				<optionlist>
-					<option name="a">
-						<para>Option A.</para>
+					<option name="c">
+						<para>The computer should cheat</para>
 					</option>
-					<option name="b">
-						<para>Option B.</para>
-					</option>
-					<option name="c">
-						<para>Option C.</para>
+					<option name="n">
+						<para>How many games to play before hanging up</para>
 					</option>
 				</optionlist>
 			</parameter>
 		</syntax>
 		<description>
-		<para>This application is a template to build other applications from. 
-		It shows you the basic structure to create your own Asterisk applications.</para>
+		<para>This simple number guessing application is a template to build other applications
+		from. It shows you the basic structure to create your own Asterisk applications.</para>
 		</description>
 	</application>
  ***/
 
-static char *app = "Skel";
+static char *app = "SkelGuessNumber";
 
 enum option_flags {
-	OPTION_A = (1 << 0),
-	OPTION_B = (1 << 1),
-	OPTION_C = (1 << 2),
+	OPTION_CHEAT    = (1 << 0),
+	OPTION_NUMGAMES = (1 << 1),
 };
 
 enum option_args {
-	OPTION_ARG_B = 0,
-	OPTION_ARG_C = 1,
+	OPTION_ARG_NUMGAMES,
 	/* This *must* be the last value in this enum! */
-	OPTION_ARG_ARRAY_SIZE = 2,
+	OPTION_ARG_ARRAY_SIZE,
 };
 
 AST_APP_OPTIONS(app_opts,{
-	AST_APP_OPTION('a', OPTION_A),
-	AST_APP_OPTION_ARG('b', OPTION_B, OPTION_ARG_B),
-	AST_APP_OPTION_ARG('c', OPTION_C, OPTION_ARG_C),
+	AST_APP_OPTION('c', OPTION_CHEAT),
+	AST_APP_OPTION_ARG('n', OPTION_NUMGAMES, OPTION_ARG_NUMGAMES),
 });
 
+/*! \brief A structure to hold global configuration-related options */
+struct skel_global_config {
+	AST_DECLARE_STRING_FIELDS(
+		AST_STRING_FIELD(prompt); /*!< The comma-separated list of sounds to prompt to enter a number */
+		AST_STRING_FIELD(wrong);  /*!< The comma-separated list of sounds to indicate a wrong guess */
+		AST_STRING_FIELD(right);  /*!< The comma-separated list of sounds to indicate a right guess */
+		AST_STRING_FIELD(high);   /*!< The comma-separated list of sounds to indicate a high guess */
+		AST_STRING_FIELD(low);    /*!< The comma-separated list of sounds to indicate a low guess */
+		AST_STRING_FIELD(lose);  /*!< The comma-separated list of sounds to indicate a lost game */
+	);
+	uint32_t num_games;    /*!< The number of games to play before hanging up */
+	unsigned char cheat:1; /*!< Whether the computer can cheat or not */
+};
+

[... 9798 lines stripped ...]



More information about the asterisk-commits mailing list