[asterisk-commits] dlee: branch dlee/stasis-http r380385 - in /team/dlee/stasis-http: ./ addons/...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Tue Jan 29 12:00:50 CST 2013


Author: dlee
Date: Tue Jan 29 12:00:44 2013
New Revision: 380385

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=380385
Log:
Merged from trunk up to 380383.

Added:
    team/dlee/stasis-http/configs/sorcery.conf.sample
      - copied unchanged from r380383, trunk/configs/sorcery.conf.sample
    team/dlee/stasis-http/configs/test_sorcery.conf.sample
      - copied unchanged from r380383, trunk/configs/test_sorcery.conf.sample
    team/dlee/stasis-http/include/asterisk/sorcery.h
      - copied unchanged from r380383, trunk/include/asterisk/sorcery.h
    team/dlee/stasis-http/include/asterisk/threadpool.h
      - copied unchanged from r380383, trunk/include/asterisk/threadpool.h
    team/dlee/stasis-http/main/sorcery.c
      - copied unchanged from r380383, trunk/main/sorcery.c
    team/dlee/stasis-http/main/threadpool.c
      - copied unchanged from r380383, trunk/main/threadpool.c
    team/dlee/stasis-http/res/res_sorcery_config.c
      - copied unchanged from r380383, trunk/res/res_sorcery_config.c
    team/dlee/stasis-http/res/res_sorcery_memory.c
      - copied unchanged from r380383, trunk/res/res_sorcery_memory.c
    team/dlee/stasis-http/tests/test_sorcery.c
      - copied unchanged from r380383, trunk/tests/test_sorcery.c
    team/dlee/stasis-http/tests/test_taskprocessor.c
      - copied unchanged from r380383, trunk/tests/test_taskprocessor.c
    team/dlee/stasis-http/tests/test_threadpool.c
      - copied unchanged from r380383, trunk/tests/test_threadpool.c
Modified:
    team/dlee/stasis-http/   (props changed)
    team/dlee/stasis-http/CHANGES
    team/dlee/stasis-http/Makefile
    team/dlee/stasis-http/UPGRADE-11.txt
    team/dlee/stasis-http/UPGRADE.txt
    team/dlee/stasis-http/addons/chan_mobile.c
    team/dlee/stasis-http/apps/app_confbridge.c
    team/dlee/stasis-http/apps/app_controlplayback.c
    team/dlee/stasis-http/apps/app_meetme.c
    team/dlee/stasis-http/apps/app_minivm.c
    team/dlee/stasis-http/apps/app_playback.c
    team/dlee/stasis-http/apps/app_voicemail.c
    team/dlee/stasis-http/apps/confbridge/conf_config_parser.c
    team/dlee/stasis-http/autoconf/ast_check_pwlib.m4
    team/dlee/stasis-http/bridges/bridge_builtin_features.c
    team/dlee/stasis-http/bridges/bridge_multiplexed.c
    team/dlee/stasis-http/bridges/bridge_simple.c
    team/dlee/stasis-http/bridges/bridge_softmix.c
    team/dlee/stasis-http/channels/chan_bridge.c
    team/dlee/stasis-http/channels/chan_iax2.c
    team/dlee/stasis-http/channels/chan_misdn.c
    team/dlee/stasis-http/channels/chan_sip.c
    team/dlee/stasis-http/channels/chan_skinny.c
    team/dlee/stasis-http/channels/iax2.h
    team/dlee/stasis-http/channels/sip/include/reqresp_parser.h
    team/dlee/stasis-http/channels/sip/reqresp_parser.c
    team/dlee/stasis-http/channels/sip/sdp_crypto.c
    team/dlee/stasis-http/codecs/codec_ilbc.c
    team/dlee/stasis-http/configs/logger.conf.sample
    team/dlee/stasis-http/configs/skinny.conf.sample
    team/dlee/stasis-http/configure
    team/dlee/stasis-http/configure.ac
    team/dlee/stasis-http/contrib/init.d/rc.archlinux.asterisk
    team/dlee/stasis-http/contrib/init.d/rc.debian.asterisk
    team/dlee/stasis-http/contrib/init.d/rc.gentoo.asterisk
    team/dlee/stasis-http/contrib/init.d/rc.mandriva.asterisk
    team/dlee/stasis-http/contrib/init.d/rc.redhat.asterisk
    team/dlee/stasis-http/contrib/init.d/rc.slackware.asterisk
    team/dlee/stasis-http/contrib/init.d/rc.suse.asterisk
    team/dlee/stasis-http/contrib/scripts/autosupport
    team/dlee/stasis-http/contrib/scripts/install_prereq
    team/dlee/stasis-http/contrib/scripts/safe_asterisk
    team/dlee/stasis-http/doc/appdocsxml.dtd
    team/dlee/stasis-http/funcs/func_frame_trace.c
    team/dlee/stasis-http/include/asterisk/autoconfig.h.in
    team/dlee/stasis-http/include/asterisk/bridging.h
    team/dlee/stasis-http/include/asterisk/bridging_features.h
    team/dlee/stasis-http/include/asterisk/bridging_technology.h
    team/dlee/stasis-http/include/asterisk/compat.h
    team/dlee/stasis-http/include/asterisk/file.h
    team/dlee/stasis-http/include/asterisk/frame.h
    team/dlee/stasis-http/include/asterisk/taskprocessor.h
    team/dlee/stasis-http/include/asterisk/test.h
    team/dlee/stasis-http/main/Makefile
    team/dlee/stasis-http/main/app.c
    team/dlee/stasis-http/main/asterisk.c
    team/dlee/stasis-http/main/astobj2.c
    team/dlee/stasis-http/main/bridging.c
    team/dlee/stasis-http/main/channel.c
    team/dlee/stasis-http/main/features.c
    team/dlee/stasis-http/main/file.c
    team/dlee/stasis-http/main/logger.c
    team/dlee/stasis-http/main/manager.c
    team/dlee/stasis-http/main/strcompat.c
    team/dlee/stasis-http/main/taskprocessor.c
    team/dlee/stasis-http/makeopts.in
    team/dlee/stasis-http/res/res_agi.c
    team/dlee/stasis-http/res/res_fax_spandsp.c
    team/dlee/stasis-http/res/res_jabber.c
    team/dlee/stasis-http/res/res_xmpp.c
    team/dlee/stasis-http/sounds/Makefile

