Sat Sep 16 05:47:51 2006

Asterisk developer's documentation


app_txfax.c File Reference

#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <inttypes.h>
#include <pthread.h>
#include <errno.h>
#include <tiffio.h>
#include <spandsp.h>
#include "asterisk.h"
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/translate.h"

Go to the source code of this file.

Defines

#define MAX_BLOCK_SIZE   240

Functions

char * description (void)
 Provides a description of the module.
char * key (void)
 Returns the ASTERISK_GPL_KEY.
int load_module (void)
 Initialize the module.
static void phase_e_handler (t30_state_t *s, void *user_data, int result)
static void span_message (int level, const char *msg)
static void t30_flush (t30_state_t *s, int which)
static int txfax_exec (struct ast_channel *chan, void *data)
int unload_module (void)
 Cleanup all module structures, sockets, etc.
int usecount (void)
 Provides a usecount.

Variables

static char * app = "TxFAX"
static char * descrip
 LOCAL_USER_DECL
 STANDARD_LOCAL_USER
static char * synopsis = "Send a FAX file"
static char * tdesc = "Trivial FAX Transmit Application"


Define Documentation

#define MAX_BLOCK_SIZE   240

Definition at line 57 of file app_txfax.c.


Function Documentation

char* description ( void   ) 

Provides a description of the module.

Returns:
a short description of your module

Definition at line 293 of file app_txfax.c.

00294 {
00295     return tdesc;
00296 }

char* key ( void   ) 

Returns the ASTERISK_GPL_KEY.

This returns the ASTERISK_GPL_KEY, signifiying that you agree to the terms of the GPL stated in the ASTERISK_GPL_KEY. Your module will not load if it does not return the EXACT message:

 char *key(void) {
         return ASTERISK_GPL_KEY;
 }

Returns:
ASTERISK_GPL_KEY

Definition at line 308 of file app_txfax.c.

References ASTERISK_GPL_KEY.

00309 {
00310     return ASTERISK_GPL_KEY;
00311 }

int load_module ( void   ) 

Initialize the module.

Initialize the Agents module. This function is being called by Asterisk when loading the module. Among other thing it registers applications, cli commands and reads the cofiguration file.

Returns:
int Always 0.

Definition at line 287 of file app_txfax.c.

References ast_register_application(), and txfax_exec().

00288 {
00289     return ast_register_application(app, txfax_exec, synopsis, descrip);
00290 }

static void phase_e_handler ( t30_state_t *  s,
void *  user_data,
int  result 
) [static]

Definition at line 79 of file app_txfax.c.

References ast_log(), LOG_DEBUG, and pbx_builtin_setvar_helper().

00080 {
00081     struct ast_channel *chan;
00082     char far_ident[21];
00083     
00084     chan = (struct ast_channel *) user_data;
00085     if (result == T30_ERR_OK)
00086     {
00087         t30_get_far_ident(s, far_ident);
00088         pbx_builtin_setvar_helper(chan, "REMOTESTATIONID", far_ident);
00089     }
00090     else
00091     {
00092         ast_log(LOG_DEBUG, "==============================================================================\n");
00093         ast_log(LOG_DEBUG, "Fax send not successful - result (%d) %s.\n", result, t30_completion_code_to_str(result));
00094         ast_log(LOG_DEBUG, "==============================================================================\n");
00095     }
00096 }

static void span_message ( int  level,
const char *  msg 
) [static]

Definition at line 59 of file app_txfax.c.

References __LOG_DEBUG, __LOG_WARNING, and ast_log().

00060 {
00061     int ast_level;
00062     
00063     if (level == SPAN_LOG_WARNING)
00064         ast_level = __LOG_WARNING;
00065     else if (level == SPAN_LOG_WARNING)
00066         ast_level = __LOG_WARNING;
00067     else
00068         ast_level = __LOG_DEBUG;
00069     ast_log(ast_level, __FILE__, __LINE__, __PRETTY_FUNCTION__, msg);
00070 }

static void t30_flush ( t30_state_t *  s,
int  which 
) [static]

Definition at line 73 of file app_txfax.c.

00074 {
00075     //TODO:
00076 }

static int txfax_exec ( struct ast_channel chan,
void *  data 
) [static]

Definition at line 99 of file app_txfax.c.

