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