Propchange: team/dlee/stasis-http/
------------------------------------------------------------------------------
Binary property 'branch-11-merged' - no diff available.

Propchange: team/dlee/stasis-http/
------------------------------------------------------------------------------
--- svnmerge-integrated (original)
+++ svnmerge-integrated Tue Jan 29 12:00:44 2013
@@ -1,1 +1,1 @@
-/trunk:1-379023
+/trunk:1-380384

Modified: team/dlee/stasis-http/CHANGES
URL: http://svnview.digium.com/svn/asterisk/team/dlee/stasis-http/CHANGES?view=diff&rev=380385&r1=380384&r2=380385
==============================================================================
--- team/dlee/stasis-http/CHANGES (original)
+++ team/dlee/stasis-http/CHANGES Tue Jan 29 12:00:44 2013
@@ -11,6 +11,7 @@
 --- Functionality changes from Asterisk 11 to Asterisk 12 --------------------
 ------------------------------------------------------------------------------
 
+
 AMI (Asterisk Manager Interface)
 ------------------
  * The SIPshowpeer action will now include a 'SubscribeContext' field for a peer
@@ -30,6 +31,25 @@
    than 15 characters and no longer shows authorization requirement for commands.
    'Manager Show Command' now displays the privileges needed for using a given
    manager command instead.
+
+ * Added new action "ControlPlayback". The ControlPlayback action allows an AMI
+   client to manipulate audio currently being played back on a channel. The
+   supported operations depend on the application being used to send audio to
+   the channel. When the audio playback was initiated using the ControlPlayback
+   application or CONTROL STREAM FILE AGI command, the audio can be paused,
+   stopped, restarted, reversed, or skipped forward. When initiated by other
+   mechanisms (such as the Playback application), the audio can be stopped,
+   reversed, or skipped forward.
+
+Channel Drivers
+------------------
+
+chan_mobile
+------------------
+ * Added general support for busy detection.
+
+ * Added ECAM command support for Sony Ericsson phones.
+
 
 Features
 -------------------
@@ -46,6 +66,9 @@
  * When performing queue pause/unpause on an interface without specifying an
    individual queue, the PAUSEALL/UNPAUSEALL event will only be logged if at
    least one member of any queue exists for that interface.
+
+ * Added the 'queue_log_realtime_use_gmt' option to have timestamps in GMT
+   for realtime queue log entries.
 
 Queue
 -------------------

Modified: team/dlee/stasis-http/Makefile
URL: http://svnview.digium.com/svn/asterisk/team/dlee/stasis-http/Makefile?view=diff&rev=380385&r1=380384&r2=380385
==============================================================================
--- team/dlee/stasis-http/Makefile (original)
+++ team/dlee/stasis-http/Makefile Tue Jan 29 12:00:44 2013
@@ -252,10 +252,8 @@
 
 ifneq ($(findstring darwin,$(OSARCH)),)
   _ASTCFLAGS+=-D__Darwin__
-  _SOLINK=-Xlinker -macosx_version_min -Xlinker 10.4 -Xlinker -undefined -Xlinker dynamic_lookup -force_flat_namespace
-  ifeq ($(shell if test `/usr/bin/sw_vers -productVersion | cut -c4` -gt 5; then echo 6; else echo 0; fi),6)
-    _SOLINK+=/usr/lib/bundle1.o
-  endif
+  _SOLINK=-Xlinker -macosx_version_min -Xlinker 10.6 -Xlinker -undefined -Xlinker dynamic_lookup
+  _SOLINK+=/usr/lib/bundle1.o
   SOLINK=-bundle $(_SOLINK)
   DYLINK=-Xlinker -dylib $(_SOLINK)
   _ASTLDFLAGS+=-L/usr/local/lib
@@ -267,6 +265,9 @@
     _ASTLDFLAGS+=-L/usr/local/lib
   endif
 endif
+
+# Include rpath settings
+_ASTLDFLAGS+=$(AST_RPATH)
 
 ifeq ($(OSARCH),SunOS)
   SOLINK=-shared -fpic -L/usr/local/ssl/lib -lrt

Modified: team/dlee/stasis-http/UPGRADE-11.txt
URL: http://svnview.digium.com/svn/asterisk/team/dlee/stasis-http/UPGRADE-11.txt?view=diff&rev=380385&r1=380384&r2=380385
==============================================================================
--- team/dlee/stasis-http/UPGRADE-11.txt (original)
+++ team/dlee/stasis-http/UPGRADE-11.txt Tue Jan 29 12:00:44 2013
@@ -19,6 +19,14 @@
 === UPGRADE-10.txt -- Upgrade info for 1.8 to 10
 ===
 ===========================================================
+
+From 11.2 to 11.3:
+
+* Now by default, when Asterisk is installed in a path other than /usr, the
+  Asterisk binary will search for shared libraries in ${libdir} in addition to
+  searching system libraries. This allows Asterisk to find its shared
+  libraries without having to specify LD_LIBRARY_PATH. This can be disabled by
+  passing --disable-rpath to configure.
 
 From 10 to 11:
 

Modified: team/dlee/stasis-http/UPGRADE.txt
URL: http://svnview.digium.com/svn/asterisk/team/dlee/stasis-http/UPGRADE.txt?view=diff&rev=380385&r1=380384&r2=380385
==============================================================================
--- team/dlee/stasis-http/UPGRADE.txt (original)
+++ team/dlee/stasis-http/UPGRADE.txt Tue Jan 29 12:00:44 2013
@@ -21,7 +21,6 @@
 ===
 ===========================================================
 
-From 11 to 12:
 
 AMI:
  - The SIP SIPqualifypeer action now sends a response indicating it will qualify

Modified: team/dlee/stasis-http/addons/chan_mobile.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/stasis-http/addons/chan_mobile.c?view=diff&rev=380385&r1=380384&r2=380385
==============================================================================
--- team/dlee/stasis-http/addons/chan_mobile.c (original)
+++ team/dlee/stasis-http/addons/chan_mobile.c Tue Jan 29 12:00:44 2013
@@ -147,6 +147,7 @@
 	int ring_sched_id;
 	struct ast_dsp *dsp;
 	struct ast_sched_context *sched;
