[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