[asterisk-commits] irroot: branch irroot/t38gateway-1.8 r338903 - in /team/irroot/t38gateway-1.8...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Sun Oct 2 06:46:34 CDT 2011
Author: irroot
Date: Sun Oct 2 06:44:33 2011
New Revision: 338903
URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=338903
Log:
Revision 338902 - Directory Listing
Modified Sun Oct 2 10:54:30 2011 UTC (46 minutes, 4 seconds ago) by irroot
Add faxdetect framehook
Revision 338898 - Directory Listing
Modified Sun Oct 2 10:47:14 2011 UTC (53 minutes, 20 seconds ago) by irroot
Move func OOH323 to func CHANNEL
-------------------------
Merged from distrotech branch
Modified:
team/irroot/t38gateway-1.8/addons/chan_ooh323.c
team/irroot/t38gateway-1.8/funcs/func_channel.c
team/irroot/t38gateway-1.8/include/asterisk/res_fax.h
team/irroot/t38gateway-1.8/res/res_fax.c
Modified: team/irroot/t38gateway-1.8/addons/chan_ooh323.c
URL: http://svnview.digium.com/svn/asterisk/team/irroot/t38gateway-1.8/addons/chan_ooh323.c?view=diff&rev=338903&r1=338902&r2=338903
==============================================================================
--- team/irroot/t38gateway-1.8/addons/chan_ooh323.c (original)
+++ team/irroot/t38gateway-1.8/addons/chan_ooh323.c Sun Oct 2 06:44:33 2011
@@ -25,42 +25,6 @@
#include "chan_ooh323.h"
#include <math.h>
-/*** DOCUMENTATION
- <function name="OOH323" language="en_US">
- <synopsis>
- Allow Setting / Reading OOH323 Settings
- </synopsis>
- <syntax>
- <parameter name="name" required="true">
- <enumlist>
- <enum name="faxdetect">
- <para>Fax Detect [R/W]</para>
- <para>Returns 0 or 1</para>
- <para>Write yes or no</para>
- </enum>
- </enumlist>
- <enumlist>
- <enum name="t38support">
- <para>t38support [R/W]</para>
- <para>Returns 0 or 1</para>
- <para>Write yes or no</para>
- </enum>
- </enumlist>
- <enumlist>
- <enum name="h323id">
- <para>Returns h323id [R]</para>
- </enum>
- </enumlist>
- </parameter>
- </syntax>
- <description>
- <para>Read and set channel parameters in the dialplan.
- <replaceable>name</replaceable> is one of the above only those with a [W] can be writen to.
- </para>
- </description>
- </function>
-***/
-
#define FORMAT_STRING_SIZE 512
/* Defaults */
@@ -118,6 +82,8 @@
static int ooh323_indicate(struct ast_channel *ast, int condition, const void *data, size_t datalen);
static int ooh323_queryoption(struct ast_channel *ast, int option, void *data, int *datalen);
static int ooh323_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
+static int function_ooh323_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len);
+static int function_ooh323_write(struct ast_channel *chan, const char *cmd, char *data, const char *value);
static enum ast_rtp_glue_result ooh323_get_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance **rtp);
static enum ast_rtp_glue_result ooh323_get_vrtp_peer(struct ast_channel *chan, struct ast_rtp_instance **rtp);
@@ -152,7 +118,8 @@
.queryoption = ooh323_queryoption,
.bridge = ast_rtp_instance_bridge, /* XXX chan unlocked ? */
.early_bridge = ast_rtp_instance_early_bridge,
-
+ .func_channel_read = function_ooh323_read,
+ .func_channel_write = function_ooh323_write,
};
static struct ast_rtp_glue ooh323_rtp = {
@@ -3516,13 +3483,6 @@
return res;
}
-/*! \brief Structure to declare a dialplan function: OOH323 */
-static struct ast_custom_function ooh323_function = {
- .name = "OOH323",
- .read = function_ooh323_read,
- .write = function_ooh323_write,
-};
-
static int load_module(void)
{
int res;
@@ -3678,9 +3638,6 @@
/* And start the monitor for the first time */
restart_monitor();
}
-
- /* Register dialplan functions */
- ast_custom_function_register(&ooh323_function);
return 0;
}
@@ -4070,9 +4027,6 @@
ast_verbose(" unload_module- destroying OOH323 endpoint \n");
}
ooH323EpDestroy();
-
- /* Unregister dial plan functions */
- ast_custom_function_unregister(&ooh323_function);
if (gH323Debug) {
ast_verbose("+++ ooh323 unload_module \n");
Modified: team/irroot/t38gateway-1.8/funcs/func_channel.c
URL: http://svnview.digium.com/svn/asterisk/team/irroot/t38gateway-1.8/funcs/func_channel.c?view=diff&rev=338903&r1=338902&r2=338903
==============================================================================
--- team/irroot/t38gateway-1.8/funcs/func_channel.c (original)
+++ team/irroot/t38gateway-1.8/funcs/func_channel.c Sun Oct 2 06:44:33 2011
@@ -251,6 +251,22 @@
The channel is either on hold or a call waiting call.</para>
</enum>
</enumlist>
+ <para><emphasis>chan_ooh323</emphasis> provides the following additional options:</para>
+ <enumlist>
+ <enum name="faxdetect">
+ <para>Fax Detect [R/W]</para>
+ <para>Returns 0 or 1</para>
+ <para>Write yes or no</para>
+ </enum>
+ <enum name="t38support">
+ <para>t38support [R/W]</para>
+ <para>Returns 0 or 1</para>
+ <para>Write yes or no</para>
+ </enum>
+ <enum name="h323id">
+ <para>Returns h323id [R]</para>
+ </enum>
+ </enumlist>
</parameter>
</syntax>
<description>
Modified: team/irroot/t38gateway-1.8/include/asterisk/res_fax.h
URL: http://svnview.digium.com/svn/asterisk/team/irroot/t38gateway-1.8/include/asterisk/res_fax.h?view=diff&rev=338903&r1=338902&r2=338903
==============================================================================
--- team/irroot/t38gateway-1.8/include/asterisk/res_fax.h (original)
+++ team/irroot/t38gateway-1.8/include/asterisk/res_fax.h Sun Oct 2 06:44:33 2011
@@ -174,6 +174,8 @@
int gateway_id;
/*! the timeout for this gateway in seconds */
int gateway_timeout;
+ /*! the id of the faxdetect framehook for this channel */
+ int faxdetect_id;
};
struct ast_fax_tech;
Modified: team/irroot/t38gateway-1.8/res/res_fax.c
URL: http://svnview.digium.com/svn/asterisk/team/irroot/t38gateway-1.8/res/res_fax.c?view=diff&rev=338903&r1=338902&r2=338903
==============================================================================
--- team/irroot/t38gateway-1.8/res/res_fax.c (original)
+++ team/irroot/t38gateway-1.8/res/res_fax.c Sun Oct 2 06:44:33 2011
@@ -184,7 +184,10 @@
<para>R/W Modem type (v17/v27/v29).</para>
</enum>
<enum name="gateway">
- <para>R/W T38 Gateway Enabled With optional fax activity timeout in seconds (yes[,gwtimeout]/no)</para>
+ <para>R/W T38 fax gateway, with optional fax activity timeout in seconds (yes[,timeout]/no)</para>
+ </enum>
+ <enum name="faxdetect">
+ <para>R/W Enable FAX detect with optional timeout in seconds seconds (yes[,timeout]/no)</para>
</enum>
<enum name="pages">
<para>R/O Number of pages transferred.</para>
@@ -285,6 +288,24 @@
unsigned int peer_write_format;
};
+/*! \brief used for fax detect framehook */
+struct fax_detect {
+ /*! \brief the start of our timeout counter */
+ struct timeval timeout_start;
+ /*! \brief faxdetect timeout */
+ int timeout;
+ /*! \brief DSP Processor */
+ struct ast_dsp *dsp;
+ /*! \brief original audio formats */
+ unsigned int orig_format;
+ /*! \brief Noise limit to end faxdetect */
+ int noiselim;
+ /*! \brief result of the framehook e[CED]/f[CNG]/n[Noise]/t[T38] */
+ int result;
+ /*! \brief fax session details */
+ struct ast_fax_session_details *details;
+};
+
static int fax_logger_level = -1;
/*! \brief maximum buckets for res_fax ao2 containers */
@@ -467,6 +488,8 @@
d->minrate = general_options.minrate;
d->maxrate = general_options.maxrate;
d->gateway_id = -1;
+ d->faxdetect_id = -1;
+ d->gateway_timeout = 0;
return d;
}
@@ -3155,6 +3178,247 @@
return gateway->framehook;
}
+/*! \brief destroy a FAX detect structure */
+static void destroy_faxdetect(void *data)
+{
+ struct fax_detect *faxdetect = data;
+
+ if (faxdetect->dsp) {
+ ast_dsp_free(faxdetect->dsp);
+ faxdetect->dsp = NULL;
+ }
+ ao2_ref(faxdetect->details, -1);
+}
+
+/*! \brief Create a new fax detect object.
+ * \param chan the channel attaching to
+ * \param timeout remove framehook in this time if set
+ * \param noiselim end faxdetect when noiselim ms of noise is detected
+ * \param dsp_detect_flag dsp faxmode detect flags
+ * \return NULL or a fax gateway object
+ */
+static struct fax_detect *fax_detect_new(struct ast_channel *chan, int timeout, int noiselim, int dsp_detect_flag)
+{
+ struct fax_detect *faxdetect = ao2_alloc(sizeof(*faxdetect), destroy_faxdetect);
+ if (!faxdetect) {
+ return NULL;
+ }
+
+ faxdetect->noiselim = noiselim;
+ faxdetect->result = 0;
+
+ if (timeout) {
+ faxdetect->timeout_start = ast_tvnow();
+ } else {
+ faxdetect->timeout_start.tv_sec = 0;
+ faxdetect->timeout_start.tv_usec = 0;
+ }
+
+ faxdetect->dsp = ast_dsp_new();
+ if (!faxdetect->dsp) {
+ ao2_ref(faxdetect, -1);
+ return NULL;
+ }
+
+ ast_dsp_set_features(faxdetect->dsp, DSP_FEATURE_FAX_DETECT);
+ if (noiselim) {
+ ast_dsp_set_faxmode(faxdetect->dsp, dsp_detect_flag || DSP_FAXMODE_DETECT_SQUELCH);
+ ast_dsp_set_threshold(faxdetect->dsp, ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE));
+ } else {
+ ast_dsp_set_faxmode(faxdetect->dsp, dsp_detect_flag);
+ }
+ return faxdetect;
+}
+
+/*! \brief Deref the faxdetect data structure when the faxdetect framehook is detached
+ * \param data framehook data (faxdetect data)*/
+static void fax_detect_framehook_destroy(void *data) {
+ struct fax_detect *faxdetect = data;
+
+ ao2_ref(faxdetect, -1);
+}
+
+/*! \brief Fax Detect Framehook
+ *
+ * Listen for fax tones in audio path and enable jumping to a extension when detected.
+ *
+ * \param chan channel
+ * \param f frame to handle may be NULL
+ * \param event framehook event
+ * \param data framehook data (struct fax_detect *)
+ *
+ * \return processed frame or NULL when f is NULL or a null frame
+ */
+static struct ast_frame *fax_detect_framehook(struct ast_channel *chan, struct ast_frame *f, enum ast_framehook_event event, void *data) {
+ struct fax_detect *faxdetect = data;
+ struct ast_fax_session_details *details;
+ struct ast_control_t38_parameters *control_params;
+ struct ast_channel *peer;
+ int dspnoise;
+
+ details = faxdetect->details;
+
+ switch (event) {
+ case AST_FRAMEHOOK_EVENT_ATTACHED:
+ /* Setup format for DSP on ATTACH*/
+ ao2_lock(faxdetect);
+ faxdetect->orig_format = chan->readformat;
+ switch (chan->readformat) {
+ case AST_FORMAT_SLINEAR:
+ break;
+ default:
+ if (ast_set_read_format(chan, AST_FORMAT_SLINEAR)) {
+ ast_framehook_detach(chan, details->faxdetect_id);
+ details->faxdetect_id = -1;
+ }
+ }
+ ao2_unlock(faxdetect);
+ return NULL;
+ case AST_FRAMEHOOK_EVENT_DETACHED:
+ /* restore audio formats when we are detached */
+ ao2_lock(faxdetect);
+ ast_set_read_format(chan, faxdetect->orig_format);
+ if ((peer = ast_bridged_channel(chan))) {
+ ast_channel_make_compatible(chan, peer);
+ }
+ ao2_unlock(faxdetect);
+ return NULL;
+ case AST_FRAMEHOOK_EVENT_READ:
+ if (f) {
+ break;
+ }
+ default:
+ return f;
+ };
+
+ if ((!ast_tvzero(faxdetect->timeout_start) &&
+ (ast_tvdiff_ms(ast_tvnow(), faxdetect->timeout_start) > faxdetect->timeout))) {
+ ast_framehook_detach(chan, details->faxdetect_id);
+ details->faxdetect_id = -1;
+ }
+
+ /* only handle VOICE and CONTROL frames*/
+ switch (f->frametype) {
+ case AST_FRAME_VOICE:
+ /* We can only process some formats*/
+ switch (f->subclass.codec) {
+ case AST_FORMAT_SLINEAR:
+ break;
+ default:
+ return f;
+ }
+ break;
+ case AST_FRAME_CONTROL:
+ if (f->subclass.integer == AST_CONTROL_T38_PARAMETERS) {
+ break;
+ }
+ return f;
+ default:
+ return f;
+ }
+
+ ao2_lock(faxdetect);
+ if (f->frametype == AST_FRAME_VOICE) {
+ f = ast_dsp_process(chan, faxdetect->dsp, f);
+ if (f->frametype == AST_FRAME_DTMF) {
+ faxdetect->result = f->subclass.integer;
+ } else if ((f->frametype == AST_FRAME_VOICE) && (faxdetect->noiselim > 0)) {
+ ast_dsp_noise(faxdetect->dsp, f, &dspnoise);
+ if (dspnoise > faxdetect->noiselim) {
+ faxdetect->result = 'n';
+ }
+ }
+ } else if ((f->frametype == AST_FRAME_CONTROL) && (f->datalen != sizeof(struct ast_control_t38_parameters))) {
+ control_params = f->data.ptr;
+ switch (control_params->request_response) {
+ case AST_T38_NEGOTIATED:
+ case AST_T38_REQUEST_NEGOTIATE:
+ faxdetect->result = 't';
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (faxdetect->result) {
+ const char *target_context = S_OR(chan->macrocontext, chan->context);
+ switch (faxdetect->result) {
+ case 'f':
+ case 't':
+ ast_channel_unlock(chan);
+ if (ast_exists_extension(chan, target_context, "fax", 1,
+ S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
+ ast_channel_lock(chan);
+ ast_verbose(VERBOSE_PREFIX_2 "Redirecting '%s' to fax extension due to %s detection\n",
+ chan->name, (faxdetect->result == 'f') ? "CNG" : "T38");
+ pbx_builtin_setvar_helper(chan, "FAXEXTEN", chan->exten);
+ if (ast_async_goto(chan, target_context, "fax", 1)) {
+ ast_log(LOG_NOTICE, "Failed to async goto '%s' into fax of '%s'\n", chan->name, target_context);
+ }
+ ast_frfree(f);
+ f = &ast_null_frame;
+ } else {
+ ast_channel_lock(chan);
+ ast_log(LOG_NOTICE, "FAX %s detected but no fax extension\n",
+ (faxdetect->result == 'f') ? "CNG" : "T38");
+ }
+ }
+ ast_framehook_detach(chan, details->faxdetect_id);
+ details->faxdetect_id = -1;
+ }
+
+ ao2_unlock(faxdetect);
+
+ return f;
+}
+
+/*! \brief Attach a faxdetect framehook object to a channel.
+ * \param chan the channel to attach to
+ * \param timeout remove framehook in this time if set
+ * \param noiselim end faxdetect when noiselim ms of noise is detected
+ * \param dsp_detect_flag dsp faxmode detect flags
+ * \return the faxdetect structure or NULL on error
+ * \retval -1 error
+ */
+static struct fax_detect* fax_detect_attach(struct ast_channel *chan, int timeout, int noiselim, int dsp_detect_flags)
+{
+ struct fax_detect *faxdetect;
+ struct ast_fax_session_details *details;
+ struct ast_framehook_interface fr_hook = {
+ .version = AST_FRAMEHOOK_INTERFACE_VERSION,
+ .event_cb = fax_detect_framehook,
+ .destroy_cb = fax_detect_framehook_destroy,
+ };
+
+ if (!(details = find_or_create_details(chan))) {
+ ast_log(LOG_ERROR, "System cannot provide memory for session requirements.\n");
+ return NULL;
+ }
+
+ /* set up the frame hook*/
+ faxdetect = fax_detect_new(chan, timeout, noiselim, dsp_detect_flags);
+ if (!faxdetect) {
+ ao2_ref(details, -1);
+ return NULL;
+ }
+
+ fr_hook.data = faxdetect;
+ faxdetect->details = details;
+ ast_channel_lock(chan);
+ details->faxdetect_id = ast_framehook_attach(chan, &fr_hook);
+ ast_channel_unlock(chan);
+
+ if (details->faxdetect_id < 0) {
+ ao2_ref(details, -1);
+ ao2_ref(faxdetect, -1);
+ return NULL;
+ }
+
+ /* return it with ref held in framhook and return*/
+ ao2_ref(faxdetect, 1);
+ return faxdetect;
+}
+
/*! \brief Faxdetect loop used by WaitFAX
* \details Run DSP faxdetect on the channel for timeout seconds or until fax is detected
* \param chan channel to run fax detect on
@@ -3164,31 +3428,13 @@
{
int timeleft = timeout;
int res = 0;
- int dspnoise = 0;
- struct ast_dsp *dsp = NULL;
struct ast_frame *f, *dup_f;
- enum ast_t38_state t38state = T38_STATE_UNKNOWN;
- unsigned int orig_read_format;
AST_LIST_HEAD_NOLOCK(, ast_frame) deferred_frames;
-
- /* Setup DSP CNG processing */
- orig_read_format = chan->readformat;
- switch (chan->readformat) {
- case AST_FORMAT_SLINEAR:
- break;
- default:
- if (ast_set_read_format(chan, AST_FORMAT_SLINEAR)) {
- return -1;
- }
- }
-
- if (!(dsp = ast_dsp_new())) {
+ struct fax_detect *faxdetect = NULL;
+
+ if (!(faxdetect = fax_detect_attach(chan, 0, noiselim, DSP_FAXMODE_DETECT_CNG))) {
return -1;
}
-
- ast_dsp_set_features(dsp, DSP_FEATURE_FAX_DETECT);
- ast_dsp_set_faxmode(dsp, DSP_FAXMODE_DETECT_CNG | DSP_FAXMODE_DETECT_SQUELCH);
- ast_dsp_set_threshold(dsp, ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE));
AST_LIST_HEAD_INIT_NOLOCK(&deferred_frames);
@@ -3197,18 +3443,18 @@
break;
}
- if (dsp && (f->frametype == AST_FRAME_VOICE) && ((f->subclass.codec == AST_FORMAT_SLINEAR) ||
- (f->subclass.codec == AST_FORMAT_ULAW) || (f->subclass.codec == AST_FORMAT_ALAW))) {
- f = ast_dsp_process(chan, dsp, f);
- if ((f->frametype == AST_FRAME_DTMF) && (f->subclass.integer == 'f')) {
+ ao2_lock(faxdetect);
+ switch (faxdetect->result) {
+ case 'f':
res = 1;
- } else if ((f->frametype == AST_FRAME_VOICE) && (noiselim > 0)) {
- ast_dsp_noise(dsp, f, &dspnoise);
- if (dspnoise > noiselim) {
- break;
- }
- }
- }
+ break;
+ case 't':
+ res = 2;
+ break;
+ case 'n':
+ break;
+ }
+ ao2_unlock(faxdetect);
if (ast_is_deferrable_frame(f)) {
AST_LIST_INSERT_HEAD(&deferred_frames, f, frame_list);
@@ -3216,18 +3462,11 @@
ast_frfree(f);
}
- t38state = ast_channel_get_t38_state(chan);
- if ((t38state == T38_STATE_NEGOTIATING) || (t38state == T38_STATE_NEGOTIATED)) {
- res = 2;
+ if (res) {
break;
- } else if (res) {
- break;
- }
- }
-
- if (orig_read_format != chan->readformat) {
- ast_set_read_format(chan, orig_read_format);
- }
+ }
+ }
+ ao2_ref(faxdetect, -1);
ast_channel_lock(chan);
while ((f = AST_LIST_REMOVE_HEAD(&deferred_frames, frame_list))) {
@@ -3238,10 +3477,6 @@
}
}
ast_channel_unlock(chan);
-
- if (dsp) {
- ast_dsp_free(dsp);
- }
return res;
}
@@ -3860,6 +4095,40 @@
} else {
ast_log(LOG_WARNING, "Unsupported value '%s' passed to FAXOPT(%s).\n", value, data);
}
+ } else if (!strcasecmp(data, "faxdetect")) {
+ const char *val = ast_skip_blanks(value);
+ char *timeout = strchr(val, ',');
+ unsigned int fdtimeout = 0;
+ struct fax_detect *faxdetect;
+
+ if (timeout) {
+ *timeout++ = '\0';
+ }
+
+ if (ast_true(val)) {
+ if (details->faxdetect_id < 0) {
+ if (timeout && (sscanf(timeout, "%u", &fdtimeout) == 1)) {
+ fdtimeout = fdtimeout * 1000;
+ }
+
+ faxdetect = fax_detect_attach(chan, fdtimeout, 0, DSP_FAXMODE_DETECT_CNG);
+
+ if (faxdetect && (details->faxdetect_id >= 0)) {
+ ast_debug(1, "Attached FAX detect to channel %s.\n", chan->name);
+ } else {
+ ast_log(LOG_ERROR, "Error attaching FAX detect to channel %s.\n", chan->name);
+ res = -1;
+ }
+ ao2_ref(faxdetect, -1);
+ } else {
+ ast_log(LOG_WARNING, "Attempt to attach a FAX detect on channel (%s) with FAX detect already running.\n", chan->name);
+ }
+ } else if (ast_false(val)) {
+ ast_framehook_detach(chan, details->faxdetect_id);
+ details->faxdetect_id = -1;
+ } else {
+ ast_log(LOG_WARNING, "Unsupported value '%s' passed to FAXOPT(%s).\n", value, data);
+ }
} else if (!strcasecmp(data, "headerinfo")) {
ast_string_field_set(details, headerinfo, value);
} else if (!strcasecmp(data, "localstationid")) {
More information about the asterisk-commits
mailing list