[asterisk-commits] mjordan: branch mjordan/longcat r378644 - in /team/mjordan/longcat: apps/ inc...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Sun Jan 6 19:51:38 CST 2013


Author: mjordan
Date: Sun Jan  6 19:51:32 2013
New Revision: 378644

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=378644
Log:
Add an AMI command to control the playback

As Richard pointed out, this is all that's needed. The AGI command
should just be removed - that keeps the modifications in the train
wreck that is res_agi's handling of multiple AGI variants to a minimum.

Modified:
    team/mjordan/longcat/apps/app_controlplayback.c
    team/mjordan/longcat/apps/app_playback.c
    team/mjordan/longcat/include/asterisk/frame.h
    team/mjordan/longcat/res/res_agi.c

Modified: team/mjordan/longcat/apps/app_controlplayback.c
URL: http://svnview.digium.com/svn/asterisk/team/mjordan/longcat/apps/app_controlplayback.c?view=diff&rev=378644&r1=378643&r2=378644
==============================================================================
--- team/mjordan/longcat/apps/app_controlplayback.c (original)
+++ team/mjordan/longcat/apps/app_controlplayback.c Sun Jan  6 19:51:32 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,60 @@
 			</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.</para>
+					</enum>
+					<enum name="restart">
+						<para>Restart the playback operation.</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>
+		</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 +259,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 +276,80 @@
 	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;
