]> git.pld-linux.org Git - packages/asterisk.git/blame - app_rxfax.c
up to 10.12.2
[packages/asterisk.git] / app_rxfax.c
CommitLineData
d7e66fb6 1/*
b568f055
CM
2 * Application to receive a TIFF FAX file
3 * based on app_rxfax.c from: Copyright (C) 2003, Steve Underwood <steveu@coppice.org>
4 * based on app_rxfax.c from www.callweaver.org
5 * PATCHED BY (C) 20007 by Antonio Gallo <agx@linux.it>
6 * - added ECM support
7 * - added more env variables
d7e66fb6 8 *
d7e66fb6 9 */
b568f055
CM
10
11/*** MODULEINFO
12Depends: libspandsp
13Desciption: Receive a FAX to a file
14DisplayName: RxFAX
15 ***/
16
17#include "asterisk.h"
18
19ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
20
d7e66fb6 21#include <string.h>
b568f055 22#include <stdarg.h>
d7e66fb6 23#include <stdlib.h>
24#include <stdio.h>
25#include <inttypes.h>
26#include <pthread.h>
27#include <errno.h>
28#include <tiffio.h>
29
30#include <spandsp.h>
b568f055 31#include <spandsp/version.h>
d7e66fb6 32
33#include "asterisk/lock.h"
34#include "asterisk/file.h"
35#include "asterisk/logger.h"
36#include "asterisk/channel.h"
37#include "asterisk/pbx.h"
38#include "asterisk/module.h"
d7e66fb6 39#include "asterisk/manager.h"
40
b568f055
CM
41#ifndef AST_MODULE
42#define AST_MODULE "app_rxfax"
43#endif
d7e66fb6 44
45static char *app = "RxFAX";
46
47static char *synopsis = "Receive a FAX to a file";
48
49static char *descrip =
b568f055
CM
50 " RxFAX(filename[|caller][|debug]): Receives a FAX from the channel into the\n"
51 "given filename. If the file exists it will be overwritten. The file\n"
52 "should be in TIFF/F format.\n"
53 "The \"caller\" option makes the application behave as a calling machine,\n"
54 "rather than the answering machine. The default behaviour is to behave as\n"
55 "an answering machine.\n"
56 "The \"ecm\" option enables ECM.\n"
57 "Uses LOCALSTATIONID to identify itself to the remote end.\n"
58 " LOCALSUBADDRESS to specify a sub-address to the remote end.\n"
59 " LOCALHEADERINFO to generate a header line on each page.\n"
60
61 " FAX_FORCE_V17 to force V.17 only\n"
62 " FAX_FORCE_V27 to force V.27 only\n"
63 " FAX_FORCE_V29 to force V.29 only\n"
64 " FAX_FORCE_V34 to force V.34 only\n"
65
66 "Sets REMOTESTATIONID to the sender CSID.\n"
67 " FAXPAGES to the number of pages received.\n"
68 " FAXBITRATE to the transmition rate.\n"
69 " FAXRESOLUTION to the resolution.\n"
70 " PHASEESTATUS to the phase E result status.\n"
71 " PHASEESTRING to the phase E result string.\n"
72 "Note that PHASEESTATUS=0 means that the fax was handled correctly. But that doesn't\n"
73 "imply that any pages were sent. Actually you should also check FAXPAGES to be\n"
74 "greater than zero.\n"
75 "Returns -1 when the user hangs up.\n"
76 "Returns 0 otherwise.\n";
d7e66fb6 77
78#define MAX_BLOCK_SIZE 240
79
b568f055
CM
80static FILE *rxfax_logfile = NULL;
81
82static void file_log(const char *msg)
83{
84 if (msg==NULL)
85 return;
86 if (rxfax_logfile==NULL)
87 return;
88 fprintf(rxfax_logfile, msg);
89}
90
d7e66fb6 91static void span_message(int level, const char *msg)
92{
b568f055
CM
93 if (msg==NULL) return;
94 int ast_level;
95 if (level == SPAN_LOG_ERROR)
96 ast_level = __LOG_ERROR;
97 else if (level == SPAN_LOG_WARNING)
98 ast_level = __LOG_WARNING;
99 else
100 ast_level = __LOG_DEBUG;
101 ast_log(ast_level, _A_, "%s", msg);
102 file_log(msg);
d7e66fb6 103}
b568f055 104
d7e66fb6 105/*- End of function --------------------------------------------------------*/
106
b568f055 107static int phase_b_handler(t30_state_t *s, void *user_data, int result)
d7e66fb6 108{
b568f055
CM
109 if (rxfax_logfile!=NULL) {
110 fprintf( rxfax_logfile, "[phase_b_handler] mark\n" );
111 fflush(rxfax_logfile);
112 }
113 return T30_ERR_OK;
d7e66fb6 114}
d7e66fb6 115
b568f055 116/*- End of function --------------------------------------------------------*/
d7e66fb6 117static void phase_e_handler(t30_state_t *s, void *user_data, int result)
118{
b568f055
CM
119 struct ast_channel *chan;
120 const char *tx_ident;
121 const char *rx_ident;
122 char buf[128];
123 t30_stats_t t;
124
125 chan = (struct ast_channel *) user_data;
126 t30_get_transfer_statistics(s, &t);
127
128 tx_ident = t30_get_tx_ident(s);
129 if (tx_ident == NULL)
130 tx_ident = "";
131 rx_ident = t30_get_rx_ident(s);
132 if (rx_ident == NULL)
133 rx_ident = "";
134 pbx_builtin_setvar_helper(chan, "REMOTESTATIONID", rx_ident);
135 snprintf(buf, sizeof(buf), "%d", t.pages_transferred);
136 pbx_builtin_setvar_helper(chan, "FAXPAGES", buf);
137 snprintf(buf, sizeof(buf), "%d", t.y_resolution);
138 pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", buf);
139 snprintf(buf, sizeof(buf), "%d", t.bit_rate);
140 pbx_builtin_setvar_helper(chan, "FAXBITRATE", buf);
141 snprintf(buf, sizeof(buf), "%d", result);
142 pbx_builtin_setvar_helper(chan, "PHASEESTATUS", buf);
143 snprintf(buf, sizeof(buf), "%s", t30_completion_code_to_str(result));
144 pbx_builtin_setvar_helper(chan, "PHASEESTRING", buf);
145
146 ast_log(LOG_DEBUG, "==============================================================================\n");
147 if (result == T30_ERR_OK)
148 {
149 ast_log(LOG_DEBUG, "Fax successfully received.\n");
150 ast_log(LOG_DEBUG, "Remote station id: %s\n", rx_ident);
151 ast_log(LOG_DEBUG, "Local station id: %s\n", tx_ident);
152 ast_log(LOG_DEBUG, "Pages transferred: %i\n", t.pages_transferred);
153 ast_log(LOG_DEBUG, "Image resolution: %i x %i\n", t.x_resolution, t.y_resolution);
154 ast_log(LOG_DEBUG, "Transfer Rate: %i\n", t.bit_rate);
155 manager_event(EVENT_FLAG_CALL,
156 "FaxReceived", "Channel: %s\nExten: %s\nCallerID: %s\nRemoteStationID: %s\nLocalStationID: %s\nPagesTransferred: %i\nResolution: %i\nTransferRate: %i\nFileName: %s\n",
157 chan->name,
158 chan->exten,
159 (chan->cid.cid_num) ? chan->cid.cid_num : "",
160 rx_ident,
161 tx_ident,
162 t.pages_transferred,
163 t.y_resolution,
164 t.bit_rate,
165 s->rx_file);
166 if (rxfax_logfile!=NULL) {
167 fprintf( rxfax_logfile, "\n[FAX OK] Remote: %s Local: %s Pages: %i Speed: %i\n\n",
168 rx_ident, tx_ident, t.pages_transferred, t.bit_rate
169 );
170 fflush(rxfax_logfile);
171 }
172 }
173 else
174 {
175 ast_log(LOG_DEBUG, "Fax receive not successful - result (%d) %s.\n", result, t30_completion_code_to_str(result));
176 if (rxfax_logfile!=NULL) {
177 fprintf( rxfax_logfile, "\n[FAX ERROR] code: %d %s\n\n", result, t30_completion_code_to_str(result) );
178 fflush(rxfax_logfile);
179 }
180 }
181 ast_log(LOG_DEBUG, "==============================================================================\n");
d7e66fb6 182}
183/*- End of function --------------------------------------------------------*/
184
b568f055 185static int phase_d_handler(t30_state_t *s, void *user_data, int result)
d7e66fb6 186{
b568f055
CM
187 struct ast_channel *chan;
188 t30_stats_t t;
189
190 chan = (struct ast_channel *) user_data;
191 if (result)
192 {
193 t30_get_transfer_statistics(s, &t);
194 ast_log(LOG_DEBUG, "==============================================================================\n");
195 ast_log(LOG_DEBUG, "Pages transferred: %i\n", t.pages_transferred);
196 ast_log(LOG_DEBUG, "Image size: %i x %i\n", t.width, t.length);
197 ast_log(LOG_DEBUG, "Image resolution %i x %i\n", t.x_resolution, t.y_resolution);
198 ast_log(LOG_DEBUG, "Transfer Rate: %i\n", t.bit_rate);
199 ast_log(LOG_DEBUG, "Bad rows %i\n", t.bad_rows);
200 ast_log(LOG_DEBUG, "Longest bad row run %i\n", t.longest_bad_row_run);
201 ast_log(LOG_DEBUG, "Compression type %s\n", t4_encoding_to_str(t.encoding));
202 ast_log(LOG_DEBUG, "Image size (bytes) %i\n", t.image_size);
203 ast_log(LOG_DEBUG, "==============================================================================\n");
204 if (rxfax_logfile!=NULL) {
205 fprintf( rxfax_logfile, "\n[phase_d_handler] Page: %i at %i\n\n", t.pages_transferred, t.bit_rate );
206 fflush(rxfax_logfile);
207 }
208 }
209 return T30_ERR_OK;
d7e66fb6 210}
211/*- End of function --------------------------------------------------------*/
212
213static int rxfax_exec(struct ast_channel *chan, void *data)
214{
b568f055
CM
215 int res = 0;
216 char target_file[256];
217 char template_file[256];
218 int samples;
219 char *s;
220 char *t;
221 char *v;
222 const char *x;
223 int option;
224 int len;
225 int i;
226 fax_state_t fax;
227 struct ast_frame *inf = NULL;
228 struct ast_frame outf;
229 int calling_party;
230 int verbose;
231 int ecm = FALSE;
d7e66fb6 232
b568f055 233 struct ast_module_user *u;
d7e66fb6 234
b568f055
CM
235 int original_read_fmt;
236 int original_write_fmt;
d7e66fb6 237
b568f055
CM
238
239 /* Basic initial checkings */
240
241 if (chan == NULL) {
242 ast_log(LOG_WARNING, "Fax receive channel is NULL. Giving up.\n");
243 file_log("FATAL ERROR: Fax receive channel is NULL. Giving up.\n");
244 return -1;
245 }
246
247 //span_set_message_handler(span_message);
248 /* make sure they are initialized to zero */
249 memset( &fax, 0, sizeof(fax));
250
251 /* Resetting channel variables related to T38 */
252 pbx_builtin_setvar_helper(chan, "REMOTESTATIONID", "");
253 pbx_builtin_setvar_helper(chan, "FAXPAGES", "");
254 pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", "");
255 pbx_builtin_setvar_helper(chan, "FAXBITRATE", "");
256 pbx_builtin_setvar_helper(chan, "PHASEESTATUS", "");
257 pbx_builtin_setvar_helper(chan, "PHASEESTRING", "");
258
259 /* Parsig parameters */
260
261 /* The next few lines of code parse out the filename and header from the input string */
262 if (data == NULL)
263 {
264 /* No data implies no filename or anything is present */
265 ast_log(LOG_WARNING, "Rxfax requires an argument (filename)\n");
266 file_log("ERROR: Rxfax requires an argument (filename)\n");
267 return -1;
268 }
269
270 calling_party = FALSE;
271 verbose = FALSE;
272 target_file[0] = '\0';
273
274 char tbuf[256];
275 for (option = 0, v = s = data; v; option++, s++) {
276 t = s;
277 v = strchr(s, '|');
278 s = (v) ? v : s + strlen(s);
279 strncpy((char *) tbuf, t, s - t);
280 tbuf[s - t] = '\0';
281 if (option == 0) {
282 /* The first option is always the file name */
283 len = s - t;
284 if (len > 255)
285 len = 255;
286 strncpy(target_file, t, len);
287 target_file[len] = '\0';
288 /* Allow the use of %d in the file name for a wild card of sorts, to
289 create a new file with the specified name scheme */
290 if ((x = strchr(target_file, '%')) && x[1] == 'd') {
291 strcpy(template_file, target_file);
292 i = 0;
293 do {
294 snprintf(target_file, 256, template_file, 1);
295 i++;
296 } while (ast_fileexists(target_file, "", chan->language) != -1);
297 }
298 } else if (strncmp("caller", t, s - t) == 0) {
299 calling_party = TRUE;
300 } else if (strncmp("debug", t, s - t) == 0) {
301 verbose = TRUE;
302 } else if (strncmp("ecm", t, s - t) == 0) {
303 ecm = TRUE;
304 }
305 }
306
307 /* Done parsing */
308
309 u = ast_module_user_add(chan);
310
311 if (chan->_state != AST_STATE_UP)
312 {
313 /* Shouldn't need this, but checking to see if channel is already answered
314 * Theoretically the PBX should already have answered before running the app */
315 res = ast_answer(chan);
316 /* NO NEED TO WARN ANYMORE
317 if (!res)
318 {
319 ast_log(LOG_WARNING, "Could not answer channel '%s'\n", chan->name);
320 file_log("Could not answer channel\n" );
321 }
322 */
323 }
324
325 /* Setting read and write formats */
326
327 original_read_fmt = chan->readformat;
328 if (original_read_fmt != AST_FORMAT_SLINEAR)
329 {
330 res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
331 if (res < 0)
332 {
333 ast_log(LOG_WARNING, "Unable to set to linear read mode, giving up\n");
334 file_log("ERROR: Unable to set to linear read mode, giving up\n");
335 ast_module_user_remove(u);
336 return -1;
337 }
338 }
339
340 original_write_fmt = chan->writeformat;
341 if (original_write_fmt != AST_FORMAT_SLINEAR)
342 {
343 res = ast_set_write_format(chan, AST_FORMAT_SLINEAR);
344 if (res < 0)
345 {
346 ast_log(LOG_WARNING, "Unable to set to linear write mode, giving up\n");
347 file_log("ERROR: Unable to set to linear write mode, giving up\n");
348 res = ast_set_read_format(chan, original_read_fmt);
349 if (res)
350 ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", chan->name);
351 ast_module_user_remove(u);
352 return -1;
353 }
354 }
355
356 /* Remove any app level gain adjustments and disable echo cancel. */
357 signed char sc;
358 sc = 0;
359 ast_channel_setoption(chan, AST_OPTION_RXGAIN, &sc, sizeof(sc), 0);
360 ast_channel_setoption(chan, AST_OPTION_TXGAIN, &sc, sizeof(sc), 0);
361 ast_channel_setoption(chan, AST_OPTION_ECHOCAN, &sc, sizeof(sc), 0);
362
363 /* This is the main loop */
364
365 uint8_t __buf[sizeof(uint16_t)*MAX_BLOCK_SIZE + 2*AST_FRIENDLY_OFFSET];
366 uint8_t *buf = __buf + AST_FRIENDLY_OFFSET;
367
368 memset(&fax, 0, sizeof(fax));
369
370 if (fax_init(&fax, calling_party) == NULL)
371 {
372 ast_log(LOG_WARNING, "Unable to set to start fax_init\n");
373 file_log("ERROR: Unable to set to start fax_init\n");
374 ast_module_user_remove(u);
375 return -1;
376 }
377 fax_set_transmit_on_idle(&fax, TRUE);
378 span_log_set_message_handler(&fax.logging, span_message);
379 span_log_set_message_handler(&fax.t30_state.logging, span_message);
380 if (verbose)
381 {
382 span_log_set_level(&fax.logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW);
383 span_log_set_level(&fax.t30_state.logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW);
384 }
385 x = pbx_builtin_getvar_helper(chan, "LOCALSTATIONID");
386 if (x && x[0])
387 t30_set_tx_ident(&fax.t30_state, x);
388 x = pbx_builtin_getvar_helper(chan, "LOCALSUBADDRESS");
389 if (x && x[0])
390 t30_set_tx_sub_address(&fax.t30_state, x);
391 x = pbx_builtin_getvar_helper(chan, "LOCALHEADERINFO");
392 if (x && x[0])
393 t30_set_tx_page_header_info(&fax.t30_state, x);
394 t30_set_rx_file(&fax.t30_state, target_file, -1);
395 t30_set_phase_b_handler(&fax.t30_state, phase_b_handler, chan);
396 t30_set_phase_d_handler(&fax.t30_state, phase_d_handler, chan);
397 t30_set_phase_e_handler(&fax.t30_state, phase_e_handler, chan);
398
399 // Default Support ALL
400 t30_set_supported_modems(&(fax.t30_state), T30_SUPPORT_V29 | T30_SUPPORT_V27TER | T30_SUPPORT_V17 );
401
402 x = pbx_builtin_getvar_helper(chan, "FAX_DISABLE_V17");
403 if (x && x[0])
404 t30_set_supported_modems(&(fax.t30_state), T30_SUPPORT_V29 | T30_SUPPORT_V27TER);
405
406 x = pbx_builtin_getvar_helper(chan, "FAX_FORCE_V17");
407 if (x && x[0])
408 t30_set_supported_modems(&(fax.t30_state), T30_SUPPORT_V17);
409 x = pbx_builtin_getvar_helper(chan, "FAX_FORCE_V27");
410 if (x && x[0])
411 t30_set_supported_modems(&(fax.t30_state), T30_SUPPORT_V27TER);
412 x = pbx_builtin_getvar_helper(chan, "FAX_FORCE_V29");
413 if (x && x[0])
414 t30_set_supported_modems(&(fax.t30_state), T30_SUPPORT_V29);
415 x = pbx_builtin_getvar_helper(chan, "FAX_FORCE_V34");
416 if (x && x[0])
417 t30_set_supported_modems(&(fax.t30_state), T30_SUPPORT_V34);
418
419 /* Support for different image sizes && resolutions*/
420 t30_set_supported_image_sizes(&fax.t30_state, T30_SUPPORT_US_LETTER_LENGTH | T30_SUPPORT_US_LEGAL_LENGTH | T30_SUPPORT_UNLIMITED_LENGTH
421 | T30_SUPPORT_215MM_WIDTH | T30_SUPPORT_255MM_WIDTH | T30_SUPPORT_303MM_WIDTH);
422 t30_set_supported_resolutions(&fax.t30_state, T30_SUPPORT_STANDARD_RESOLUTION | T30_SUPPORT_FINE_RESOLUTION | T30_SUPPORT_SUPERFINE_RESOLUTION
423 | T30_SUPPORT_R8_RESOLUTION | T30_SUPPORT_R16_RESOLUTION);
424 if (ecm) {
425 t30_set_ecm_capability(&(fax.t30_state), TRUE);
426 t30_set_supported_compressions(&(fax.t30_state), T30_SUPPORT_T4_1D_COMPRESSION | T30_SUPPORT_T4_2D_COMPRESSION | T30_SUPPORT_T6_COMPRESSION);
427 ast_log(LOG_DEBUG, "Enabling ECM mode for app_rxfax\n" );
428 file_log("DEBUG: Enabling ECM mode for app_rxfax\n" );
429 } else {
430 t30_set_ecm_capability(&(fax.t30_state), FALSE);
431 t30_set_supported_compressions(&(fax.t30_state), T30_SUPPORT_T4_1D_COMPRESSION | T30_SUPPORT_T4_2D_COMPRESSION );
432 }
433
434
435 /* This is the main loop */
436
437 res = 0;
438
439 /* temporary workwaround vars */
440 int donotspam=10;
441 int watchdog=256;
442
443 while ( chan )
444 {
445 if (ast_check_hangup(chan)) {
446 ast_log(LOG_WARNING, "Channel has been hanged at fax.\n");
447 file_log("INFO: Channel has been hanged at fax.\n");
448 res = 0;
449 break;
450 }
451
452 if ((res = ast_waitfor(chan, 20)) < 0) {
453 ast_log(LOG_WARNING, "Channel ast_waitfor < 0.\n");
454 file_log("WARNING: Channel ast_waitfor < 0.\n");
455 res = 0;
456 break;
457 }
458
459 if ((fax.current_rx_type == T30_MODEM_DONE) || (fax.current_tx_type == T30_MODEM_DONE)) {
460 /* Avoid spamming debug info */
461 if (donotspam>0) {
462 ast_log(LOG_WARNING, "Channel T30 DONE < 0.\n");
463 file_log("DEBUG: Channel T30 DONE.\n");
464 donotspam--;
465 }
466 /*
467 * NOTE: if i break here it seems to have bad behavios on some faxes that
468 * will not result as successfull send even if it has benn fully received
469 */
470/*JUST WARNING: res = 0;
471 break;*/
472 /*
473 * Workaround: let 256 more packet to pass thru then definitively hangup
474 */
475 if (watchdog>0) {
476 watchdog--;
477 } else {
478 break;
479 }
480 }
481
482 inf = ast_read(chan);
483 if (inf == NULL)
484 {
485 ast_log(LOG_WARNING, "Channel INF is NULL.\n");
486 file_log("DEBUG: Channel INF is NULL.\n");
487
488 // While trasmiitting i got: Received a DCN from remote after sending a page
489 // at last page
490 continue;
491 //res = 0;
492 //break;
493 }
494
495 /* We got a frame */
496 //if (inf->frametype == AST_FRAME_VOICE) {
497 /* Check the frame type. Format also must be checked because there is a chance
498 that a frame in old format was already queued before we set chanel format
499 to slinear so it will still be received by ast_read */
500 if (inf->frametype == AST_FRAME_VOICE && inf->subclass == AST_FORMAT_SLINEAR) {
501 if (fax_rx(&fax, inf->data, inf->samples)) {
502 ast_log(LOG_WARNING, "RXFAX: fax_rx returned error\n");
503 res = -1;
504 break;
505 }
506
507 samples = (inf->samples <= MAX_BLOCK_SIZE) ? inf->samples : MAX_BLOCK_SIZE;
508 len = fax_tx(&fax, (int16_t *) &buf[AST_FRIENDLY_OFFSET], samples);
509 if (len>0) {
510 /*if (len <= 0) {
511 ast_log(LOG_WARNING, "len <=0 using samples.\n");
512 file_log("len <= 0 using samples.\n");
513 len = samples;
514 }*/
515 memset(&outf, 0, sizeof(outf));
516 outf.frametype = AST_FRAME_VOICE;
517 outf.subclass = AST_FORMAT_SLINEAR;
518 outf.datalen = len*sizeof(int16_t);
519 outf.samples = len;
520 outf.data = &buf[AST_FRIENDLY_OFFSET];
521 outf.offset = AST_FRIENDLY_OFFSET;
522 outf.src = "RxFAX";
523 /*if (len <= 0) {
524 memset(&buf[AST_FRIENDLY_OFFSET], 0, outf.datalen);
525 }*/
526 if (ast_write(chan, &outf) < 0)
527 {
528 ast_log(LOG_WARNING, "Unable to write frame to channel; %s\n", strerror(errno));
529 file_log("ERROR: Unable to write frame to channel\n");
530 res = -1;
531 break;
532 }
533 }
534 }
535 ast_frfree(inf);
536 inf = NULL;
537 /* TODO put a Watchdog here */
538 }
539
540 if (inf != NULL)
541 {
542 ast_frfree(inf);
543 inf = NULL;
544 }
545
546 t30_terminate(&fax.t30_state);
547 fax_release(&fax);
548
549 /* Restoring initial channel formats. */
550
551 if (original_read_fmt != AST_FORMAT_SLINEAR)
552 {
553 res = ast_set_read_format(chan, original_read_fmt);
554 if (res)
555 ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", chan->name);
556 }
557 if (original_write_fmt != AST_FORMAT_SLINEAR)
558 {
559 res = ast_set_write_format(chan, original_write_fmt);
560 if (res)
561 ast_log(LOG_WARNING, "Unable to restore write format on '%s'\n", chan->name);
562 }
563 ast_module_user_remove(u);
564 return res;
d7e66fb6 565}
566/*- End of function --------------------------------------------------------*/
567
b568f055 568static int unload_module(void)
d7e66fb6 569{
b568f055
CM
570 int res;
571 ast_module_user_hangup_all();
572 res = ast_unregister_application(app);
573 if (rxfax_logfile) {
574 fclose(rxfax_logfile);
575 rxfax_logfile = NULL;
576 }
577 return res;
d7e66fb6 578}
579/*- End of function --------------------------------------------------------*/
580
b568f055 581static int load_module(void)
d7e66fb6 582{
b568f055
CM
583 ast_log(LOG_NOTICE, "RxFax using spandsp %i %i\n", SPANDSP_RELEASE_DATE, SPANDSP_RELEASE_TIME );
584 rxfax_logfile = fopen("/var/log/rxfax.log", "w+" );
585 if (rxfax_logfile)
586 ast_log(LOG_WARNING, "RxFax output also available in /var/log/rxfax.log\n" );
587 return ast_register_application(app, rxfax_exec, synopsis, descrip);
d7e66fb6 588}
589/*- End of function --------------------------------------------------------*/
b568f055
CM
590
591AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Trivial FAX Receive Application");
592
d7e66fb6 593/*- End of file ------------------------------------------------------------*/
This page took 0.399458 seconds and 4 git commands to generate.