Author: ctrix
Date: 2007-04-01 18:43:35 -0400 (Sun, 01 Apr 2007)
New Revision: 2578
Modified:
openpbx/trunk/apps/app_rxfax.c
openpbx/trunk/apps/app_txfax.c
Log:
This should improve app_(T|R)Fax capabilities to send audio
faxes. T38 is to be improved in Txfax.
Modified: openpbx/trunk/apps/app_rxfax.c
============================================================
=======
--- openpbx/trunk/apps/app_rxfax.c 2007-04-01 15:50:04 UTC
(rev 2577)
+++ openpbx/trunk/apps/app_rxfax.c 2007-04-01 22:43:35 UTC
(rev 2578)
 -462,7
+462,9 
if (fax_rx(&fax, inf->data,
inf->samples))
break;
samples = (inf->samples <=
MAX_BLOCK_SIZE) ? inf->samples : MAX_BLOCK_SIZE;
- if ((len = fax_tx(&fax, (int16_t *)
&buf[OPBX_FRIENDLY_OFFSET], samples)))
+
+ len = fax_tx(&fax, (int16_t *)
&buf[OPBX_FRIENDLY_OFFSET], samples);
+ if ( len )
{
opbx_fr_init_ex(&outf,
OPBX_FRAME_VOICE, OPBX_FORMAT_SLINEAR, "RxFAX");
outf.datalen = len*sizeof(int16_t);
 -475,6
+477,20 
break;
}
}
+ else {
+ len = samples;
+ opbx_fr_init_ex(&outf,
OPBX_FRAME_VOICE, OPBX_FORMAT_SLINEAR, "RxFAX");
+ outf.datalen = len*sizeof(int16_t);
+ outf.samples = len;
+ outf.data =
&buf[OPBX_FRIENDLY_OFFSET];
+ outf.offset = OPBX_FRIENDLY_OFFSET;
+
memset(&buf[OPBX_FRIENDLY_OFFSET],0,outf.datalen);
+ if (opbx_write(chan, &outf) <
0)
+ {
+ opbx_log(LOG_WARNING, "Unable
to write frame to channel; %sn", strerror(errno));
+ break;
+ }
+ }
}
else if (inf->frametype == OPBX_FRAME_MODEM
&& inf->subclass == OPBX_MODEM_T38)
{
Modified: openpbx/trunk/apps/app_txfax.c
============================================================
=======
--- openpbx/trunk/apps/app_txfax.c 2007-04-01 15:50:04 UTC
(rev 2577)
+++ openpbx/trunk/apps/app_txfax.c 2007-04-01 22:43:35 UTC
(rev 2578)
 -14,7
+14,8 
#ifdef HAVE_CONFIG_H
#include "confdefs.h"
#endif
-
+
+#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include <inttypes.h>
 -65,6
+66,7 
LOCAL_USER_DECL;
#define MAX_BLOCK_SIZE 240
+#define ready_to_talk(chan) ( (!chan ||
opbx_check_hangup(chan) ) ? 0 : 1)
static void span_message(int level, const char *msg)
{
 -80,14
+82,86 
opbx_log(opbx_level, __FILE__, __LINE__,
__PRETTY_FUNCTION__, msg);
}
/*- End of function
--------------------------------------------------------*/
-/* Removing alerts generated by the compiler.
-static void t30_flush(t30_state_t *s, int which)
+
+/* Return a monotonically increasing time, in microseconds
*/
+static uint64_t nowis(void)
{
- //TODO:
+ int64_t now;
+#ifndef HAVE_POSIX_TIMERS
+ struct timeval tv;
+
+ gettimeofday(&tv, NULL);
+ now = tv.tv_sec*1000000LL + tv.tv_usec;
+#else
+ struct timespec ts;
+
+ if (clock_gettime(CLOCK_MONOTONIC, &ts))
+ opbx_log(LOG_WARNING, "clock_gettime returned
%sn", strerror(errno));
+ now = ts.tv_sec*1000000LL + ts.tv_nsec/1000;
+#endif
+ return now;
}
-*/
+
/*- End of function
--------------------------------------------------------*/
+/*
************************************************************
*****************
+ MEMBER GENERATOR
+
************************************************************
****************/
+
+static void *faxgen_alloc(struct opbx_channel *chan, void
*params)
+{
+ opbx_log(LOG_DEBUG,"Allocating fax
generatorn");
+ return params;
+}
+
+/*- End of function
--------------------------------------------------------*/
+
+static void faxgen_release(struct opbx_channel *chan, void
*data)
+{
+ opbx_log(LOG_DEBUG,"Releasing fax
generatorn");
+ return;
+}
+
+/*- End of function
--------------------------------------------------------*/
+
+static int faxgen_generate(struct opbx_channel *chan, void
*data, int samples)
+{
+ int len;
+ fax_state_t *fax;
+ struct opbx_frame outf;
+
+ uint8_t __buf[sizeof(uint16_t)*MAX_BLOCK_SIZE +
2*OPBX_FRIENDLY_OFFSET];
+ uint8_t *buf = __buf + OPBX_FRIENDLY_OFFSET;
+
+ fax = (fax_state_t*) data;
+
+ samples = ( samples <= MAX_BLOCK_SIZE ) ? samples
: MAX_BLOCK_SIZE;
+ len = fax_tx(fax, (int16_t *)
&buf[OPBX_FRIENDLY_OFFSET], samples);
+
+ if (len) {
+ opbx_fr_init_ex(&outf, OPBX_FRAME_VOICE,
OPBX_FORMAT_SLINEAR, "TxFAX");
+ outf.datalen = len*sizeof(int16_t);
+ outf.samples = len;
+ outf.data = &buf[OPBX_FRIENDLY_OFFSET];
+ outf.offset = OPBX_FRIENDLY_OFFSET;
+
+ if (opbx_write(chan, &outf) < 0) {
+ opbx_log(LOG_WARNING, "Unable to write
frame to channel; %sn", strerror(errno));
+ }
+ }
+
+ return 0;
+}
+
+struct opbx_generator faxgen =
+{
+ alloc: faxgen_alloc,
+ release: faxgen_release,
+ generate: faxgen_generate,
+} ;
+
+/*- End of function
--------------------------------------------------------*/
+
static void phase_e_handler(t30_state_t *s, void
*user_data, int result)
{
struct opbx_channel *chan;
 -157,67
+231,258 
}
/*- End of function
--------------------------------------------------------*/
-/* Return a monotonically increasing time, in microseconds
*/
-static int64_t nowis(void)
-{
- int64_t now;
-#ifndef HAVE_POSIX_TIMERS
- struct timeval tv;
- gettimeofday(&tv, NULL);
- now = tv.tv_sec*1000000LL + tv.tv_usec;
-#else
- struct timespec ts;
+static int txfax_t38(struct opbx_channel *chan,
t38_terminal_state_t *t38, char *source_file, int
calling_party,int verbose, int ecm) {
+ char *x;
+ struct opbx_frame *inf = NULL;
+ int ready = 1,
+ res = 0;
+
+ memset(t38, 0, sizeof(t38));
+
+ t38_terminal_init(t38, calling_party,
t38_tx_packet_handler, chan);
+
+ span_log_set_message_handler(&t38->logging,
span_message);
+
span_log_set_message_handler(&t38->t30_state.logging,
span_message);
+ span_log_set_message_handler(&t38->t38.logging,
span_message);
+
+ if (verbose)
+ {
+ span_log_set_level(&t38->logging,
SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL |
SPAN_LOG_FLOW);
+ span_log_set_level(&t38->t30_state.logging,
SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL |
SPAN_LOG_FLOW);
+ span_log_set_level(&t38->t38.logging,
SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL |
SPAN_LOG_FLOW);
+ }
+
+ x = pbx_builtin_getvar_helper(chan,
"LOCALSTATIONID");
+ if (x && x[0])
+ t30_set_local_ident(&t38->t30_state, x);
+ x = pbx_builtin_getvar_helper(chan,
"LOCALHEADERINFO");
+ if (x && x[0])
+ t30_set_header_info(&t38->t30_state, x);
+ t30_set_tx_file(&t38->t30_state, source_file,
-1, -1);
+ //t30_set_phase_b_handler(&t38.t30_state,
phase_b_handler, chan);
+ //t30_set_phase_d_handler(&t38.t30_state,
phase_d_handler, chan);
+ t30_set_phase_e_handler(&t38->t30_state,
phase_e_handler, chan);
+
+ t30_set_supported_image_sizes(&t38->t30_state,
T30_SUPPORT_US_LETTER_LENGTH | T30_SUPPORT_US_LEGAL_LENGTH |
T30_SUPPORT_UNLIMITED_LENGTH
+ |
T30_SUPPORT_215MM_WIDTH | T30_SUPPORT_255MM_WIDTH |
T30_SUPPORT_303MM_WIDTH);
+ t30_set_supported_resolutions(&t38->t30_state,
T30_SUPPORT_STANDARD_RESOLUTION |
T30_SUPPORT_FINE_RESOLUTION |
T30_SUPPORT_SUPERFINE_RESOLUTION
+ |
T30_SUPPORT_R8_RESOLUTION | T30_SUPPORT_R16_RESOLUTION);
+
+ if (ecm) {
+ t30_set_ecm_capability(&t38->t30_state,
TRUE);
+
t30_set_supported_compressions(&t38->t30_state,
T30_SUPPORT_T4_1D_COMPRESSION |
T30_SUPPORT_T4_2D_COMPRESSION |
T30_SUPPORT_T6_COMPRESSION);
+ opbx_log(LOG_DEBUG, "Enabling ECM mode for
app_txfaxn" );
+ }
+
+
+
+ while ( ready && ready_to_talk(chan) )
+ {
- if (clock_gettime(CLOCK_MONOTONIC, &ts))
- opbx_log(LOG_WARNING, "clock_gettime returned
%sn", strerror(errno));
- now = ts.tv_sec*1000000LL + ts.tv_nsec/1000;
-#endif
- return now;
+ if ( !chan->t38mode_enabled )
+ break;
+
+ if ((res = opbx_waitfor(chan, 20)) < 0) {
+ ready = 0;
+ break;
+ }
+
+ inf = opbx_read(chan);
+ if (inf == NULL) {
+ ready = 0;
+ break;
+ }
+
+ if (inf->frametype == OPBX_FRAME_MODEM
&& inf->subclass == OPBX_MODEM_T38)
+ {
+ t38_core_rx_ifp_packet(&t38->t38,
inf->seq_no, inf->data, inf->datalen);
+ }
+
+ opbx_fr_free(inf);
+ }
+
+ return ready;
+
}
+
/*- End of function
--------------------------------------------------------*/
+static int txfax_audio(struct opbx_channel *chan,
fax_state_t *fax, char *source_file, int calling_party,int
verbose, int ecm) {
+ char *x;
+ struct opbx_frame *inf = NULL;
+ struct opbx_frame outf;
+ int ready = 1,
+ samples = 0,
+ res = 0,
+ len = 0,
+ generator_mode = 0;
+ uint64_t begin = 0,
+ received_frames = 0;
+
+ uint8_t __buf[sizeof(uint16_t)*MAX_BLOCK_SIZE +
2*OPBX_FRIENDLY_OFFSET];
+ uint8_t *buf = __buf + OPBX_FRIENDLY_OFFSET;
+
+ memset(fax, 0, sizeof(fax));
+
+ fax_init(fax, calling_party);
+ fax_set_transmit_on_idle(fax,TRUE);
+ span_log_set_message_handler(&fax->logging,
span_message);
+
span_log_set_message_handler(&fax->t30_state.logging,
span_message);
+ if (verbose)
+ {
+ span_log_set_level(&fax->logging,
SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL |
SPAN_LOG_FLOW);
+ span_log_set_level(&fax->t30_state.logging,
SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL |
SPAN_LOG_FLOW);
+ }
+ x = pbx_builtin_getvar_helper(chan,
"LOCALSTATIONID");
+ if (x && x[0])
+ t30_set_local_ident(&fax->t30_state, x);
+ x = pbx_builtin_getvar_helper(chan,
"LOCALHEADERINFO");
+ if (x && x[0])
+ t30_set_header_info(&fax->t30_state, x);
+ t30_set_tx_file(&fax->t30_state, source_file,
-1, -1);
+ //t30_set_phase_b_handler(&fax.t30_state,
phase_b_handler, chan);
+ //t30_set_phase_d_handler(&fax.t30_state,
phase_d_handler, chan);
+ t30_set_phase_e_handler(&fax->t30_state,
phase_e_handler, chan);
+
+ /* Support for different image sizes &&
resolutions*/
+ t30_set_supported_image_sizes(&fax->t30_state,
T30_SUPPORT_US_LETTER_LENGTH | T30_SUPPORT_US_LEGAL_LENGTH |
T30_SUPPORT_UNLIMITED_LENGTH
+ |
T30_SUPPORT_215MM_WIDTH | T30_SUPPORT_255MM_WIDTH |
T30_SUPPORT_303MM_WIDTH);
+ t30_set_supported_resolutions(&fax->t30_state,
T30_SUPPORT_STANDARD_RESOLUTION |
T30_SUPPORT_FINE_RESOLUTION |
T30_SUPPORT_SUPERFINE_RESOLUTION
+ |
T30_SUPPORT_R8_RESOLUTION | T30_SUPPORT_R16_RESOLUTION);
+ if (ecm) {
+ t30_set_ecm_capability(&fax->t30_state,
TRUE);
+
t30_set_supported_compressions(&fax->t30_state,
T30_SUPPORT_T4_1D_COMPRESSION |
T30_SUPPORT_T4_2D_COMPRESSION |
T30_SUPPORT_T6_COMPRESSION);
+ opbx_log(LOG_DEBUG, "Enabling ECM mode for
app_txfaxn" );
+ }
+
+ /* This is the main loop */
+
+ begin = nowis();
+
+ while ( ready && ready_to_talk(chan) )
+ {
+
+ if ( chan->t38mode_enabled )
+ break;
+
+ if ((res = opbx_waitfor(chan, 20)) < 0) {
+ ready = 0;
+ break;
+ }
+
+ inf = opbx_read(chan);
+ if (inf == NULL) {
+ ready = 0;
+ break;
+ }
+
+ /* We got a frame */
+ if (inf->frametype == OPBX_FRAME_VOICE) {
+
+ received_frames ++;
+
+ if (fax_rx(fax, inf->data,
inf->samples))
+ break;
+
+ samples = (inf->samples <=
MAX_BLOCK_SIZE) ? inf->samples : MAX_BLOCK_SIZE;
+ len = fax_tx(fax, (int16_t *)
&buf[OPBX_FRIENDLY_OFFSET], samples);
+
+ if (len) {
+ opbx_fr_init_ex(&outf,
OPBX_FRAME_VOICE, OPBX_FORMAT_SLINEAR, "TxFAX");
+ outf.datalen = len*sizeof(int16_t);
+ outf.samples = len;
+ outf.data =
&buf[OPBX_FRIENDLY_OFFSET];
+ outf.offset = OPBX_FRIENDLY_OFFSET;
+
+ if (opbx_write(chan, &outf) < 0) {
+ opbx_log(LOG_WARNING, "Unable to
write frame to channel; %sn", strerror(errno));
+ break;
+ }
+ }
+ }
+ else {
+ if ( (nowis() - begin) > 1000000 ) {
+ if (received_frames < 20 ) { // just to be sure we
have had no frames ...
+ opbx_log(LOG_WARNING,"Switching to generator
moden");
+ generator_mode = 1;
+ break;
+ }
+ }
+ }
+ opbx_fr_free(inf);
+ }
+
+ if (generator_mode) {
+ // This is activated when we don't receive any frame for
+ // X seconds (see above)... we are probably on ZAP or
talking without UDPTL to
+ // another openpbx box
+ opbx_generator_activate(chan, &faxgen, fax);
+
+ while ( ready && ready_to_talk(chan) ) {
+
+ if ( chan->t38mode_enabled )
+ break;
+
+ if ((res = opbx_waitfor(chan, 20)) < 0) {
+ ready = 0;
+ break;
+ }
+
+ inf = opbx_read(chan);
+ if (inf == NULL) {
+ ready = 0;
+ break;
+ }
+
+ /* We got a frame */
+ if (inf->frametype == OPBX_FRAME_VOICE) {
+ if (fax_rx(fax, inf->data, inf->samples)) {
+ ready = 0;
+ break;
+ }
+ }
+
+ }
+
+ opbx_generator_deactivate(chan);
+
+ }
+
+ return ready;
+}
+
+/*- End of function
--------------------------------------------------------*/
+
+
static int txfax_exec(struct opbx_channel *chan, void
*data)
{
+ fax_state_t fax;
+ t38_terminal_state_t t38;
+
int res = 0;
char source_file[256];
- char *x;
char *s;
char *t;
char *v;
int option;
int len;
- fax_state_t fax;
- t38_terminal_state_t t38;
+ int ready;
+
int calling_party;
int verbose;
- int samples;
- int call_is_t38_mode;
int ecm = FALSE;
struct localuser *u;
- struct opbx_frame *inf = NULL;
- struct opbx_frame outf;
int original_read_fmt;
int original_write_fmt;
- int64_t now;
- int64_t next;
- int64_t passage;
- int delay;
- time_t begin, thistime;
-
- pbx_builtin_setvar_helper(chan,
"REMOTESTATIONID", "");
- pbx_builtin_setvar_helper(chan, "FAXPAGES",
"");
- pbx_builtin_setvar_helper(chan,
"FAXRESOLUTION", "");
- pbx_builtin_setvar_helper(chan, "FAXBITRATE",
"");
- pbx_builtin_setvar_helper(chan,
"PHASEESTATUS", "");
- pbx_builtin_setvar_helper(chan,
"PHASEESTRING", "");
-
uint8_t __buf[sizeof(uint16_t)*MAX_BLOCK_SIZE +
2*OPBX_FRIENDLY_OFFSET];
uint8_t *buf = __buf + OPBX_FRIENDLY_OFFSET;
+ /* Basic initial checkings */
+
if (chan == NULL)
{
opbx_log(LOG_WARNING, "Fax transmit channel is
NULL. Giving up.n");
 -231,7
+496,18 
opbx_log(LOG_WARNING, "Txfax requires an
argument (filename)n");
return -1;
}
+
+ /* Resetting channel variables related to T38 */
+ pbx_builtin_setvar_helper(chan,
"REMOTESTATIONID", "");
+ pbx_builtin_setvar_helper(chan, "FAXPAGES",
"");
+ pbx_builtin_setvar_helper(chan,
"FAXRESOLUTION", "");
+ pbx_builtin_setvar_helper(chan, "FAXBITRATE",
"");
+ pbx_builtin_setvar_helper(chan,
"PHASEESTATUS", "");
+ pbx_builtin_setvar_helper(chan,
"PHASEESTRING", "");
+
+ /* Parsig parameters */
+
calling_party = FALSE;
verbose = FALSE;
source_file[0] = ' ';
 -273,7
+549,6 
/* TODO: handle this */
}
}
-
/* Done parsing */
LOCAL_USER_ADD(u);
 -283,239
+558,83 
/* Shouldn't need this, but checking to see if
channel is already answered
* Theoretically the PBX should already have
answered before running the app */
res = opbx_answer(chan);
+ if (!res)
+ {
+ opbx_log(LOG_WARNING, "Could not answer
channel '%s'n", chan->name);
+ LOCAL_USER_REMOVE(u);
+ return res;
+ }
}
+
+ /* Setting read and write formats */
- if (!res)
+ original_read_fmt = chan->readformat;
+ if (original_read_fmt != OPBX_FORMAT_SLINEAR)
{
- original_read_fmt = chan->readformat;
- if (original_read_fmt != OPBX_FORMAT_SLINEAR)
+ res = opbx_set_read_format(chan,
OPBX_FORMAT_SLINEAR);
+ if (res < 0)
{
- res = opbx_set_read_format(chan,
OPBX_FORMAT_SLINEAR);
- if (res < 0)
- {
- opbx_log(LOG_WARNING, "Unable to set
to linear read mode, giving upn");
- LOCAL_USER_REMOVE(u);
- return -1;
- }
+ opbx_log(LOG_WARNING, "Unable to set to
linear read mode, giving upn");
+ LOCAL_USER_REMOVE(u);
+ return -1;
}
- original_write_fmt = chan->writeformat;
- if (original_write_fmt != OPBX_FORMAT_SLINEAR)
+ }
+
+ original_write_fmt = chan->writeformat;
+ if (original_write_fmt != OPBX_FORMAT_SLINEAR)
+ {
+ res = opbx_set_write_format(chan,
OPBX_FORMAT_SLINEAR);
+ if (res < 0)
{
- res = opbx_set_write_format(chan,
OPBX_FORMAT_SLINEAR);
- if (res < 0)
- {
- opbx_log(LOG_WARNING, "Unable to set
to linear write mode, giving upn");
- res = opbx_set_read_format(chan,
original_read_fmt);
- if (res)
- opbx_log(LOG_WARNING, "Unable to
restore read format on '%s'n", chan->name);
- LOCAL_USER_REMOVE(u);
- return -1;
- }
+ opbx_log(LOG_WARNING, "Unable to set to
linear write mode, giving upn");
+ res = opbx_set_read_format(chan,
original_read_fmt);
+ if (res)
+ opbx_log(LOG_WARNING, "Unable to
restore read format on '%s'n", chan->name);
+ LOCAL_USER_REMOVE(u);
+ return -1;
}
+ }
- memset(&fax, 0, sizeof(fax));
- memset(&t38, 0, sizeof(t38));
- fax_init(&fax, calling_party);
- fax_set_transmit_on_idle(&fax,TRUE);
- span_log_set_message_handler(&fax.logging,
span_message);
-
span_log_set_message_handler(&fax.t30_state.logging,
span_message);
- if (verbose)
- {
- span_log_set_level(&fax.logging,
SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL |
SPAN_LOG_FLOW);
- span_log_set_level(&fax.t30_state.logging,
SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL |
SPAN_LOG_FLOW);
- }
- x = pbx_builtin_getvar_helper(chan,
"LOCALSTATIONID");
- if (x && x[0])
- t30_set_local_ident(&fax.t30_state, x);
- x = pbx_builtin_getvar_helper(chan,
"LOCALHEADERINFO");
- if (x && x[0])
- t30_set_header_info(&fax.t30_state, x);
- t30_set_tx_file(&fax.t30_state, source_file,
-1, -1);
- //t30_set_phase_b_handler(&fax.t30_state,
phase_b_handler, chan);
- //t30_set_phase_d_handler(&fax.t30_state,
phase_d_handler, chan);
- t30_set_phase_e_handler(&fax.t30_state,
phase_e_handler, chan);
+ /* This is the main loop */
- t38_terminal_init(&t38, calling_party,
t38_tx_packet_handler, chan);
- span_log_set_message_handler(&t38.logging,
span_message);
-
span_log_set_message_handler(&t38.t30_state.logging,
span_message);
- span_log_set_message_handler(&t38.t38.logging,
span_message);
- if (verbose)
- {
- span_log_set_level(&t38.logging,
SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL |
SPAN_LOG_FLOW);
- span_log_set_level(&t38.t30_state.logging,
SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL |
SPAN_LOG_FLOW);
- span_log_set_level(&t38.t38.logging,
SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL |
SPAN_LOG_FLOW);
- }
- x = pbx_builtin_getvar_helper(chan,
"LOCALSTATIONID");
- if (x && x[0])
- t30_set_local_ident(&t38.t30_state, x);
- x = pbx_builtin_getvar_helper(chan,
"LOCALHEADERINFO");
- if (x && x[0])
- t30_set_header_info(&t38.t30_state, x);
- t30_set_tx_file(&t38.t30_state, source_file,
-1, -1);
- //t30_set_phase_b_handler(&t38.t30_state,
phase_b_handler, chan);
- //t30_set_phase_d_handler(&t38.t30_state,
phase_d_handler, chan);
- t30_set_phase_e_handler(&t38.t30_state,
phase_e_handler, chan);
+ ready = TRUE;
- /* Support for different image sizes &&
resolutions*/
- t30_set_supported_image_sizes(&fax.t30_state,
T30_SUPPORT_US_LETTER_LENGTH | T30_SUPPORT_US_LEGAL_LENGTH |
T30_SUPPORT_UNLIMITED_LENGTH
- |
T30_SUPPORT_215MM_WIDTH | T30_SUPPORT_255MM_WIDTH |
T30_SUPPORT_303MM_WIDTH);
- t30_set_supported_resolutions(&fax.t30_state,
T30_SUPPORT_STANDARD_RESOLUTION |
T30_SUPPORT_FINE_RESOLUTION |
T30_SUPPORT_SUPERFINE_RESOLUTION
- |
T30_SUPPORT_R8_RESOLUTION | T30_SUPPORT_R16_RESOLUTION);
- t30_set_supported_image_sizes(&t38.t30_state,
T30_SUPPORT_US_LETTER_LENGTH | T30_SUPPORT_US_LEGAL_LENGTH |
T30_SUPPORT_UNLIMITED_LENGTH
- |
T30_SUPPORT_215MM_WIDTH | T30_SUPPORT_255MM_WIDTH |
T30_SUPPORT_303MM_WIDTH);
- t30_set_supported_resolutions(&t38.t30_state,
T30_SUPPORT_STANDARD_RESOLUTION |
T30_SUPPORT_FINE_RESOLUTION |
T30_SUPPORT_SUPERFINE_RESOLUTION
- |
T30_SUPPORT_R8_RESOLUTION | T30_SUPPORT_R16_RESOLUTION);
- if (ecm) {
- t30_set_ecm_capability(&fax.t30_state,
TRUE);
-
t30_set_supported_compressions(&fax.t30_state,
T30_SUPPORT_T4_1D_COMPRESSION |
T30_SUPPORT_T4_2D_COMPRESSION |
T30_SUPPORT_T6_COMPRESSION);
- t30_set_ecm_capability(&t38.t30_state,
TRUE);
-
t30_set_supported_compressions(&t38.t30_state,
T30_SUPPORT_T4_1D_COMPRESSION |
T30_SUPPORT_T4_2D_COMPRESSION |
T30_SUPPORT_T6_COMPRESSION);
- opbx_log(LOG_DEBUG, "Enabling ECM mode for
app_txfaxn" );
- }
-
- call_is_t38_mode = FALSE;
- passage = nowis();
- next = passage + 30000;
- time(&begin);
- while (1)
- {
- now = nowis();
- delay = (next < now) ? 0 : (next - now +
500)/1000;
- if ((res = opbx_waitfor(chan, delay)) < 0)
- break;
+ while ( ready && ready_to_talk(chan) )
+ {
- // Let's timeout if we have no input packets
for at least 60 secs.
- time(&thistime);
- if ( ((thistime-begin) >= 60) &&
!call_is_t38_mode ) {
- opbx_log(LOG_DEBUG, "No data
received for %ld seconds. Hanging up.n",
(int)thistime-begin );
- break;
- }
- // Let's help T38 switchover (don't wait for
udptl packets but trust channel state).
- if (!call_is_t38_mode) {
- if (chan->t38mode_enabled==1) {
- call_is_t38_mode=TRUE;
- opbx_log(LOG_DEBUG, "T38
switchover detectedn" );
- }
- }
+ if ( ready && chan->t38mode_enabled!=1 )
{
+ ready = txfax_audio( chan, &fax, source_file,
calling_party, verbose, ecm);
+ }
- if (call_is_t38_mode)
- {
- now = nowis();
- t38_terminal_send_timeout(&t38, (now -
passage)/125);
- passage = now;
- /* End application when T38/T30 has
finished */
- if ((t38.current_rx_type == T30_MODEM_DONE)
|| (t38.current_tx_type == T30_MODEM_DONE))
- break;
- }
+ if ( ready && chan->t38mode_enabled==1 )
{
+ ready = txfax_t38 ( chan, &t38, source_file,
calling_party, verbose, ecm);
+ }
- if (res == 0)
- {
- if (!call_is_t38_mode)
- {
- samples = 160;
- if ((len = fax_tx(&fax, (int16_t *)
&buf[OPBX_FRIENDLY_OFFSET], samples)))
- {
- opbx_fr_init_ex(&outf,
OPBX_FRAME_VOICE, OPBX_FORMAT_SLINEAR, "TxFAX");
- outf.datalen =
len*sizeof(int16_t);
- outf.samples = len;
- outf.data =
&buf[OPBX_FRIENDLY_OFFSET];
- outf.offset =
OPBX_FRIENDLY_OFFSET;
- if (opbx_write(chan, &outf)
< 0)
- {
- opbx_log(LOG_WARNING,
"Unable to write frame to channel; %sn",
strerror(errno));
- break;
- }
- passage = now;
- next += 20000; // If I remember
well, spandsp generates 1 frame every 20ms
- }
- }
- else
- next += 30000;
- continue;
- }
- else
- {
- // TxFax receives 1 fake packet every 3-4
secs.
- // This check is used to verify autenticity
of RTP packets.
- if ( thistime-begin <=2 )
- time(&begin);
- }
+ ready = 0; // 1 loop is enough. This could be useful if we
want to turn from udptl to RTP later.
- if ((inf = opbx_read(chan)) == NULL)
- {
- res = -1;
- break;
- }
+ }
+ t30_terminate(&fax.t30_state);
+ t30_terminate(&t38.t30_state);
+ fax_release(&fax);
- if (inf->frametype == OPBX_FRAME_VOICE
&& !call_is_t38_mode)
- {
- if (fax_rx(&fax, inf->data,
inf->samples))
- break;
- samples = (inf->samples <=
MAX_BLOCK_SIZE) ? inf->samples : MAX_BLOCK_SIZE;
- if ((len = fax_tx(&fax, (int16_t *)
&buf[OPBX_FRIENDLY_OFFSET], samples)))
- {
- opbx_fr_init_ex(&outf,
OPBX_FRAME_VOICE, OPBX_FORMAT_SLINEAR, "TxFAX");
- outf.datalen = len*sizeof(int16_t);
- outf.samples = len;
- outf.data =
&buf[OPBX_FRIENDLY_OFFSET];
- outf.offset = OPBX_FRIENDLY_OFFSET;
- if (opbx_write(chan, &outf) <
0)
- {
- opbx_log(LOG_WARNING, "Unable
to write frame to channel; %sn", strerror(errno));
- break;
- }
- }
- }
- else if (inf->frametype == OPBX_FRAME_MODEM
&& inf->subclass == OPBX_MODEM_T38)
- {
- //printf("T.38 frame
receivedn");
- if (!call_is_t38_mode)
- {
- call_is_t38_mode = TRUE;
- passage = now;
- }
- t38_core_rx_ifp_packet(&t38.t38,
inf->seq_no, inf->data, inf->datalen);
- }
- else
- {
- if (verbose)
- opbx_log(LOG_DEBUG," Unknown pkt
received: frametype: %d subclass: %d t38_mode: %dn",
- inf->frametype,
inf->subclass, call_is_t38_mode );
- }
- opbx_fr_free(inf);
- }
- if (inf == NULL)
- {
- opbx_log(LOG_DEBUG, "Got hangupn");
- res = -1;
- }
+ /* Restoring initial channel formats. */
- if (!call_is_t38_mode)
- t30_terminate(&fax.t30_state);
- else
- t30_terminate(&t38.t30_state);
-
- if (original_read_fmt != OPBX_FORMAT_SLINEAR)
- {
- if ((res = opbx_set_read_format(chan,
original_read_fmt)))
- opbx_log(LOG_WARNING, "Unable to
restore read format on '%s'n", chan->name);
- }
- if (original_write_fmt != OPBX_FORMAT_SLINEAR)
- {
- if ((res = opbx_set_write_format(chan,
original_write_fmt)))
- opbx_log(LOG_WARNING, "Unable to
restore write format on '%s'n", chan->name);
- }
- fax_release(&fax);
+ if (original_read_fmt != OPBX_FORMAT_SLINEAR)
+ {
+ if ((res = opbx_set_read_format(chan,
original_read_fmt)))
+ opbx_log(LOG_WARNING, "Unable to restore
read format on '%s'n", chan->name);
}
- else
+ if (original_write_fmt != OPBX_FORMAT_SLINEAR)
{
- opbx_log(LOG_WARNING, "Could not answer
channel '%s'n", chan->name);
+ if ((res = opbx_set_write_format(chan,
original_write_fmt)))
+ opbx_log(LOG_WARNING, "Unable to restore
write format on '%s'n", chan->name);
}
- LOCAL_USER_REMOVE(u);
- return res;
+
+ return ready;
+
}
/*- End of function
--------------------------------------------------------*/
_______________________________________________
Openpbx-svn mailing list
Openpbx-svn openpbx.org
http://lists.openpbx.org/mailman/listinfo/openpbx-svn
|