+	}
+
+	/* At least make sure that before we send the control signal there is
+	 * something streamed to the channel. The playback could still end before
+	 * the frame is serviced, but it's something.
+	 */
+	ast_channel_lock(chan);
+	if (!ast_channel_stream(chan)) {
+		ast_channel_unlock(chan);
+		chan = ast_channel_unref(chan);
+		astman_send_error(s, m, "Nothing being played back to channel");
+		return 0;
+	}
+	ast_channel_unlock(chan);
+
+	if (!strcmp(control_type, "stop")) {
+		ast_indicate(chan, AST_CONTROL_STREAM_STOP);
+	} else if (!strcmp(control_type, "forward")) {
+		ast_indicate(chan, AST_CONTROL_STREAM_FORWARD);
+	} else if (!strcmp(control_type, "reverse")) {
+		ast_indicate(chan, AST_CONTROL_STREAM_REVERSE);
+	} else if (!strcmp(control_type, "pause")) {
+		ast_indicate(chan, AST_CONTROL_STREAM_SUSPEND);
+	} else if (!strcmp(control_type, "restart")) {
+		ast_indicate(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/mjordan/longcat/apps/app_playback.c
URL: http://svnview.digium.com/svn/asterisk/team/mjordan/longcat/apps/app_playback.c?view=diff&rev=378644&r1=378643&r2=378644
==============================================================================
--- team/mjordan/longcat/apps/app_playback.c (original)
+++ team/mjordan/longcat/apps/app_playback.c Sun Jan  6 19:51:32 2013
@@ -82,6 +82,14 @@
 			<para>See Also: Background (application) -- for playing sound files that are interruptible</para>
 			<para>WaitExten (application) -- wait for digits from caller, optionally play music on hold</para>
 		</description>
+		<see-also>
+			<ref type="application">Background</ref>
+			<ref type="application">WaitExten</ref>
+			<ref type="application">ControlPlayback</ref>
+			<ref type="agi">stream file</ref>
+			<ref type="agi">control stream file</ref>
+			<ref type="manager">ControlPlayback</ref>
+		</see-also>
 	</application>
  ***/
 

Modified: team/mjordan/longcat/include/asterisk/frame.h
URL: http://svnview.digium.com/svn/asterisk/team/mjordan/longcat/include/asterisk/frame.h?view=diff&rev=378644&r1=378643&r2=378644
==============================================================================
--- team/mjordan/longcat/include/asterisk/frame.h (original)
+++ team/mjordan/longcat/include/asterisk/frame.h Sun Jan  6 19:51:32 2013
@@ -267,12 +267,15 @@
 	AST_CONTROL_MCID = 31,			/*!< Indicate that the caller is being malicious. */
 	AST_CONTROL_UPDATE_RTP_PEER = 32, /*!< Interrupt the bridge and have it update the peer */
 	AST_CONTROL_PVT_CAUSE_CODE = 33, /*!< Contains an update to the protocol-specific cause-code stored for branching dials */
-	/* Control frames used to manipulate a stream on a channel */
-	AST_CONTROL_STREAM_STOP = 1000,
-	AST_CONTROL_STREAM_SUSPEND = 1001,
-	AST_CONTROL_STREAM_RESTART = 1002,
-	AST_CONTROL_STREAM_REVERSE = 1003,
-	AST_CONTROL_STREAM_FORWARD = 1004,
+
+	/* Control frames used to manipulate a stream on a channel. The values for these
+	 * must be greater than the allowed value for a 8-bit char, so that they avoid
+	 * conflicts with DTMF values. */
+	AST_CONTROL_STREAM_STOP = 1000,		/*!< Indicate to a channel in playback to stop the stream */
+	AST_CONTROL_STREAM_SUSPEND = 1001,	/*!< Indicate to a channel in playback to suspend the stream */
+	AST_CONTROL_STREAM_RESTART = 1002,	/*!< Indicate to a channel in playback to restart the stream */
+	AST_CONTROL_STREAM_REVERSE = 1003,	/*!< Indicate to a channel in playback to rewind */
+	AST_CONTROL_STREAM_FORWARD = 1004,	/*!< Indicate to a channel in playback to fast forward */
 
 };
 

Modified: team/mjordan/longcat/res/res_agi.c
URL: http://svnview.digium.com/svn/asterisk/team/mjordan/longcat/res/res_agi.c?view=diff&rev=378644&r1=378643&r2=378644
==============================================================================
--- team/mjordan/longcat/res/res_agi.c (original)
+++ team/mjordan/longcat/res/res_agi.c Sun Jan  6 19:51:32 2013
@@ -187,6 +187,24 @@
 			permitted. Returns <literal>0</literal> if playback completes without a digit
 			being pressed, or the ASCII numerical value of the digit if one was pressed,
 			or <literal>-1</literal> on error or if the channel was disconnected.</para>
+			<para>It sets the following channel variables upon completion:</para>
+			<variablelist>
+				<variable name="CPLAYBACKSTATUS">
+					<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">
+					<para>Contains the offset in ms into the file where playback
+					was at when it stopped. <literal>-1</literal> is end of file.</para>
+				</variable>
+				<variable name="CPLAYBACKSTOPKEY">
+					<para>If the playback is stopped by the user this variable contains
+					the key that was pressed.</para>
+				</variable>
+			</variablelist>
 		</description>
 	</agi>
 	<agi name="database del" language="en_US">
@@ -2040,6 +2058,9 @@
 {
 	int res = 0, skipms = 3000;
 	const char *fwd = "#", *rev = "*", *suspend = NULL, *stop = NULL;	/* Default values */
+	char stopkeybuf[2];
+	long offsetms = 0;
+	char offsetbuf[20];
 
 	if (argc < 5 || argc > 9) {
 		return RESULT_SHOWUSAGE;
@@ -2066,6 +2087,25 @@
 	}
 
 	res = ast_control_streamfile(chan, argv[3], fwd, rev, stop, suspend, NULL, skipms, NULL);
+
+	/* If we stopped on one of our stop keys, return 0  */
+	if (res > 0 && stop && strchr(stop, res)) {
+		pbx_builtin_setvar_helper(chan, "CPLAYBACKSTATUS", "USERSTOPPED");
+		snprintf(stopkeybuf, sizeof(stopkeybuf), "%c", res);
+		pbx_builtin_setvar_helper(chan, "CPLAYBACKSTOPKEY", stopkeybuf);
+	} else if (res > 0 && res == AST_CONTROL_STREAM_STOP) {
+		pbx_builtin_setvar_helper(chan, "CPLAYBACKSTATUS", "REMOTESTOPPED");
+		res = 0;
+	} else {
+		if (res < 0) {
+			pbx_builtin_setvar_helper(chan, "CPLAYBACKSTATUS", "ERROR");
+		} else {
+			pbx_builtin_setvar_helper(chan, "CPLAYBACKSTATUS", "SUCCESS");
+		}
+	}
+
+	snprintf(offsetbuf, sizeof(offsetbuf), "%ld", offsetms);
+	pbx_builtin_setvar_helper(chan, "CPLAYBACKOFFSET", offsetbuf);
 
 	ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
 




More information about the asterisk-commits mailing list