fi
fi
+force=0
version=`svnversion . -n || echo hacked`
oldversion=`cat .version 2>/dev/null || echo "0"`
+grep "@SVN_VERSION@" src/include/switch_version.h && force=1
-if [ $oldversion != $version ] ; then
+if [ $oldversion != $version ] || [ $force = 1 ] ; then
cat src/include/switch_version.h.in | sed "s/@SVN_VERSION@/$version/g" > src/include/switch_version.h
echo $version > .version
make modclean
applications/mod_bridgecall
applications/mod_playback
+applications/mod_ivrtest
#applications/mod_skel
#codecs/mod_g729
codecs/mod_gsm
* @{
*/
+/*!
+ \brief Wait for DTMF digits calling a pluggable callback function when digits are collected.
+ \param session the session to read.
+ \param dtmf_collection_callback code to execute if any dtmf is dialed during the recording
+ \return SWITCH_STATUS_SUCCESS to keep the collection moving.
+*/
+SWITCH_DECLARE(switch_status) switch_ivr_collect_digits_callback(switch_core_session *session,
+ switch_dtmf_callback_function dtmf_callback,
+ void *buf,
+ unsigned int buflen);
+
+/*!
+ \brief Wait for specified number of DTMF digits, untile terminator is received or until the channel hangs up.
+ \param session the session to read.
+ \param buf strig to write to
+ \param buflen max size of buf
+ \param maxdigits max number of digits to read
+ \param terminators digits to end the collection
+ \param terminator actual digit that caused the collection to end (if any)
+ \return SWITCH_STATUS_SUCCESS to keep the collection moving.
+*/
+SWITCH_DECLARE(switch_status) switch_ivr_collect_digits_count(switch_core_session *session,
+ char *buf,
+ unsigned int buflen,
+ int maxdigits,
+ const char *terminators,
+ char *terminator);
+
/*!
\brief play a file from the disk to the session
\param session the session to play the file too
\param timer_name the name of a timer to use input will be absorbed (NULL to time off the session input).
\param dtmf_callback code to execute if any dtmf is dialed during the playback
\return SWITCH_STATUS_SUCCESS if all is well
+ \note passing a NULL dtmf_callback nad a not NULL buf indicates to copy any dtmf to buf and stop playback.
*/
SWITCH_DECLARE(switch_status) switch_ivr_play_file(switch_core_session *session,
char *file,
char *timer_name,
- switch_dtmf_callback_function dtmf_callback);
+ switch_dtmf_callback_function dtmf_callback,
+ void *buf,
+ unsigned int buflen);
\param file the path to the file
\param dtmf_callback code to execute if any dtmf is dialed during the recording
\return SWITCH_STATUS_SUCCESS if all is well
+ \note passing a NULL dtmf_callback nad a not NULL buf indicates to copy any dtmf to buf and stop recording.
*/
SWITCH_DECLARE(switch_status) switch_ivr_record_file(switch_core_session *session,
char *file,
- switch_dtmf_callback_function dtmf_callback);
-
+ switch_dtmf_callback_function dtmf_callback,
+ void *buf,
+ unsigned int buflen);
+
+
/** @} */
#ifdef __cplusplus
SWITCH_STATUS_RESAMPLE - An indication that a resample has occured
SWITCH_STATUS_GENERR - A general Error
SWITCH_STATUS_INUSE - An indication that requested resource is in use
+ SWITCH_STATUS_BREAK - A non-fatal break of an operation
</pre>
*/
typedef enum {
SWITCH_STATUS_NOOP,
SWITCH_STATUS_RESAMPLE,
SWITCH_STATUS_GENERR,
- SWITCH_STATUS_INUSE
+ SWITCH_STATUS_INUSE,
+ SWITCH_STATUS_BREAK,
} switch_status;
/*!
typedef switch_status (*switch_waitfor_write_hook)(switch_core_session *, int, int);
typedef switch_status (*switch_send_dtmf_hook)(switch_core_session *, char *);
typedef switch_status (*switch_api_function)(char *in, char *out, size_t outlen);
-typedef switch_status (*switch_dtmf_callback_function)(switch_core_session *session, char *dtmf);
+typedef switch_status (*switch_dtmf_callback_function)(switch_core_session *session, char *dtmf, void *buf, unsigned int buflen);
/* things we don't deserve to know about */
--- /dev/null
+/*
+ * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ * Copyright (C) 2005/2006, Anthony Minessale II <anthmct@yahoo.com>
+ *
+ * Version: MPL 1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
+ *
+ * The Initial Developer of the Original Code is
+ * Anthony Minessale II <anthmct@yahoo.com>
+ * Portions created by the Initial Developer are Copyright (C)
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Anthony Minessale II <anthmct@yahoo.com>
+ *
+ *
+ * mod_ivrtest.c -- Raw Audio File Streaming Application Module
+ *
+ */
+#include <switch.h>
+#include <switch_ivr.h>
+
+
+
+static const char modname[] = "mod_ivrtest";
+
+
+/*
+ dtmf handler function you can hook up to be executed when a digit is dialed during playback
+ if you return anything but SWITCH_STATUS_SUCCESS the playback will stop.
+*/
+static switch_status on_dtmf(switch_core_session *session, char *dtmf, void *buf, unsigned int buflen)
+{
+ switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Digits %s\n", dtmf);
+
+ switch_copy_string((char *)buf, dtmf, buflen);
+ return SWITCH_STATUS_BREAK;
+
+}
+
+static void ivrtest_function(switch_core_session *session, char *data)
+{
+ switch_channel *channel;
+ switch_status status = SWITCH_STATUS_SUCCESS;
+ char buf[10] = "";
+ char term;
+
+ channel = switch_core_session_get_channel(session);
+ assert(channel != NULL);
+
+ switch_channel_answer(channel);
+
+
+ while (switch_channel_get_state(channel) == CS_EXECUTE) {
+ memset(buf, 0, sizeof(buf));
+ switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Enter up to 10 digits, press # to terminate, * to hangup\n");
+
+ if (data) {
+ /* you could have passed NULL instead of on_dtmf to get this exact behaviour (copy the digits to buf and stop playing)
+ but you may want to pass the function if you have something cooler to do...
+ */
+ status = switch_ivr_play_file(session, data, NULL, on_dtmf, buf, sizeof(buf));
+
+ if (status != SWITCH_STATUS_SUCCESS && status != SWITCH_STATUS_BREAK) {
+ switch_channel_hangup(channel);
+ break;
+ }
+ }
+
+ if (switch_ivr_collect_digits_count(session, buf, sizeof(buf), 10, "#*", &term) != SWITCH_STATUS_SUCCESS) {
+ switch_channel_hangup(channel);
+ break;
+ }
+
+ if (term && term == '*') {
+ break;
+ }
+
+ switch_console_printf(SWITCH_CHANNEL_CONSOLE, "You Dialed [%s]\n", buf);
+ }
+
+}
+
+
+static const switch_application_interface ivrtest_application_interface = {
+ /*.interface_name */ "ivrtest",
+ /*.application_function */ ivrtest_function
+};
+
+static const switch_loadable_module_interface mod_ivrtest_module_interface = {
+ /*.module_name = */ modname,
+ /*.endpoint_interface = */ NULL,
+ /*.timer_interface = */ NULL,
+ /*.dialplan_interface = */ NULL,
+ /*.codec_interface = */ NULL,
+ /*.application_interface */ &ivrtest_application_interface
+};
+
+SWITCH_MOD_DECLARE(switch_status) switch_module_load(const switch_loadable_module_interface **interface, char *filename)
+{
+
+ /* connect my internal structure to the blank pointer passed to me */
+ *interface = &mod_ivrtest_module_interface;
+
+
+ /* indicate that the module should continue to be loaded */
+ return SWITCH_STATUS_SUCCESS;
+}
+
+/* 'switch_module_runtime' will start up in a thread by itself just by having it exist
+ if it returns anything but SWITCH_STATUS_TERM it will be called again automaticly
+*/
+
+
+//switch_status switch_module_runtime(void)
--- /dev/null
+<?xml version="1.0" encoding="Windows-1252"?>\r
+<VisualStudioProject\r
+ ProjectType="Visual C++"\r
+ Version="8.00"\r
+ Name="mod_ivrtest"\r
+ ProjectGUID="{78100236-7CEA-4948-96CC-E8ED3160329C}"\r
+ RootNamespace="mod_ivrtest"\r
+ Keyword="Win32Proj"\r
+ >\r
+ <Platforms>\r
+ <Platform\r
+ Name="Win32"\r
+ />\r
+ </Platforms>\r
+ <ToolFiles>\r
+ </ToolFiles>\r
+ <Configurations>\r
+ <Configuration\r
+ Name="Debug|Win32"\r
+ OutputDirectory="Debug"\r
+ IntermediateDirectory="Debug"\r
+ ConfigurationType="2"\r
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
+ CharacterSet="2"\r
+ >\r
+ <Tool\r
+ Name="VCPreBuildEventTool"\r
+ />\r
+ <Tool\r
+ Name="VCCustomBuildTool"\r
+ />\r
+ <Tool\r
+ Name="VCXMLDataGeneratorTool"\r
+ />\r
+ <Tool\r
+ Name="VCWebServiceProxyGeneratorTool"\r
+ />\r
+ <Tool\r
+ Name="VCMIDLTool"\r
+ />\r
+ <Tool\r
+ Name="VCCLCompilerTool"\r
+ Optimization="0"\r
+ AdditionalIncludeDirectories=""$(InputDir)..\..\..\include";"$(InputDir)include";"$(InputDir)..\..\..\..\libs\include""\r
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;MOD_EXPORTS"\r
+ MinimalRebuild="true"\r
+ BasicRuntimeChecks="3"\r
+ RuntimeLibrary="1"\r
+ UsePrecompiledHeader="0"\r
+ WarningLevel="3"\r
+ Detect64BitPortabilityProblems="true"\r
+ DebugInformationFormat="4"\r
+ />\r
+ <Tool\r
+ Name="VCManagedResourceCompilerTool"\r
+ />\r
+ <Tool\r
+ Name="VCResourceCompilerTool"\r
+ />\r
+ <Tool\r
+ Name="VCPreLinkEventTool"\r
+ />\r
+ <Tool\r
+ Name="VCLinkerTool"\r
+ OutputFile="..\..\..\..\w32\vsnet\$(OutDir)/mod/mod_ivrtest.dll"\r
+ LinkIncremental="2"\r
+ AdditionalLibraryDirectories="$(InputDir)..\..\..\libs\apr\Debug"\r
+ GenerateDebugInformation="true"\r
+ ProgramDatabaseFile="$(OutDir)/mod_ivrtest.pdb"\r
+ SubSystem="2"\r
+ ImportLibrary="$(OutDir)/mod_ivrtest.lib"\r
+ TargetMachine="1"\r
+ />\r
+ <Tool\r
+ Name="VCALinkTool"\r
+ />\r
+ <Tool\r
+ Name="VCManifestTool"\r
+ />\r
+ <Tool\r
+ Name="VCXDCMakeTool"\r
+ />\r
+ <Tool\r
+ Name="VCBscMakeTool"\r
+ />\r
+ <Tool\r
+ Name="VCFxCopTool"\r
+ />\r
+ <Tool\r
+ Name="VCAppVerifierTool"\r
+ />\r
+ <Tool\r
+ Name="VCWebDeploymentTool"\r
+ />\r
+ <Tool\r
+ Name="VCPostBuildEventTool"\r
+ />\r
+ </Configuration>\r
+ <Configuration\r
+ Name="Release|Win32"\r
+ OutputDirectory="Release"\r
+ IntermediateDirectory="Release"\r
+ ConfigurationType="2"\r
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"\r
+ CharacterSet="2"\r
+ >\r
+ <Tool\r
+ Name="VCPreBuildEventTool"\r
+ />\r
+ <Tool\r
+ Name="VCCustomBuildTool"\r
+ />\r
+ <Tool\r
+ Name="VCXMLDataGeneratorTool"\r
+ />\r
+ <Tool\r
+ Name="VCWebServiceProxyGeneratorTool"\r
+ />\r
+ <Tool\r
+ Name="VCMIDLTool"\r
+ />\r
+ <Tool\r
+ Name="VCCLCompilerTool"\r
+ AdditionalIncludeDirectories=""$(InputDir)..\..\..\include";"$(InputDir)include";"$(InputDir)..\..\..\..\libs\include""\r
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_USRDLL;MOD_EXPORTS"\r
+ RuntimeLibrary="0"\r
+ UsePrecompiledHeader="0"\r
+ WarningLevel="3"\r
+ Detect64BitPortabilityProblems="true"\r
+ DebugInformationFormat="3"\r
+ />\r
+ <Tool\r
+ Name="VCManagedResourceCompilerTool"\r
+ />\r
+ <Tool\r
+ Name="VCResourceCompilerTool"\r
+ />\r
+ <Tool\r
+ Name="VCPreLinkEventTool"\r
+ />\r
+ <Tool\r
+ Name="VCLinkerTool"\r
+ OutputFile="..\..\..\..\w32\vsnet\$(OutDir)/mod/mod_ivrtest.dll"\r
+ LinkIncremental="1"\r
+ AdditionalLibraryDirectories=""$(InputDir)..\..\..\libs\apr\Release""\r
+ GenerateDebugInformation="true"\r
+ SubSystem="2"\r
+ OptimizeReferences="2"\r
+ EnableCOMDATFolding="2"\r
+ ImportLibrary="$(OutDir)/mod_ivrtest.lib"\r
+ TargetMachine="1"\r
+ />\r
+ <Tool\r
+ Name="VCALinkTool"\r
+ />\r
+ <Tool\r
+ Name="VCManifestTool"\r
+ />\r
+ <Tool\r
+ Name="VCXDCMakeTool"\r
+ />\r
+ <Tool\r
+ Name="VCBscMakeTool"\r
+ />\r
+ <Tool\r
+ Name="VCFxCopTool"\r
+ />\r
+ <Tool\r
+ Name="VCAppVerifierTool"\r
+ />\r
+ <Tool\r
+ Name="VCWebDeploymentTool"\r
+ />\r
+ <Tool\r
+ Name="VCPostBuildEventTool"\r
+ />\r
+ </Configuration>\r
+ </Configurations>\r
+ <References>\r
+ </References>\r
+ <Files>\r
+ <Filter\r
+ Name="Source Files"\r
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"\r
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"\r
+ >\r
+ <File\r
+ RelativePath=".\mod_ivrtest.c"\r
+ >\r
+ </File>\r
+ </Filter>\r
+ <Filter\r
+ Name="Header Files"\r
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"\r
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"\r
+ >\r
+ </Filter>\r
+ <Filter\r
+ Name="Resource Files"\r
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"\r
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"\r
+ >\r
+ </Filter>\r
+ </Files>\r
+ <Globals>\r
+ </Globals>\r
+</VisualStudioProject>\r
dtmf handler function you can hook up to be executed when a digit is dialed during playback
if you return anything but SWITCH_STATUS_SUCCESS the playback will stop.
*/
-static switch_status on_dtmf(switch_core_session *session, char *dtmf)
+static switch_status on_dtmf(switch_core_session *session, char *dtmf, void *buf, unsigned int buflen)
{
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "Digits %s\n", dtmf);
}
-void playback_function(switch_core_session *session, char *data)
+static void playback_function(switch_core_session *session, char *data)
{
switch_channel *channel;
char *timer_name = NULL;
channel = switch_core_session_get_channel(session);
assert(channel != NULL);
- if (switch_ivr_play_file(session, file_name, timer_name, on_dtmf) != SWITCH_STATUS_SUCCESS) {
+ if (switch_ivr_play_file(session, file_name, timer_name, on_dtmf, NULL, 0) != SWITCH_STATUS_SUCCESS) {
switch_channel_hangup(channel);
}
}
-void record_function(switch_core_session *session, char *data)
+static void record_function(switch_core_session *session, char *data)
{
switch_channel *channel;
channel = switch_core_session_get_channel(session);
assert(channel != NULL);
- if (switch_ivr_record_file(session, data, on_dtmf) != SWITCH_STATUS_SUCCESS) {
+ if (switch_ivr_record_file(session, data, on_dtmf, NULL, 0) != SWITCH_STATUS_SUCCESS) {
switch_channel_hangup(channel);
}
if ((data = strchr(app, ' '))) {
*data = '\0';
data++;
- } else {
- switch_console_printf(SWITCH_CHANNEL_CONSOLE, "invalid extension on line %d\n", cfg.lineno);
- continue;
- }
-
+ }
if (!extension) {
if (!
} else {
ready = 0;
}
+ } else {
+ ready = 0;
}
/* TBD (Lots! there are not very many functions in here lol) */
+SWITCH_DECLARE(switch_status) switch_ivr_collect_digits_callback(switch_core_session *session,
+ switch_dtmf_callback_function dtmf_callback,
+ void *buf,
+ unsigned int buflen)
+{
+ switch_channel *channel;
+ switch_status status = SWITCH_STATUS_SUCCESS;
+
+ channel = switch_core_session_get_channel(session);
+ assert(channel != NULL);
+
+ if (!dtmf_callback) {
+ return SWITCH_STATUS_GENERR;
+ }
+
+ while (switch_channel_get_state(channel) == CS_EXECUTE) {
+ switch_frame *read_frame;
+ char dtmf[128];
+
+ if (switch_channel_has_dtmf(channel)) {
+ switch_channel_dequeue_dtmf(channel, dtmf, sizeof(dtmf));
+ status = dtmf_callback(session, dtmf, buf, buflen);
+ }
+
+ if (status != SWITCH_STATUS_SUCCESS) {
+ break;
+ }
+
+ if (switch_core_session_read_frame(session, &read_frame, -1, 0) != SWITCH_STATUS_SUCCESS) {
+ break;
+ }
+ }
+
+ return status;
+}
+
+
+SWITCH_DECLARE(switch_status) switch_ivr_collect_digits_count(switch_core_session *session,
+ char *buf,
+ unsigned int buflen,
+ int maxdigits,
+ const char *terminators,
+ char *terminator)
+{
+ int i = 0, x = strlen(buf);
+ switch_channel *channel;
+ switch_status status = SWITCH_STATUS_SUCCESS;
+
+ channel = switch_core_session_get_channel(session);
+ assert(channel != NULL);
+
+ *terminator = '\0';
+ while (switch_channel_get_state(channel) == CS_EXECUTE) {
+ switch_frame *read_frame;
+
+ if (switch_channel_has_dtmf(channel)) {
+ char dtmf[128];
+ switch_channel_dequeue_dtmf(channel, dtmf, sizeof(dtmf));
+
+ for(i =0 ; i < strlen(dtmf); i++) {
+
+ if (strchr(terminators, dtmf[i])) {
+ *terminator = dtmf[i];
+ return SWITCH_STATUS_SUCCESS;
+ }
+
+ buf[x++] = dtmf[i];
+ buf[x] = '\0';
+ if (x >= buflen || x >= maxdigits) {
+ return SWITCH_STATUS_SUCCESS;
+ }
+ }
+ }
+
+ if ((status = switch_core_session_read_frame(session, &read_frame, -1, 0)) != SWITCH_STATUS_SUCCESS) {
+ break;
+ }
+ }
+
+ return status;
+}
+
+
+
SWITCH_DECLARE(switch_status) switch_ivr_record_file(switch_core_session *session,
char *file,
- switch_dtmf_callback_function dtmf_callback)
+ switch_dtmf_callback_function dtmf_callback,
+ void *buf,
+ unsigned int buflen)
{
switch_channel *channel;
char dtmf[128];
while (switch_channel_get_state(channel) == CS_EXECUTE) {
size_t len;
- if (dtmf_callback) {
+ if (dtmf_callback || buf) {
/*
dtmf handler function you can hook up to be executed when a digit is dialed during playback
if you return anything but SWITCH_STATUS_SUCCESS the playback will stop.
*/
if (switch_channel_has_dtmf(channel)) {
switch_channel_dequeue_dtmf(channel, dtmf, sizeof(dtmf));
- status = dtmf_callback(session, dtmf);
+ if (dtmf_callback) {
+ status = dtmf_callback(session, dtmf, buf, buflen);
+ } else {
+ switch_copy_string((char *)buf, dtmf, buflen);
+ status = SWITCH_STATUS_BREAK;
+ }
}
if (status != SWITCH_STATUS_SUCCESS) {
break;
}
}
-
- if (switch_core_session_read_frame(session, &read_frame, -1, 0) != SWITCH_STATUS_SUCCESS) {
+
+ if ((status = switch_core_session_read_frame(session, &read_frame, -1, 0)) != SWITCH_STATUS_SUCCESS) {
break;
}
SWITCH_DECLARE(switch_status) switch_ivr_play_file(switch_core_session *session,
char *file,
char *timer_name,
- switch_dtmf_callback_function dtmf_callback)
+ switch_dtmf_callback_function dtmf_callback,
+ void *buf,
+ unsigned int buflen)
{
switch_channel *channel;
- short buf[960];
+ short abuf[960];
char dtmf[128];
int interval = 0, samples = 0;
size_t len = 0, ilen = 0;
switch_channel_answer(channel);
- write_frame.data = buf;
- write_frame.buflen = sizeof(buf);
+ write_frame.data = abuf;
+ write_frame.buflen = sizeof(abuf);
switch_console_printf(SWITCH_CHANNEL_CONSOLE, "OPEN FILE %s %dhz %d channels\n", file, fh.samplerate, fh.channels);
while (switch_channel_get_state(channel) == CS_EXECUTE) {
int done = 0;
- if (dtmf_callback) {
+ if (dtmf_callback || buf) {
+
+
/*
dtmf handler function you can hook up to be executed when a digit is dialed during playback
if you return anything but SWITCH_STATUS_SUCCESS the playback will stop.
*/
if (switch_channel_has_dtmf(channel)) {
switch_channel_dequeue_dtmf(channel, dtmf, sizeof(dtmf));
- status = dtmf_callback(session, dtmf);
+ if (dtmf_callback) {
+ status = dtmf_callback(session, dtmf, buf, buflen);
+ } else {
+ switch_copy_string((char *)buf, dtmf, buflen);
+ status = SWITCH_STATUS_BREAK;
+ }
}
-
+
if (status != SWITCH_STATUS_SUCCESS) {
done = 1;
break;
}
}
- switch_core_file_read(&fh, buf, &ilen);
+ switch_core_file_read(&fh, abuf, &ilen);
if (done || ilen <= 0) {
break;
return status;
}
+
+
+