References ast_channel::_state, ast_answer(), AST_FORMAT_SLINEAR, AST_FRAME_VOICE, ast_frfree(), AST_FRIENDLY_OFFSET, ast_log(), ast_read(), ast_set_read_format(), ast_set_write_format(), AST_STATE_UP, ast_waitfor(), ast_write(), ast_frame::data, FALSE, ast_frame::frametype, LOCAL_USER_ADD, LOCAL_USER_REMOVE, LOG_DEBUG, LOG_WARNING, MAX_BLOCK_SIZE, ast_channel::name, pbx_builtin_getvar_helper(), phase_e_handler(), ast_channel::readformat, s, ast_frame::samples, span_message(), t, TRUE, and ast_channel::writeformat.

Referenced by load_module().

00100 {
00101     int res = 0;
00102     char source_file[256];
00103     char *x;
00104     char *s;
00105     char *t;
00106     char *v;
00107     int option;
00108     int len;
00109     t30_state_t fax;
00110     int calling_party;
00111     int verbose;
00112     int samples;
00113     
00114     struct localuser *u;
00115     struct ast_frame *inf = NULL;
00116     struct ast_frame outf;
00117 
00118     int original_read_fmt;
00119     int original_write_fmt;
00120     
00121     uint8_t __buf[sizeof(uint16_t)*MAX_BLOCK_SIZE + 2*AST_FRIENDLY_OFFSET];
00122     uint8_t *buf = __buf + AST_FRIENDLY_OFFSET;
00123 
00124     if (chan == NULL)
00125     {
00126         ast_log(LOG_WARNING, "Fax transmit channel is NULL. Giving up.\n");
00127         return -1;
00128     }
00129 
00130     span_set_message_handler(span_message);
00131 
00132     /* The next few lines of code parse out the filename and header from the input string */
00133     if (data == NULL)
00134     {
00135         /* No data implies no filename or anything is present */
00136         ast_log(LOG_WARNING, "Txfax requires an argument (filename)\n");
00137         return -1;
00138     }
00139     
00140     calling_party = FALSE;
00141     verbose = FALSE;
00142     source_file[0] = '\0'; 
00143 
00144     for (option = 0, v = s = data;  v;  option++, s++)
00145     {
00146         t = s;
00147         v = strchr(s, '|');
00148         s = (v)  ?  v  :  s + strlen(s);
00149         strncpy((char *) buf, t, s - t);
00150         buf[s - t] = '\0';
00151         if (option == 0)
00152         {
00153             /* The first option is always the file name */
00154             len = s - t;
00155             if (len > 255)
00156                 len = 255;
00157             strncpy(source_file, t, len);
00158             source_file[len] = '\0';
00159         }
00160         else if (strncmp("caller", t, s - t) == 0)
00161         {
00162             calling_party = TRUE;
00163         }
00164         else if (strncmp("debug", t, s - t) == 0)
00165         {
00166             verbose = TRUE;
00167         }
00168     }
00169 
00170     /* Done parsing */
00171 
00172     LOCAL_USER_ADD(u);
00173 
00174     if (chan->_state != AST_STATE_UP)
00175     {
00176         /* Shouldn't need this, but checking to see if channel is already answered
00177          * Theoretically asterisk should already have answered before running the app */
00178         res = ast_answer(chan);
00179     }
00180     
00181     if (!res)
00182     {
00183         original_read_fmt = chan->readformat;
00184         if (original_read_fmt != AST_FORMAT_SLINEAR)
00185         {
00186             res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
00187             if (res < 0)
00188             {
00189                 ast_log(LOG_WARNING, "Unable to set to linear read mode, giving up\n");
00190                 return -1;
00191             }
00192         }
00193         original_write_fmt = chan->writeformat;
00194         if (original_write_fmt != AST_FORMAT_SLINEAR)
00195         {
00196             res = ast_set_write_format(chan, AST_FORMAT_SLINEAR);
00197             if (res < 0)
00198             {
00199                 ast_log(LOG_WARNING, "Unable to set to linear write mode, giving up\n");
00200                 res = ast_set_read_format(chan, original_read_fmt);
00201                 if (res)
00202                     ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", chan->name);
00203                 return -1;
00204             }
00205         }
00206         fax_init(&fax, calling_party, NULL);
00207         if (verbose)
00208        fax.logging.level = SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW;
00209 
00210         x = pbx_builtin_getvar_helper(chan, "LOCALSTATIONID");
00211         if (x  &&  x[0])
00212             t30_set_local_ident(&fax, x);
00213         x = pbx_builtin_getvar_helper(chan, "LOCALHEADERINFO");
00214         if (x  &&  x[0])
00215             t30_set_header_info(&fax, x);
00216         t30_set_tx_file(&fax, source_file, -1, -1);
00217         //t30_set_phase_b_handler(&fax, phase_b_handler, chan);
00218         //t30_set_phase_d_handler(&fax, phase_d_handler, chan);
00219         t30_set_phase_e_handler(&fax, phase_e_handler, chan);
00220         while (ast_waitfor(chan, -1) > -1)
00221         {
00222             inf = ast_read(chan);
00223             if (inf == NULL)
00224             {
00225                 res = -1;
00226                 break;
00227             }
00228             if (inf->frametype == AST_FRAME_VOICE)
00229             {
00230                 if (fax_rx(&fax, inf->data, inf->samples))
00231                     break;
00232                 samples = (inf->samples <= MAX_BLOCK_SIZE)  ?  inf->samples  :  MAX_BLOCK_SIZE;
00233                 len = fax_tx(&fax, (int16_t *) &buf[AST_FRIENDLY_OFFSET], samples);
00234                 if (len)
00235                 {
00236                     memset(&outf, 0, sizeof(outf));
00237                     outf.frametype = AST_FRAME_VOICE;
00238                     outf.subclass = AST_FORMAT_SLINEAR;
00239                     outf.datalen = len*sizeof(int16_t);
00240                     outf.samples = len;
00241                     outf.data = &buf[AST_FRIENDLY_OFFSET];
00242                     outf.offset = AST_FRIENDLY_OFFSET;
00243                     if (ast_write(chan, &outf) < 0)
00244                     {
00245                         ast_log(LOG_WARNING, "Unable to write frame to channel; %s\n", strerror(errno));
00246                         break;
00247                     }
00248                 }
00249             }
00250             ast_frfree(inf);
00251         }
00252         if (inf == NULL)
00253         {
00254             ast_log(LOG_DEBUG, "Got hangup\n");
00255             res = -1;
00256         }
00257         if (original_read_fmt != AST_FORMAT_SLINEAR)
00258         {
00259             res = ast_set_read_format(chan, original_read_fmt);
00260             if (res)
00261                 ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", chan->name);
00262         }
00263         if (original_write_fmt != AST_FORMAT_SLINEAR)
00264         {
00265             res = ast_set_write_format(chan, original_write_fmt);
00266             if (res)
00267                 ast_log(LOG_WARNING, "Unable to restore write format on '%s'\n", chan->name);
00268         }
00269         fax_release(&fax);
00270     }
00271     else
00272     {
00273         ast_log(LOG_WARNING, "Could not answer channel '%s'\n", chan->name);
00274     }
00275     LOCAL_USER_REMOVE(u);
00276     return res;
00277 }