+	int hangupcause;
 
 	/* flags */
 	unsigned int outgoing:1;	/*!< outgoing call */
@@ -172,6 +173,9 @@
 static int handle_response_cmti(struct mbl_pvt *pvt, char *buf);
 static int handle_response_cmgr(struct mbl_pvt *pvt, char *buf);
 static int handle_response_cusd(struct mbl_pvt *pvt, char *buf);
+static int handle_response_busy(struct mbl_pvt *pvt);
+static int handle_response_no_dialtone(struct mbl_pvt *pvt, char *buf);
+static int handle_response_no_carrier(struct mbl_pvt *pvt, char *buf);
 static int handle_sms_prompt(struct mbl_pvt *pvt, char *buf);
 
 /* CLI stuff */
@@ -341,6 +345,7 @@
 	struct hfp_cind cind_map;	/*!< the cind name to index mapping for this AG */
 	int rsock;			/*!< our rfcomm socket */
 	int rport;			/*!< our rfcomm port */
+	int sent_alerting;		/*!< have we sent alerting? */
 };
 
 
@@ -435,6 +440,10 @@
 	AT_CMER,
 	AT_CIND_TEST,
 	AT_CUSD,
+	AT_BUSY,
+	AT_NO_DIALTONE,
+	AT_NO_CARRIER,
+	AT_ECAM,
 } at_message_t;
 
 static int at_match_prefix(char *buf, char *prefix);
@@ -981,6 +990,7 @@
 			ast_log(LOG_ERROR, "error sending ATD command on %s\n", pvt->id);
 			return -1;
 		}
+		pvt->hangupcause = 0;
 		pvt->needchup = 1;
 		msg_queue_push(pvt, AT_OK, AT_D);
 	} else {
@@ -1314,6 +1324,9 @@
 			if (ast_channel_trylock(pvt->owner)) {
 				DEADLOCK_AVOIDANCE(&pvt->lock);
 			} else {
+				if (pvt->hangupcause != 0) {
+					ast_channel_hangupcause_set(pvt->owner, pvt->hangupcause);
+				}
 				ast_queue_hangup(pvt->owner);
 				ast_channel_unlock(pvt->owner);
 				break;
@@ -1376,7 +1389,7 @@
 	memset(&addr, 0, sizeof(addr));
 	addr.rc_family = AF_BLUETOOTH;
 	bacpy(&addr.rc_bdaddr, &src);
-	addr.rc_channel = (uint8_t) 1;
+	addr.rc_channel = (uint8_t) 0;
 	if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
 		ast_debug(1, "bind() failed (%d).\n", errno);
 		close(s);
@@ -2030,6 +2043,14 @@
 		return AT_VGS;
 	} else if (at_match_prefix(buf, "+CUSD:")) {
 		return AT_CUSD;
+	} else if (at_match_prefix(buf, "BUSY")) {
+		return AT_BUSY;
+	} else if (at_match_prefix(buf, "NO DIALTONE")) {
+		return AT_NO_DIALTONE;
+	} else if (at_match_prefix(buf, "NO CARRIER")) {
+		return AT_NO_CARRIER;
+	} else if (at_match_prefix(buf, "*ECAV:")) {
+		return AT_ECAM;
 	} else {
 		return AT_UNKNOWN;
 	}
@@ -2074,6 +2095,12 @@
 		return "SMS PROMPT";
 	case AT_CMS_ERROR:
 		return "+CMS ERROR";
+	case AT_BUSY:
+		return "BUSY";
+	case AT_NO_DIALTONE:
+		return "NO DIALTONE";
+	case AT_NO_CARRIER:
+		return "NO CARRIER";
 	/* at commands */
 	case AT_A:
 		return "ATA";
@@ -2101,6 +2128,8 @@
 		return "AT+CIND=?";
 	case AT_CUSD:
 		return "AT+CUSD";
+	case AT_ECAM:
+		return "AT*ECAM";
 	}
 }
 
@@ -2108,6 +2137,40 @@
 /*
  * bluetooth handsfree profile helpers
  */
