#include <asterisk.h>
#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/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"
Include dependency graph for app_txfax.c:
Go to the source code of this file.
Defines | |
#define | MAX_BLOCK_SIZE 240 |
Functions | |
AST_MODULE_INFO_STANDARD (ASTERISK_GPL_KEY,"Trivial FAX Transmit Application") | |
static int | load_module (void) |
static void | phase_e_handler (t30_state_t *s, void *user_data, int result) |
static void | span_message (int level, const char *msg) |
static int | txfax_exec (struct ast_channel *chan, void *data) |
static int | unload_module (void) |
Variables | |
static char * | app = "TxFAX" |
static char * | descrip |
static char * | synopsis = "Send a FAX file" |
#define MAX_BLOCK_SIZE 240 |
Definition at line 49 of file app_txfax.c.
AST_MODULE_INFO_STANDARD | ( | ASTERISK_GPL_KEY | , | |
"Trivial FAX Transmit Application" | ||||
) |
static int load_module | ( | void | ) | [static] |
Definition at line 267 of file app_txfax.c.
References app, ast_register_application(), descrip, synopsis, and txfax_exec().
00268 { 00269 return ast_register_application(app, txfax_exec, synopsis, descrip); 00270 }
static void phase_e_handler | ( | t30_state_t * | s, | |
void * | user_data, | |||
int | result | |||
) | [static] |
Definition at line 75 of file app_txfax.c.
References ast_log(), LOG_DEBUG, and pbx_builtin_setvar_helper().
00076 { 00077 struct ast_channel *chan; 00078 char far_ident[21]; 00079 00080 chan = (struct ast_channel *) user_data; 00081 if (result == T30_ERR_OK) { 00082 t30_get_far_ident(s, far_ident); 00083 pbx_builtin_setvar_helper(chan, "REMOTESTATIONID", far_ident); 00084 } else { 00085 ast_log(LOG_DEBUG, "==============================================================================\n"); 00086 ast_log(LOG_DEBUG, "Fax send not successful - result (%d) %s.\n", result, t30_completion_code_to_str(result)); 00087 ast_log(LOG_DEBUG, "==============================================================================\n"); 00088 } 00089 }
static void span_message | ( | int | level, | |
const char * | msg | |||
) | [static] |
Definition at line 51 of file app_txfax.c.
References __LOG_DEBUG, __LOG_WARNING, and ast_log().
00052 { 00053 int ast_level; 00054 00055 if (level == SPAN_LOG_WARNING) 00056 ast_level = __LOG_WARNING; 00057 else if (level == SPAN_LOG_WARNING) 00058 ast_level = __LOG_WARNING; 00059 else 00060 ast_level = __LOG_DEBUG; 00061 ast_log(ast_level, __FILE__, __LINE__, __PRETTY_FUNCTION__, msg); 00062 }
static int txfax_exec | ( | struct ast_channel * | chan, | |
void * | data | |||
) | [static] |
Definition at line 93 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_module_user_add, ast_module_user_remove, ast_read(), ast_set_read_format(), ast_set_write_format(), AST_STATE_UP, ast_waitfor(), ast_write(), ast_frame::data, errno, FALSE, ast_frame::frametype, len, LOG_DEBUG, LOG_WARNING, MAX_BLOCK_SIZE, 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().
00094 { 00095 int res = 0; 00096 char source_file[256]; 00097 char *s; 00098 char *t; 00099 char *v; 00100 const char *x; 00101 int option; 00102 int len; 00103 fax_state_t fax; 00104 int calling_party; 00105 int verbose; 00106 int samples; 00107 00108 struct ast_module_user *u; 00109 struct ast_frame *inf = NULL; 00110 struct ast_frame outf; 00111 00112 int original_read_fmt; 00113 int original_write_fmt; 00114 00115 uint8_t __buf[sizeof(uint16_t) * MAX_BLOCK_SIZE + 2 * AST_FRIENDLY_OFFSET]; 00116 uint8_t *buf = __buf + AST_FRIENDLY_OFFSET; 00117 00118 if (chan == NULL) { 00119 ast_log(LOG_WARNING, "Fax transmit channel is NULL. Giving up.\n"); 00120 return -1; 00121 } 00122 00123 span_set_message_handler(span_message); 00124 00125 /* The next few lines of code parse out the filename and header from the input string */ 00126 if (data == NULL) { 00127 /* No data implies no filename or anything is present */ 00128 ast_log(LOG_WARNING, "Txfax requires an argument (filename)\n"); 00129 return -1; 00130 } 00131 00132 calling_party = FALSE; 00133 verbose = FALSE; 00134 source_file[0] = '\0'; 00135 00136 for (option = 0, v = s = data; v; option++, s++) { 00137 t = s; 00138 v = strchr(s, '|'); 00139 s = (v) ? v : s + strlen(s); 00140 strncpy((char *) buf, t, s - t); 00141 buf[s - t] = '\0'; 00142 if (option == 0) { 00143 /* The first option is always the file name */ 00144 len = s - t; 00145 if (len > 255) 00146 len = 255; 00147 strncpy(source_file, t, len); 00148 source_file[len] = '\0'; 00149 } else if (strncmp("caller", t, s - t) == 0) { 00150 calling_party = TRUE; 00151 } else if (strncmp("debug", t, s - t) == 0) { 00152 verbose = TRUE; 00153 } 00154 } 00155 00156 /* Done parsing */ 00157 00158 u = ast_module_user_add(chan); 00159 00160 if (chan->_state != AST_STATE_UP) { 00161 /* Shouldn't need this, but checking to see if channel is already answered 00162 * Theoretically asterisk should already have answered before running the app */ 00163 res = ast_answer(chan); 00164 } 00165 00166 if (!res) { 00167 original_read_fmt = chan->readformat; 00168 if (original_read_fmt != AST_FORMAT_SLINEAR) { 00169 res = ast_set_read_format(chan, AST_FORMAT_SLINEAR); 00170 if (res < 0) { 00171 ast_log(LOG_WARNING, "Unable to set to linear read mode, giving up\n"); 00172 return -1; 00173 } 00174 } 00175 original_write_fmt = chan->writeformat; 00176 if (original_write_fmt != AST_FORMAT_SLINEAR) { 00177 res = ast_set_write_format(chan, AST_FORMAT_SLINEAR); 00178 if (res < 0) { 00179 ast_log(LOG_WARNING, "Unable to set to linear write mode, giving up\n"); 00180 res = ast_set_read_format(chan, original_read_fmt); 00181 if (res) 00182 ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", chan->name); 00183 return -1; 00184 } 00185 } 00186 fax_init(&fax, calling_party); 00187 if (verbose) 00188 fax.logging.level = SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW; 00189 00190 x = pbx_builtin_getvar_helper(chan, "LOCALSTATIONID"); 00191 if (x && x[0]) 00192 t30_set_local_ident(&fax.t30_state, x); 00193 x = pbx_builtin_getvar_helper(chan, "LOCALHEADERINFO"); 00194 if (x && x[0]) 00195 t30_set_header_info(&fax.t30_state, x); 00196 t30_set_tx_file(&fax.t30_state, source_file, -1, -1); 00197 //t30_set_phase_b_handler(&fax.t30_state, phase_b_handler, chan); 00198 //t30_set_phase_d_handler(&fax.t30_state, phase_d_handler, chan); 00199 t30_set_phase_e_handler(&fax.t30_state, phase_e_handler, chan); 00200 t30_set_ecm_capability(&fax.t30_state, TRUE); 00201 t30_set_supported_compressions(&fax.t30_state, T30_SUPPORT_T4_1D_COMPRESSION | T30_SUPPORT_T4_2D_COMPRESSION | T30_SUPPORT_T6_COMPRESSION); 00202 while (ast_waitfor(chan, -1) > -1) { 00203 inf = ast_read(chan); 00204 if (inf == NULL) { 00205 res = -1; 00206 break; 00207 } 00208 if (inf->frametype == AST_FRAME_VOICE) { 00209 if (fax_rx(&fax, inf->data, inf->samples)) 00210 break; 00211 samples = (inf->samples <= MAX_BLOCK_SIZE) ? inf->samples : MAX_BLOCK_SIZE; 00212 len = fax_tx(&fax, (int16_t *) & buf[AST_FRIENDLY_OFFSET], samples); 00213 if (len) { 00214 memset(&outf, 0, sizeof(outf)); 00215 outf.frametype = AST_FRAME_VOICE; 00216 outf.subclass = AST_FORMAT_SLINEAR; 00217 outf.datalen = len * sizeof(int16_t); 00218 outf.samples = len; 00219 outf.data = &buf[AST_FRIENDLY_OFFSET]; 00220 outf.offset = AST_FRIENDLY_OFFSET; 00221 if (ast_write(chan, &outf) < 0) { 00222 ast_log(LOG_WARNING, "Unable to write frame to channel; %s\n", strerror(errno)); 00223 break; 00224 } 00225 } 00226 } 00227 ast_frfree(inf); 00228 } 00229 if (inf == NULL) { 00230 ast_log(LOG_DEBUG, "Got hangup\n"); 00231 res = -1; 00232 } 00233 if (original_read_fmt != AST_FORMAT_SLINEAR) { 00234 res = ast_set_read_format(chan, original_read_fmt); 00235 if (res) 00236 ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", chan->name); 00237 } 00238 if (original_write_fmt != AST_FORMAT_SLINEAR) { 00239 res = ast_set_write_format(chan, original_write_fmt); 00240 if (res) 00241 ast_log(LOG_WARNING, "Unable to restore write format on '%s'\n", chan->name); 00242 } 00243 t30_terminate(&fax.t30_state); 00244 } else { 00245 ast_log(LOG_WARNING, "Could not answer channel '%s'\n", chan->name); 00246 } 00247 ast_module_user_remove(u); 00248 return res; 00249 }
static int unload_module | ( | void | ) | [static] |
Definition at line 253 of file app_txfax.c.
References app, ast_module_user_hangup_all, and ast_unregister_application().
00254 { 00255 int res; 00256 00257 ast_module_user_hangup_all(); 00258 00259 res = ast_unregister_application(app); 00260 00261 00262 return res; 00263 }
char* app = "TxFAX" [static] |
Definition at line 36 of file app_txfax.c.
char* descrip [static] |
Definition at line 40 of file app_txfax.c.
Definition at line 38 of file app_txfax.c.