int unload_module ( void   ) 

Cleanup all module structures, sockets, etc.

This is called at exit. Any registrations and memory allocations need to be unregistered and free'd here. Nothing else will do these for you (until exit).

Returns:
Zero on success, or non-zero on error.

Definition at line 280 of file app_txfax.c.

References ast_unregister_application(), and STANDARD_HANGUP_LOCALUSERS.

00281 {
00282     STANDARD_HANGUP_LOCALUSERS;
00283     return ast_unregister_application(app);
00284 }

int usecount ( void   ) 

Provides a usecount.

This function will be called by various parts of asterisk. Basically, all it has to do is to return a usecount when called. You will need to maintain your usecount within the module somewhere. The usecount should be how many channels provided by this module are in use.

Returns:
The module's usecount.

Definition at line 299 of file app_txfax.c.

References STANDARD_USECOUNT.

00300 {
00301     int res;
00302 
00303     STANDARD_USECOUNT(res);
00304     return res;
00305 }


Variable Documentation

char* app = "TxFAX" [static]

Definition at line 38 of file app_txfax.c.

char* descrip [static]

Definition at line 42 of file app_txfax.c.

LOCAL_USER_DECL

Definition at line 55 of file app_txfax.c.

STANDARD_LOCAL_USER

Definition at line 53 of file app_txfax.c.

char* synopsis = "Send a FAX file" [static]

Definition at line 40 of file app_txfax.c.

char* tdesc = "Trivial FAX Transmit Application" [static]

Definition at line 36 of file app_txfax.c.


Generated on Sat Sep 16 05:47:51 2006 for Asterisk - the Open Source PBX by  doxygen 1.4.7