+
+ /*!
+ * \brief Parse a ECAV event.
+ * \param hfp an hfp_pvt struct
+ * \param buf the buffer to parse (null terminated)
+ * \return -1 on error (parse error) or a ECAM value on success
+ *
+ * Example string: *ECAV: <ccid>,<ccstatus>,<calltype>[,<processid>]
+ * [,exitcause][,<number>,<type>]
+ *
+ * Example indicating busy: *ECAV: 1,7,1
+ */
+static int hfp_parse_ecav(struct hfp_pvt *hfp, char *buf)
+{
+	int ccid = 0;
+	int ccstatus = 0;
+	int calltype = 0;
+
+	if (!sscanf(buf, "*ECAV: %2d,%2d,%2d", &ccid, &ccstatus, &calltype)) {
+		ast_debug(1, "[%s] error parsing ECAV event '%s'\n", hfp->owner->id, buf);
+		return -1;
+	}
+
+	return ccstatus;
+}
+
+/*!
+ * \brief Enable Sony Erricson extensions / indications.
+ * \param hfp an hfp_pvt struct
+ */
+static int hfp_send_ecam(struct hfp_pvt *hfp)
+{
+	return rfcomm_write(hfp->rsock, "AT*ECAM=1\r");
+}
 
 /*!
  * \brief Parse a CIEV event.
@@ -2238,6 +2301,7 @@
 			if (buf[i] == '"') {
 				state++;
 			}
+			break;
 		case 2: /* mark the start of the number */
 			if (from_number) {
 				*from_number = &buf[i];
@@ -3214,6 +3278,14 @@
 			break;
 		case AT_CLIP:
 			ast_debug(1, "[%s] caling line indication enabled\n", pvt->id);
+			if (hfp_send_ecam(pvt->hfp) || msg_queue_push(pvt, AT_OK, AT_ECAM)) {
+				ast_debug(1, "[%s] error enabling Sony Ericsson call monitoring extensions\n", pvt->id);
+				goto e_return;
+			}
+
+			break;
+		case AT_ECAM:
+			ast_debug(1, "[%s] Sony Ericsson call monitoring is active on device\n", pvt->id);
 			if (hfp_send_vgs(pvt->hfp, 15) || msg_queue_push(pvt, AT_OK, AT_VGS)) {
 				ast_debug(1, "[%s] error synchronizing gain settings\n", pvt->id);
 				goto e_return;
@@ -3345,6 +3417,21 @@
 			ast_debug(1, "[%s] error setting CNMI\n", pvt->id);
 			ast_debug(1, "[%s] no SMS support\n", pvt->id);
 			break;
+		case AT_ECAM:
+			ast_debug(1, "[%s] Mobile does not support Sony Ericsson extensions\n", pvt->id);
+
+			/* this is not a fatal error, let's continue with the initialization */
+
+			if (hfp_send_vgs(pvt->hfp, 15) || msg_queue_push(pvt, AT_OK, AT_VGS)) {
+				ast_debug(1, "[%s] error synchronizing gain settings\n", pvt->id);
+				goto e_return;
+			}
+
+			pvt->timeout = -1;
+			pvt->hfp->initialized = 1;
+			ast_verb(3, "Bluetooth Device %s initialized and ready.\n", pvt->id);
+
+			break;
 		/* end initialization stuff */
 
 		case AT_A:
@@ -3440,6 +3527,9 @@
 		case HFP_CIND_CALLSETUP_NONE:
 			if (pvt->hfp->cind_state[pvt->hfp->cind_map.call] != HFP_CIND_CALL_ACTIVE) {
 				if (pvt->owner) {
+					if (pvt->hfp->sent_alerting == 1) {
+						handle_response_busy(pvt);
+					}
 					if (mbl_queue_hangup(pvt)) {
 						ast_log(LOG_ERROR, "[%s] error queueing hangup, disconnectiong...\n", pvt->id);
 						return -1;
@@ -3458,6 +3548,7 @@
 			break;
 		case HFP_CIND_CALLSETUP_OUTGOING:
 			if (pvt->outgoing) {
+				pvt->hfp->sent_alerting = 0;
 				ast_debug(1, "[%s] outgoing call\n", pvt->id);
 			} else {
 				ast_verb(3, "[%s] user dialed from handset, disconnecting\n", pvt->id);
@@ -3468,6 +3559,7 @@
 			if (pvt->outgoing) {
 				ast_debug(1, "[%s] remote alerting\n", pvt->id);
 				mbl_queue_control(pvt, AST_CONTROL_RINGING);
+				pvt->hfp->sent_alerting = 1;
 			}
 			break;
 		}
@@ -3659,6 +3751,50 @@
 
 	ast_verb(0, "[%s] CUSD response: %s\n", pvt->id, cusd);
 
+	return 0;
+}
+
+/*!
+ * \brief Handle BUSY messages.
+ * \param pvt a mbl_pvt structure
+ * \retval 0 success
+ * \retval -1 error
+ */
+static int handle_response_busy(struct mbl_pvt *pvt)
+{
+	pvt->hangupcause = AST_CAUSE_USER_BUSY;
+	pvt->needchup = 1;
+	mbl_queue_control(pvt, AST_CONTROL_BUSY);
+	return 0;
+}
+
+/*!
+ * \brief Handle NO DIALTONE messages.
+ * \param pvt a mbl_pvt structure
+ * \param buf a null terminated buffer containing an AT message
+ * \retval 0 success
+ * \retval -1 error
+ */
+static int handle_response_no_dialtone(struct mbl_pvt *pvt, char *buf)
+{
+	ast_verb(1, "[%s] mobile reports NO DIALTONE\n", pvt->id);
+	pvt->needchup = 1;
+	mbl_queue_control(pvt, AST_CONTROL_CONGESTION);
+	return 0;
+}
+
+/*!
+ * \brief Handle NO CARRIER messages.
+ * \param pvt a mbl_pvt structure
+ * \param buf a null terminated buffer containing an AT message
+ * \retval 0 success
+ * \retval -1 error
+ */
+static int handle_response_no_carrier(struct mbl_pvt *pvt, char *buf)
+{
+	ast_verb(1, "[%s] mobile reports NO CARRIER\n", pvt->id);
+	pvt->needchup = 1;
+	mbl_queue_control(pvt, AST_CONTROL_CONGESTION);
 	return 0;
 }
 
@@ -3820,6 +3956,40 @@
 			}
 			ast_mutex_unlock(&pvt->lock);
 			break;
+		case AT_BUSY:
+			ast_mutex_lock(&pvt->lock);
+			if (handle_response_busy(pvt)) {
+				ast_mutex_unlock(&pvt->lock);
+				goto e_cleanup;
+			}
+			ast_mutex_unlock(&pvt->lock);
+			break;
+		case AT_NO_DIALTONE:
+			ast_mutex_lock(&pvt->lock);
+			if (handle_response_no_dialtone(pvt, buf)) {
+				ast_mutex_unlock(&pvt->lock);
+				goto e_cleanup;
+			}
+			ast_mutex_unlock(&pvt->lock);
+			break;
+		case AT_NO_CARRIER:
+			ast_mutex_lock(&pvt->lock);
+			if (handle_response_no_carrier(pvt, buf)) {
+				ast_mutex_unlock(&pvt->lock);
+				goto e_cleanup;
+			}
+			ast_mutex_unlock(&pvt->lock);
+			break;
+		case AT_ECAM:
+			ast_mutex_lock(&pvt->lock);
+			if (hfp_parse_ecav(hfp, buf) == 7) {
+				if (handle_response_busy(pvt)) {
+					ast_mutex_unlock(&pvt->lock);
+					goto e_cleanup;
+				}
+			}
+			ast_mutex_unlock(&pvt->lock);
+			break;
 		case AT_UNKNOWN:
 			ast_debug(1, "[%s] ignoring unknown message: %s\n", pvt->id, buf);
 			break;

Modified: team/dlee/stasis-http/apps/app_confbridge.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/stasis-http/apps/app_confbridge.c?view=diff&rev=380385&r1=380384&r2=380385
==============================================================================
--- team/dlee/stasis-http/apps/app_confbridge.c (original)
+++ team/dlee/stasis-http/apps/app_confbridge.c Tue Jan 29 12:00:44 2013
@@ -161,7 +161,7 @@
 		</synopsis>
 		<syntax>
 			<xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
-			<parameter name="Conference" required="false">
+			<parameter name="Conference" required="true">
 				<para>Conference number.</para>
 			</parameter>
 		</syntax>
@@ -675,6 +675,23 @@
 }
 
 /*!
+ * \internal
+ * \brief Complain if the given sound file does not exist.
+ *
+ * \param filename Sound file to check if exists.
+ *
+ * \retval non-zero if the file exists.
+ */
+static int sound_file_exists(const char *filename)
+{
+	if (ast_fileexists(filename, NULL, NULL)) {
+		return -1;
+	}
+	ast_log(LOG_WARNING, "File %s does not exist in any format\n", filename);
+	return 0;
+}
+
+/*!
  * \brief Announce number of users in the conference bridge to the caller
  *
  * \param conference_bridge Conference bridge to peek at
@@ -719,7 +736,7 @@
 				"")) {
 				return -1;
 			}
-		} else if (ast_fileexists(there_are, NULL, NULL) && ast_fileexists(other_in_party, NULL, NULL)) {
+		} else if (sound_file_exists(there_are) && sound_file_exists(other_in_party)) {
 			play_sound_file(conference_bridge, there_are);
 			play_sound_number(conference_bridge, conference_bridge->activeusers - 1);
 			play_sound_file(conference_bridge, other_in_party);
@@ -1209,7 +1226,16 @@
 
 	if (ast_test_flag(&conference_bridge_user->u_profile, USER_OPT_ANNOUNCEUSERCOUNTALL) &&
 		(conference_bridge->activeusers > conference_bridge_user->u_profile.announce_user_count_all_after)) {
-		if (announce_user_count(conference_bridge, NULL)) {
+		int user_count_res;
+
+		/*
+		 * We have to autoservice the new user because he has not quite
+		 * joined the conference yet.
+		 */
+		ast_autoservice_start(conference_bridge_user->chan);
+		user_count_res = announce_user_count(conference_bridge, NULL);
+		ast_autoservice_stop(conference_bridge_user->chan);
+		if (user_count_res) {
 			leave_conference(conference_bridge_user);
 			return NULL;
 		}
@@ -1288,8 +1314,7 @@
 	struct ast_channel *underlying_channel;
 
 	/* Do not waste resources trying to play files that do not exist */
-	if (!ast_strlen_zero(filename) && !ast_fileexists(filename, NULL, NULL)) {
-		ast_log(LOG_WARNING, "File %s does not exist in any format\n", !ast_strlen_zero(filename) ? filename : "<unknown>");
+	if (!ast_strlen_zero(filename) && !sound_file_exists(filename)) {
 		return 0;
 	}
 
@@ -1303,7 +1328,10 @@
 	} else {
 		/* Channel was already available so we just need to add it back into the bridge */
 		underlying_channel = ast_channel_tech(conference_bridge->playback_chan)->bridged_channel(conference_bridge->playback_chan, NULL);
-		ast_bridge_impart(conference_bridge->bridge, underlying_channel, NULL, NULL, 0);
+		if (ast_bridge_impart(conference_bridge->bridge, underlying_channel, NULL, NULL, 0)) {
+			ast_mutex_unlock(&conference_bridge->playback_lock);
+			return -1;
+		}
 	}
 
 	/* The channel is all under our control, in goes the prompt */
@@ -2092,6 +2120,16 @@
 	return CLI_SUCCESS;
 }
 
+static void handle_cli_confbridge_list_item(struct ast_cli_args *a, struct conference_bridge_user *participant)
+{
+	ast_cli(a->fd, "%-29s ", ast_channel_name(participant->chan));
+	ast_cli(a->fd, "%-17s", participant->u_profile.name);
+	ast_cli(a->fd, "%-17s", participant->b_profile.name);
+	ast_cli(a->fd, "%-17s", participant->menu_name);
+	ast_cli(a->fd, "%-17s", S_COR(ast_channel_caller(participant->chan)->id.number.valid, ast_channel_caller(participant->chan)->id.number.str, "<unknown>"));
+	ast_cli(a->fd, "\n");
+}
+
 static char *handle_cli_confbridge_list(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 {
 	struct ao2_iterator i;
@@ -2118,7 +2156,7 @@
 		ast_cli(a->fd, "================================ ====== ====== ========\n");
 		i = ao2_iterator_init(conference_bridges, 0);
 		while ((bridge = ao2_iterator_next(&i))) {
-			ast_cli(a->fd, "%-32s %6i %6i %s\n", bridge->name, bridge->activeusers, bridge->markedusers, (bridge->locked ? "locked" : "unlocked"));
+			ast_cli(a->fd, "%-32s %6i %6i %s\n", bridge->name, bridge->activeusers + bridge->waitingusers, bridge->markedusers, (bridge->locked ? "locked" : "unlocked"));
 			ao2_ref(bridge, -1);
 		}
 		ao2_iterator_destroy(&i);
@@ -2136,12 +2174,10 @@
 		ast_cli(a->fd, "============================= ================ ================ ================ ================\n");
 		ao2_lock(bridge);
 		AST_LIST_TRAVERSE(&bridge->active_list, participant, list) {
-			ast_cli(a->fd, "%-29s ", ast_channel_name(participant->chan));
-			ast_cli(a->fd, "%-17s", participant->u_profile.name);
-			ast_cli(a->fd, "%-17s", participant->b_profile.name);
-			ast_cli(a->fd, "%-17s", participant->menu_name);
-			ast_cli(a->fd, "%-17s", S_COR(ast_channel_caller(participant->chan)->id.number.valid, ast_channel_caller(participant->chan)->id.number.str, "<unknown>"));
-			ast_cli(a->fd, "\n");
+			handle_cli_confbridge_list_item(a, participant);
+		}
+		AST_LIST_TRAVERSE(&bridge->waiting_list, participant, list) {
+			handle_cli_confbridge_list_item(a, participant);
 		}
 		ao2_unlock(bridge);
 		ao2_ref(bridge, -1);
@@ -2440,6 +2476,27 @@
 	.read = func_confbridge_info,
 };
 
+static void action_confbridgelist_item(struct mansession *s, const char *id_text, struct conference_bridge *bridge, struct conference_bridge_user *participant)
+{
+	astman_append(s,
+		"Event: ConfbridgeList\r\n"
+		"%s"
+		"Conference: %s\r\n"
+		"CallerIDNum: %s\r\n"
+		"CallerIDName: %s\r\n"
+		"Channel: %s\r\n"
+		"Admin: %s\r\n"
+		"MarkedUser: %s\r\n"
+		"\r\n",
+		id_text,
+		bridge->name,
+		S_COR(ast_channel_caller(participant->chan)->id.number.valid, ast_channel_caller(participant->chan)->id.number.str, "<unknown>"),
+		S_COR(ast_channel_caller(participant->chan)->id.name.valid, ast_channel_caller(participant->chan)->id.name.str, "<no name>"),
+		ast_channel_name(participant->chan),
+		ast_test_flag(&participant->u_profile, USER_OPT_ADMIN) ? "Yes" : "No",
+		ast_test_flag(&participant->u_profile, USER_OPT_MARKEDUSER) ? "Yes" : "No");
+}
+
 static int action_confbridgelist(struct mansession *s, const struct message *m)
 {
 	const char *actionid = astman_get_header(m, "ActionID");
@@ -2473,23 +2530,11 @@
 	ao2_lock(bridge);
 	AST_LIST_TRAVERSE(&bridge->active_list, participant, list) {
 		total++;
-		astman_append(s,
-			"Event: ConfbridgeList\r\n"
-			"%s"
-			"Conference: %s\r\n"
-			"CallerIDNum: %s\r\n"
-			"CallerIDName: %s\r\n"
-			"Channel: %s\r\n"
-			"Admin: %s\r\n"
-			"MarkedUser: %s\r\n"
-			"\r\n",
-			id_text,
-			bridge->name,
-			S_COR(ast_channel_caller(participant->chan)->id.number.valid, ast_channel_caller(participant->chan)->id.number.str, "<unknown>"),
-			S_COR(ast_channel_caller(participant->chan)->id.name.valid, ast_channel_caller(participant->chan)->id.name.str, "<no name>"),
-			ast_channel_name(participant->chan),
-			ast_test_flag(&participant->u_profile, USER_OPT_ADMIN) ? "Yes" : "No",
-			ast_test_flag(&participant->u_profile, USER_OPT_MARKEDUSER) ? "Yes" : "No");
+		action_confbridgelist_item(s, id_text, bridge, participant);
+	}
+	AST_LIST_TRAVERSE(&bridge->waiting_list, participant, list) {
+		total++;
+		action_confbridgelist_item(s, id_text, bridge, participant);
 	}
 	ao2_unlock(bridge);
 	ao2_ref(bridge, -1);
@@ -2539,7 +2584,7 @@
 		"\r\n",
 		id_text,
 		bridge->name,
-		bridge->activeusers,
+		bridge->activeusers + bridge->waitingusers,
 		bridge->markedusers,
 		bridge->locked ? "Yes" : "No"); 
 		ao2_unlock(bridge);

Modified: team/dlee/stasis-http/apps/app_controlplayback.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/stasis-http/apps/app_controlplayback.c?view=diff&rev=380385&r1=380384&r2=380385
==============================================================================
--- team/dlee/stasis-http/apps/app_controlplayback.c (original)
+++ team/dlee/stasis-http/apps/app_controlplayback.c Tue Jan 29 12:00:44 2013
@@ -36,6 +36,9 @@
 #include "asterisk/pbx.h"
 #include "asterisk/app.h"
 #include "asterisk/module.h"
+#include "asterisk/manager.h"
+#include "asterisk/utils.h"
+#include "asterisk/astobj2.h"
 
 /*** DOCUMENTATION
 	<application name="ControlPlayback" language="en_US">
@@ -82,6 +85,7 @@
 					<para>Contains the status of the attempt as a text string</para>
 					<value name="SUCCESS" />
 					<value name="USERSTOPPED" />
+					<value name="REMOTESTOPPED" />
 					<value name="ERROR" />
 				</variable>
 				<variable name="CPLAYBACKOFFSET">
@@ -95,6 +99,69 @@
 			</variablelist>
 		</description>
 	</application>
+	<manager name="ControlPlayback" language="en_US">
+		<synopsis>
+			Control the playback of a file being played to a channel.
+		</synopsis>
+		<syntax>
+			<xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
+			<parameter name="Channel" required="true">
+				<para>The name of the channel that currently has a file being played back to it.</para>
+			</parameter>
+			<parameter name="Control" required="true">
+				<enumlist>
+					<enum  name="stop">
+						<para>Stop the playback operation.</para>
+					</enum>
+					<enum name="forward">
+						<para>Move the current position in the media forward. The amount
+						of time that the stream moves forward is determined by the
+						<replaceable>skipms</replaceable> value passed to the application
+						that initiated the playback.</para>
+						<note>
+							<para>The default skipms value is <literal>3000</literal> ms.</para>
+						</note>
+					</enum>
+					<enum name="reverse">
+						<para>Move the current position in the media backward. The amount
+						of time that the stream moves backward is determined by the
+						<replaceable>skipms</replaceable> value passed to the application
+						that initiated the playback.</para>
+						<note>
+							<para>The default skipms value is <literal>3000</literal> ms.</para>
+						</note>
+					</enum>
+					<enum name="pause">
+						<para>Pause/unpause the playback operation, if supported.
+						If not supported, stop the playback.</para>
+					</enum>
+					<enum name="restart">
+						<para>Restart the playback operation, if supported.
+						If not supported, stop the playback.</para>
+					</enum>
+				</enumlist>
+			</parameter>
+		</syntax>
+		<description>
+			<para>Control the operation of a media file being played back to a channel.
+			Note that this AMI action does not initiate playback of media to channel, but
+			rather controls the operation of a media operation that was already initiated
+			on the channel.</para>
+			<note>
+				<para>The <literal>pause</literal> and <literal>restart</literal>
+				<replaceable>Control</replaceable> options will stop a playback
+				operation if that operation was not initiated from the
+				<replaceable>ControlPlayback</replaceable> application or the
+				<replaceable>control stream file</replaceable> AGI command.</para>
+			</note>
+		</description>
+		<see-also>
+			<ref type="application">Playback</ref>
+			<ref type="application">ControlPlayback</ref>
+			<ref type="agi">stream file</ref>
+			<ref type="agi">control stream file</ref>
+		</see-also>
+	</manager>
  ***/
 static const char app[] = "ControlPlayback";
 
@@ -201,6 +268,9 @@
 		snprintf(stopkeybuf, sizeof(stopkeybuf), "%c", res);
 		pbx_builtin_setvar_helper(chan, "CPLAYBACKSTOPKEY", stopkeybuf);
 		res = 0;
+	} else if (res > 0 && res == AST_CONTROL_STREAM_STOP) {
+		pbx_builtin_setvar_helper(chan, "CPLAYBACKSTATUS", "REMOTESTOPPED");
+		res = 0;
 	} else {
 		if (res < 0) {
 			res = 0;
@@ -215,16 +285,67 @@
 	return res;
 }
 
+static int controlplayback_manager(struct mansession *s, const struct message *m)
+{
+	const char *channel_name = astman_get_header(m, "Channel");
+	const char *control_type = astman_get_header(m, "Control");
+	struct ast_channel *chan;
+
+	if (ast_strlen_zero(channel_name)) {
+		astman_send_error(s, m, "Channel not specified");
+		return 0;
+	}
+
+	if (ast_strlen_zero(control_type)) {
+		astman_send_error(s, m, "Control not specified");
+		return 0;
+	}
+
+	chan = ast_channel_get_by_name(channel_name);
+	if (!chan) {
+		astman_send_error(s, m, "No such channel");
+		return 0;
+	}
+
+	if (!strcasecmp(control_type, "stop")) {
+		ast_queue_control(chan, AST_CONTROL_STREAM_STOP);
+	} else if (!strcasecmp(control_type, "forward")) {
+		ast_queue_control(chan, AST_CONTROL_STREAM_FORWARD);
+	} else if (!strcasecmp(control_type, "reverse")) {
+		ast_queue_control(chan, AST_CONTROL_STREAM_REVERSE);
+	} else if (!strcasecmp(control_type, "pause")) {
+		ast_queue_control(chan, AST_CONTROL_STREAM_SUSPEND);
+	} else if (!strcasecmp(control_type, "restart")) {
+		ast_queue_control(chan, AST_CONTROL_STREAM_RESTART);
+	} else {
+		astman_send_error(s, m, "Unknown control type");
+		chan = ast_channel_unref(chan);
+		return 0;
+	}
+
+	chan = ast_channel_unref(chan);
+	astman_send_ack(s, m, NULL);
+	return 0;
+}
+
 static int unload_module(void)
 {
-	int res;
-	res = ast_unregister_application(app);
+	int res = 0;
+
+	res |= ast_unregister_application(app);
+	res |= ast_manager_unregister("ControlPlayback");
+
 	return res;
 }
 
 static int load_module(void)
 {
-	return ast_register_application_xml(app, controlplayback_exec);
+	int res = 0;
+
+	res |= ast_register_application_xml(app, controlplayback_exec);
+	res |= ast_manager_register_xml("ControlPlayback", EVENT_FLAG_CALL, controlplayback_manager);
+
+	return res;
 }
 
 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Control Playback Application");

Modified: team/dlee/stasis-http/apps/app_meetme.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/stasis-http/apps/app_meetme.c?view=diff&rev=380385&r1=380384&r2=380385
==============================================================================
--- team/dlee/stasis-http/apps/app_meetme.c (original)
+++ team/dlee/stasis-http/apps/app_meetme.c Tue Jan 29 12:00:44 2013
@@ -2375,6 +2375,428 @@
 	return 0;
 }
 
+enum menu_modes {
+	MENU_DISABLED = 0,
+	MENU_NORMAL,
+	MENU_ADMIN,
+	MENU_ADMIN_EXTENDED,
+};
+
+/*! \internal
+ * \brief Processes menu options for the standard menu (accessible through the 's' option for app_meetme)
+ *
+ * \param menu_mode a pointer to the currently active menu_mode.
+ * \param dtmf a pointer to the dtmf value currently being processed against the menu.
+ * \param conf the active conference for which the user has called the menu from.
+ * \param confflags flags used by conf for various options
+ * \param chan ast_channel belonging to the user who called the menu
+ * \param user which meetme conference user invoked the menu
+ */
+static void meetme_menu_normal(enum menu_modes *menu_mode, int *dtmf, struct ast_conference *conf, struct ast_flags64 *confflags, struct ast_channel *chan, struct ast_conf_user *user)
+{
+	switch (*dtmf) {
+	case '1': /* Un/Mute */
+		*menu_mode = MENU_DISABLED;
+
+		/* user can only toggle the self-muted state */
+		user->adminflags ^= ADMINFLAG_SELFMUTED;
+
+		/* they can't override the admin mute state */
+		if (ast_test_flag64(confflags, CONFFLAG_MONITOR) || (user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED))) {
+			if (!ast_streamfile(chan, "conf-muted", ast_channel_language(chan))) {
+				ast_waitstream(chan, "");
+			}
+		} else {
+			if (!ast_streamfile(chan, "conf-unmuted", ast_channel_language(chan))) {
+				ast_waitstream(chan, "");
+			}
+		}
+		break;
+
+	case '2':
+		*menu_mode = MENU_DISABLED;
+		if (user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED)) {
+			user->adminflags |= ADMINFLAG_T_REQUEST;
+		}
+
+		if (user->adminflags & ADMINFLAG_T_REQUEST) {
+			if (!ast_streamfile(chan, "beep", ast_channel_language(chan))) {
+				ast_waitstream(chan, "");
+			}
+		}
+		break;
+
+	case '4':
+		tweak_listen_volume(user, VOL_DOWN);
+		break;
+	case '5':
+		/* Extend RT conference */
+		if (rt_schedule) {
+			rt_extend_conf(conf->confno);
+		}
+		*menu_mode = MENU_DISABLED;
+		break;
+
+	case '6':
+		tweak_listen_volume(user, VOL_UP);
+		break;
+
+	case '7':
+		tweak_talk_volume(user, VOL_DOWN);
+		break;
+
+	case '8':
+		*menu_mode = MENU_DISABLED;
+		break;
+
+	case '9':
+		tweak_talk_volume(user, VOL_UP);
+		break;
+
+	default:
+		*menu_mode = MENU_DISABLED;
+		if (!ast_streamfile(chan, "conf-errormenu", ast_channel_language(chan))) {
+			ast_waitstream(chan, "");
+		}
+		break;
+	}
+}
+
+/*! \internal
+ * \brief Processes menu options for the adminstrator menu (accessible through the 's' option for app_meetme)
+ *
+ * \param menu_mode a pointer to the currently active menu_mode.
+ * \param dtmf a pointer to the dtmf value currently being processed against the menu.
+ * \param conf the active conference for which the user has called the menu from.
+ * \param confflags flags used by conf for various options
+ * \param chan ast_channel belonging to the user who called the menu
+ * \param user which meetme conference user invoked the menu
+ */
+static void meetme_menu_admin(enum menu_modes *menu_mode, int *dtmf, struct ast_conference *conf, struct ast_flags64 *confflags, struct ast_channel *chan, struct ast_conf_user *user)
+{
+	switch(*dtmf) {
+	case '1': /* Un/Mute */
+		*menu_mode = MENU_DISABLED;
+		/* for admin, change both admin and use flags */
+		if (user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED)) {
+			user->adminflags &= ~(ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED);
+		} else {
+			user->adminflags |= (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED);
+		}
+
+		if (ast_test_flag64(confflags, CONFFLAG_MONITOR) || (user->adminflags & (ADMINFLAG_MUTED | ADMINFLAG_SELFMUTED))) {
+			if (!ast_streamfile(chan, "conf-muted", ast_channel_language(chan))) {
+				ast_waitstream(chan, "");
+			}
+		} else {
+			if (!ast_streamfile(chan, "conf-unmuted", ast_channel_language(chan))) {
+				ast_waitstream(chan, "");
+			}
+		}
+		break;
+
+	case '2': /* Un/Lock the Conference */
+		*menu_mode = MENU_DISABLED;
+		if (conf->locked) {
+			conf->locked = 0;
+			if (!ast_streamfile(chan, "conf-unlockednow", ast_channel_language(chan))) {
+				ast_waitstream(chan, "");
+			}
+		} else {
+			conf->locked = 1;
+			if (!ast_streamfile(chan, "conf-lockednow", ast_channel_language(chan))) {
+				ast_waitstream(chan, "");
+			}
+		}
+		break;
+
+	case '3': /* Eject last user */
+	{
+		struct ast_conf_user *usr = NULL;
+		int max_no = 0;
+		ao2_callback(conf->usercontainer, OBJ_NODATA, user_max_cmp, &max_no);
+		*menu_mode = MENU_DISABLED;
+		usr = ao2_find(conf->usercontainer, &max_no, 0);
+		if ((ast_channel_name(usr->chan) == ast_channel_name(chan)) || ast_test_flag64(&usr->userflags, CONFFLAG_ADMIN)) {
+			if (!ast_streamfile(chan, "conf-errormenu", ast_channel_language(chan))) {
+				ast_waitstream(chan, "");
+			}
+		} else {
+			usr->adminflags |= ADMINFLAG_KICKME;
+		}
+		ao2_ref(usr, -1);
+		ast_stopstream(chan);
+		break;
+	}
+
+	case '4':
+		tweak_listen_volume(user, VOL_DOWN);
+		break;
+
+	case '5':
+		/* Extend RT conference */
+		if (rt_schedule) {
+			if (!rt_extend_conf(conf->confno)) {
+				if (!ast_streamfile(chan, "conf-extended", ast_channel_language(chan))) {
+					ast_waitstream(chan, "");
+				}
+			} else {
+				if (!ast_streamfile(chan, "conf-nonextended", ast_channel_language(chan))) {
+					ast_waitstream(chan, "");
+				}
+			}
+			ast_stopstream(chan);
+		}
+		*menu_mode = MENU_DISABLED;
+		break;
+
+	case '6':
+		tweak_listen_volume(user, VOL_UP);
+		break;
+
+	case '7':
+		tweak_talk_volume(user, VOL_DOWN);
+		break;
+
+	case '8':
+		if (!ast_streamfile(chan, "conf-adminmenu-menu8", ast_channel_language(chan))) {
+			/* If the user provides DTMF while playing the sound, we want to drop right into the extended menu function with new DTMF once we get out of here. */
+			*dtmf = ast_waitstream(chan, AST_DIGIT_ANY);
+			ast_stopstream(chan);
+		}
+		*menu_mode = MENU_ADMIN_EXTENDED;
+		break;
+
+	case '9':
+		tweak_talk_volume(user, VOL_UP);
+		break;
+	default:
+		menu_mode = MENU_DISABLED;
+		/* Play an error message! */
+		if (!ast_streamfile(chan, "conf-errormenu", ast_channel_language(chan))) {
+			ast_waitstream(chan, "");
+		}
+		break;
+	}
+
+}
+
+/*! \internal
+ * \brief Processes menu options for the extended administrator menu (accessible through option 8 on the administrator menu)
+ *
+ * \param menu_mode a pointer to the currently active menu_mode.
+ * \param dtmf a pointer to the dtmf value currently being processed against the menu.
+ * \param conf the active conference for which the user has called the menu from.
+ * \param confflags flags used by conf for various options
+ * \param chan ast_channel belonging to the user who called the menu
+ * \param user which meetme conference user invoked the menu
+ * \param recordingtmp character buffer which may hold the name of the conference recording file
+ * \param dahdic dahdi configuration info used by the main conference loop
+ */

[... 6303 lines stripped ...]



More information about the asterisk-commits mailing list