]> git.pld-linux.org Git - packages/asterisk.git/blob - asterisk-t30.patch
- adapterized (sorted %verify attrs)
[packages/asterisk.git] / asterisk-t30.patch
1 diff -urN asterisk-1.0.9-o/apps/app_rxfax.c asterisk-1.0.9-n/apps/app_rxfax.c
2 --- asterisk-1.0.9-o/apps/app_rxfax.c   1969-12-31 17:00:00.000000000 -0700
3 +++ asterisk-1.0.9-n/apps/app_rxfax.c   2005-09-20 13:01:02.000000000 -0600
4 @@ -0,0 +1,367 @@
5 +/*
6 + * Asterisk -- A telephony toolkit for Linux.
7 + *
8 + * Trivial application to receive a TIFF FAX file
9 + * 
10 + * Copyright (C) 2003, Steve Underwood
11 + *
12 + * Steve Underwood <steveu@coppice.org>
13 + *
14 + * This program is free software, distributed under the terms of
15 + * the GNU General Public License
16 + */
17
18 +#include <asterisk/lock.h>
19 +#include <asterisk/file.h>
20 +#include <asterisk/logger.h>
21 +#include <asterisk/channel.h>
22 +#include <asterisk/pbx.h>
23 +#include <asterisk/module.h>
24 +#include <asterisk/translate.h>
25 +#include <asterisk/dsp.h>
26 +#include <asterisk/manager.h>
27 +#include <string.h>
28 +#include <stdlib.h>
29 +#include <stdint.h>
30 +#include <pthread.h>
31 +#include <errno.h>
32 +#include <tiffio.h>
33 +
34 +#include <spandsp.h>
35 +
36 +static char *tdesc = "Trivial FAX Receive Application";
37 +
38 +static char *app = "RxFAX";
39 +
40 +static char *synopsis = "Receive a FAX to a file";
41 +
42 +static char *descrip = 
43 +"  RxFAX(filename[|caller][|debug]): Receives a FAX from the channel into the\n"
44 +"given filename. If the file exists it will be overwritten. The file\n"
45 +"should be in TIFF/F format.\n"
46 +"The \"caller\" option makes the application behave as a calling machine,\n"
47 +"rather than the answering machine. The default behaviour is to behave as\n"
48 +"an answering machine.\n"
49 +"Uses LOCALSTATIONID to identify itself to the remote end.\n"
50 +"     LOCALHEADERINFO to generate a header line on each page.\n"
51 +"Sets REMOTESTATIONID to the sender CSID.\n"
52 +"     FAXPAGES to the number of pages received.\n"
53 +"     FAXBITRATE to the transmition rate.\n"
54 +"     FAXRESOLUTION to the resolution.\n"
55 +"Returns -1 when the user hangs up.\n"
56 +"Returns 0 otherwise.\n";
57 +
58 +STANDARD_LOCAL_USER;
59 +
60 +LOCAL_USER_DECL;
61 +
62 +#define MAX_BLOCK_SIZE 240
63 +
64 +static void t30_flush(t30_state_t *s, int which)
65 +{
66 +    //TODO:
67 +}
68 +/*- End of function --------------------------------------------------------*/
69 +
70 +static void phase_e_handler(t30_state_t *s, void *user_data, int result)
71 +{
72 +    struct ast_channel *chan;
73 +    t30_stats_t t;
74 +    char local_ident[21];
75 +    char far_ident[21];
76 +    char buf[11];
77 +    
78 +    chan = (struct ast_channel *) user_data;
79 +    if (result)
80 +    {
81 +        fax_get_transfer_statistics(s, &t);
82 +        fax_get_far_ident(s, far_ident);
83 +        fax_get_local_ident(s, local_ident);
84 +        ast_log(LOG_DEBUG, "==============================================================================\n");
85 +        ast_log(LOG_DEBUG, "Fax successfully received.\n");
86 +        ast_log(LOG_DEBUG, "Remote station id: %s\n", far_ident);
87 +        ast_log(LOG_DEBUG, "Local station id:  %s\n", local_ident);
88 +        ast_log(LOG_DEBUG, "Pages transferred: %i\n", t.pages_transferred);
89 +        ast_log(LOG_DEBUG, "Image resolution:  %i x %i\n", t.column_resolution, t.row_resolution);
90 +        ast_log(LOG_DEBUG, "Transfer Rate:     %i\n", t.bit_rate);
91 +        ast_log(LOG_DEBUG, "==============================================================================\n");
92 +        manager_event(EVENT_FLAG_CALL,
93 +                      "FaxReceived", "Channel: %s\nExten: %s\nCallerID: %s\nRemoteStationID: %s\nLocalStationID: %s\nPagesTransferred: %i\nResolution: %i\nTransferRate: %i\nFileName: %s\n",
94 +                      chan->name,
95 +                      chan->exten,
96 +#if (ASTERISK_VERSION_NUM <= 011000)
97 +                      chan->callerid,
98 +#else
99 +                      (chan->cid.cid_num)  ?  chan->cid.cid_num  :  "",
100 +#endif
101 +                      far_ident,
102 +                      local_ident,
103 +                      t.pages_transferred,
104 +                      t.row_resolution,
105 +                      t.bit_rate,
106 +                      s->rx_file);
107 +        pbx_builtin_setvar_helper(chan, "REMOTESTATIONID", far_ident);
108 +        snprintf(buf, sizeof(buf), "%i", t.pages_transferred);
109 +        pbx_builtin_setvar_helper(chan, "FAXPAGES", buf);
110 +        snprintf(buf, sizeof(buf), "%i", t.row_resolution);
111 +        pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", buf);
112 +        snprintf(buf, sizeof(buf), "%i", t.bit_rate);
113 +        pbx_builtin_setvar_helper(chan, "FAXBITRATE", buf);
114 +    }
115 +    else
116 +    {
117 +        ast_log(LOG_DEBUG, "==============================================================================\n");
118 +        ast_log(LOG_DEBUG, "Fax receive not successful.\n");
119 +        ast_log(LOG_DEBUG, "==============================================================================\n");
120 +    }
121 +}
122 +/*- End of function --------------------------------------------------------*/
123 +
124 +static void phase_d_handler(t30_state_t *s, void *user_data, int result)
125 +{
126 +    struct ast_channel *chan;
127 +    t30_stats_t t;
128 +    
129 +    chan = (struct ast_channel *) user_data;
130 +    if (result)
131 +    {
132 +        fax_get_transfer_statistics(s, &t);
133 +        ast_log(LOG_DEBUG, "==============================================================================\n");
134 +        ast_log(LOG_DEBUG, "Pages transferred:  %i\n", t.pages_transferred);
135 +        ast_log(LOG_DEBUG, "Image size:         %i x %i\n", t.columns, t.rows);
136 +        ast_log(LOG_DEBUG, "Image resolution    %i x %i\n", t.column_resolution, t.row_resolution);
137 +        ast_log(LOG_DEBUG, "Transfer Rate:      %i\n", t.bit_rate);
138 +        ast_log(LOG_DEBUG, "Bad rows            %i\n", t.bad_rows);
139 +        ast_log(LOG_DEBUG, "Longest bad row run %i\n", t.longest_bad_row_run);
140 +        ast_log(LOG_DEBUG, "Compression type    %i\n", t.encoding);
141 +        ast_log(LOG_DEBUG, "Image size (bytes)  %i\n", t.image_size);
142 +        ast_log(LOG_DEBUG, "==============================================================================\n");
143 +    }
144 +}
145 +/*- End of function --------------------------------------------------------*/
146 +
147 +static int rxfax_exec(struct ast_channel *chan, void *data)
148 +{
149 +    int res = 0;
150 +    char template_file[256];
151 +    char target_file[256];
152 +    char *s;
153 +    char *t;
154 +    char *v;
155 +    char *x;
156 +    int option;
157 +    int len;
158 +    int i;
159 +    t30_state_t fax;
160 +    int calling_party;
161 +    int verbose;
162 +    int samples;
163 +
164 +    struct localuser *u;
165 +    struct ast_frame *inf = NULL;
166 +    struct ast_frame outf;
167 +
168 +    int original_read_fmt;
169 +    int original_write_fmt;
170 +    
171 +    uint8_t __buf[sizeof(uint16_t)*MAX_BLOCK_SIZE + 2*AST_FRIENDLY_OFFSET];
172 +    uint8_t *buf = __buf + AST_FRIENDLY_OFFSET;
173 +
174 +    if (chan == NULL)
175 +    {
176 +        ast_log(LOG_WARNING, "Fax receive channel is NULL. Giving up.\n");
177 +        return -1;
178 +    }
179 +
180 +    /* The next few lines of code parse out the filename and header from the input string */
181 +    if (data == NULL)
182 +    {
183 +        /* No data implies no filename or anything is present */
184 +        ast_log(LOG_WARNING, "Rxfax requires an argument (filename)\n");
185 +        return -1;
186 +    }
187 +    
188 +    calling_party = FALSE;
189 +    verbose = FALSE;
190 +    target_file[0] = '\0';
191 +
192 +    for (option = 0, v = s = data;  v;  option++, s++)
193 +    {
194 +        t = s;
195 +        v = strchr(s, '|');
196 +        s = (v)  ?  v  :  s + strlen(s);
197 +        strncpy(buf, t, s - t);
198 +        buf[s - t] = '\0';
199 +        if (option == 0)
200 +        {
201 +            /* The first option is always the file name */
202 +            len = s - t;
203 +            if (len > 255)
204 +                len = 255;
205 +            strncpy(target_file, t, len);
206 +            target_file[len] = '\0';
207 +            /* Allow the use of %d in the file name for a wild card of sorts, to
208 +               create a new file with the specified name scheme */
209 +            if ((x = strchr(target_file, '%'))  &&  x[1] == 'd')
210 +            {
211 +                strcpy(template_file, target_file);
212 +                i = 0;
213 +                do
214 +                {
215 +                    snprintf(target_file, 256, template_file, 1);
216 +                    i++;
217 +                }
218 +                while (ast_fileexists(target_file, "", chan->language) != -1);
219 +            }
220 +        }
221 +        else if (strncmp("caller", t, s - t) == 0)
222 +        {
223 +            calling_party = TRUE;
224 +        }
225 +        else if (strncmp("debug", t, s - t) == 0)
226 +        {
227 +            verbose = TRUE;
228 +        }
229 +    }
230 +
231 +    /* Done parsing */
232 +
233 +    LOCAL_USER_ADD(u);
234 +
235 +    if (chan->_state != AST_STATE_UP)
236 +    {
237 +        /* Shouldn't need this, but checking to see if channel is already answered
238 +         * Theoretically asterisk should already have answered before running the app */
239 +        res = ast_answer(chan);
240 +    }
241 +    
242 +    if (!res)
243 +    {
244 +        original_read_fmt = chan->readformat;
245 +        if (original_read_fmt != AST_FORMAT_SLINEAR)
246 +        {
247 +            res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
248 +            if (res < 0)
249 +            {
250 +                ast_log(LOG_WARNING, "Unable to set to linear read mode, giving up\n");
251 +                return -1;
252 +            }
253 +        }
254 +        original_write_fmt = chan->writeformat;
255 +        if (original_write_fmt != AST_FORMAT_SLINEAR)
256 +        {
257 +            res = ast_set_write_format(chan, AST_FORMAT_SLINEAR);
258 +            if (res < 0)
259 +            {
260 +                ast_log(LOG_WARNING, "Unable to set to linear write mode, giving up\n");
261 +                res = ast_set_read_format(chan, original_read_fmt);
262 +                if (res)
263 +                    ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", chan->name);
264 +                return -1;
265 +            }
266 +        }
267 +        fax_init(&fax, calling_party, NULL);
268 +        fax.verbose = verbose;
269 +        x = pbx_builtin_getvar_helper(chan, "LOCALSTATIONID");
270 +        if (x  &&  x[0])
271 +            fax_set_local_ident(&fax, x);
272 +        x = pbx_builtin_getvar_helper(chan, "LOCALHEADERINFO");
273 +        if (x  &&  x[0])
274 +            fax_set_header_info(&fax, x);
275 +        fax_set_rx_file(&fax, target_file);
276 +        //fax_set_phase_b_handler(&fax, phase_b_handler, chan);
277 +        fax_set_phase_d_handler(&fax, phase_d_handler, chan);
278 +        fax_set_phase_e_handler(&fax, phase_e_handler, chan);
279 +        while (ast_waitfor(chan, -1) > -1)
280 +        {
281 +            inf = ast_read(chan);
282 +            if (inf == NULL)
283 +            {
284 +                res = -1;
285 +                break;
286 +            }
287 +            if (inf->frametype == AST_FRAME_VOICE)
288 +            {
289 +                if (fax_rx_process(&fax, inf->data, inf->samples))
290 +                    break;
291 +                samples = (inf->samples <= MAX_BLOCK_SIZE)  ?  inf->samples  :  MAX_BLOCK_SIZE;
292 +                len = fax_tx_process(&fax, (int16_t *) &buf[AST_FRIENDLY_OFFSET], samples);
293 +                if (len)
294 +                {
295 +                    memset(&outf, 0, sizeof(outf));
296 +                    outf.frametype = AST_FRAME_VOICE;
297 +                    outf.subclass = AST_FORMAT_SLINEAR;
298 +                    outf.datalen = len*sizeof(int16_t);
299 +                    outf.samples = len;
300 +                    outf.data = &buf[AST_FRIENDLY_OFFSET];
301 +                    outf.offset = AST_FRIENDLY_OFFSET;
302 +                    outf.src = "RxFAX";
303 +                    if (ast_write(chan, &outf) < 0)
304 +                    {
305 +                        ast_log(LOG_WARNING, "Unable to write frame to channel; %s\n", strerror(errno));
306 +                        break;
307 +                    }
308 +                }
309 +            }
310 +            ast_frfree(inf);
311 +        }
312 +        if (inf == NULL)
313 +        {
314 +            ast_log(LOG_DEBUG, "Got hangup\n");
315 +            res = -1;
316 +        }
317 +        if (original_read_fmt != AST_FORMAT_SLINEAR)
318 +        {
319 +            res = ast_set_read_format(chan, original_read_fmt);
320 +            if (res)
321 +                ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", chan->name);
322 +        }
323 +        if (original_write_fmt != AST_FORMAT_SLINEAR)
324 +        {
325 +            res = ast_set_write_format(chan, original_write_fmt);
326 +            if (res)
327 +                ast_log(LOG_WARNING, "Unable to restore write format on '%s'\n", chan->name);
328 +        }
329 +        fax_release(&fax);
330 +    }
331 +    else
332 +    {
333 +        ast_log(LOG_WARNING, "Could not answer channel '%s'\n", chan->name);
334 +    }
335 +    LOCAL_USER_REMOVE(u);
336 +    return res;
337 +}
338 +/*- End of function --------------------------------------------------------*/
339 +
340 +int unload_module(void)
341 +{
342 +    STANDARD_HANGUP_LOCALUSERS;
343 +    return ast_unregister_application(app);
344 +}
345 +/*- End of function --------------------------------------------------------*/
346 +
347 +int load_module(void)
348 +{
349 +    return ast_register_application(app, rxfax_exec, synopsis, descrip);
350 +}
351 +
352 +char *description(void)
353 +{
354 +    return tdesc;
355 +}
356 +/*- End of function --------------------------------------------------------*/
357 +
358 +int usecount(void)
359 +{
360 +    int res;
361 +    STANDARD_USECOUNT(res);
362 +    return res;
363 +}
364 +/*- End of function --------------------------------------------------------*/
365 +
366 +char *key(void)
367 +{
368 +    return ASTERISK_GPL_KEY;
369 +}
370 +/*- End of function --------------------------------------------------------*/
371 +/*- End of file ------------------------------------------------------------*/
372 diff -urN asterisk-1.0.9-o/apps/app_rxfax_test.c asterisk-1.0.9-n/apps/app_rxfax_test.c
373 --- asterisk-1.0.9-o/apps/app_rxfax_test.c      1969-12-31 17:00:00.000000000 -0700
374 +++ asterisk-1.0.9-n/apps/app_rxfax_test.c      2005-09-20 13:01:02.000000000 -0600
375 @@ -0,0 +1,400 @@
376 +/*
377 + * Asterisk -- A telephony toolkit for Linux.
378 + *
379 + * Trivial application to receive a TIFF FAX file
380 + * 
381 + * Copyright (C) 2003, Steve Underwood
382 + *
383 + * Steve Underwood <steveu@coppice.org>
384 + *
385 + * This program is free software, distributed under the terms of
386 + * the GNU General Public License
387 + */
388
389 +#include <asterisk/lock.h>
390 +#include <asterisk/file.h>
391 +#include <asterisk/logger.h>
392 +#include <asterisk/channel.h>
393 +#include <asterisk/pbx.h>
394 +#include <asterisk/module.h>
395 +#include <asterisk/translate.h>
396 +#include <asterisk/dsp.h>
397 +#include <asterisk/manager.h>
398 +#include <string.h>
399 +#include <stdlib.h>
400 +#include <stdint.h>
401 +#include <pthread.h>
402 +#include <errno.h>
403 +#include <tiffio.h>
404 +
405 +#include <spandsp.h>
406 +
407 +static char *tdesc = "Trivial FAX Receive Application";
408 +
409 +static char *app = "RxFAX";
410 +
411 +static char *synopsis = "Receive a FAX to a file";
412 +
413 +static char *descrip = 
414 +"  RxFAX(filename[|caller][|debug]): Receives a FAX from the channel into the\n"
415 +"given filename. If the file exists it will be overwritten. The file\n"
416 +"should be in TIFF/F format.\n"
417 +"The \"caller\" option makes the application behave as a calling machine,\n"
418 +"rather than the answering machine. The default behaviour is to behave as\n"
419 +"an answering machine.\n"
420 +"Uses LOCALSTATIONID to identify itself to the remote end.\n"
421 +"     LOCALHEADERINFO to generate a header line on each page.\n"
422 +"Sets REMOTESTATIONID to the sender CSID.\n"
423 +"     FAXPAGES to the number of pages received.\n"
424 +"     FAXBITRATE to the transmition rate.\n"
425 +"     FAXRESOLUTION to the resolution.\n"
426 +"Returns -1 when the user hangs up.\n"
427 +"Returns 0 otherwise.\n";
428 +
429 +STANDARD_LOCAL_USER;
430 +
431 +LOCAL_USER_DECL;
432 +
433 +#define MAX_BLOCK_SIZE 240
434 +
435 +static void t30_flush(t30_state_t *s, int which)
436 +{
437 +    //TODO:
438 +}
439 +/*- End of function --------------------------------------------------------*/
440 +
441 +static void phase_e_handler(t30_state_t *s, void *user_data, int result)
442 +{
443 +    struct ast_channel *chan;
444 +    t30_stats_t t;
445 +    char local_ident[21];
446 +    char far_ident[21];
447 +    char buf[11];
448 +    
449 +    chan = (struct ast_channel *) user_data;
450 +    if (result)
451 +    {
452 +        fax_get_transfer_statistics(s, &t);
453 +        fax_get_far_ident(s, far_ident);
454 +        fax_get_local_ident(s, local_ident);
455 +        ast_log(LOG_DEBUG, "==============================================================================\n");
456 +        ast_log(LOG_DEBUG, "Fax successfully received.\n");
457 +        ast_log(LOG_DEBUG, "Remote station id: %s\n", far_ident);
458 +        ast_log(LOG_DEBUG, "Local station id:  %s\n", local_ident);
459 +        ast_log(LOG_DEBUG, "Pages transferred: %i\n", t.pages_transferred);
460 +        ast_log(LOG_DEBUG, "Image resolution:  %i x %i\n", t.column_resolution, t.row_resolution);
461 +        ast_log(LOG_DEBUG, "Transfer Rate:     %i\n", t.bit_rate);
462 +        ast_log(LOG_DEBUG, "==============================================================================\n");
463 +        manager_event(EVENT_FLAG_CALL,
464 +                      "FaxReceived", "Channel: %s\nExten: %s\nCallerID: %s\nRemoteStationID: %s\nLocalStationID: %s\nPagesTransferred: %i\nResolution: %i\nTransferRate: %i\nFileName: %s\n",
465 +                      chan->name,
466 +                      chan->exten,
467 +#if (ASTERISK_VERSION_NUM <= 011000)
468 +                      chan->callerid,
469 +#else
470 +                      (chan->cid.cid_num)  ?  chan->cid.cid_num  :  "",
471 +#endif
472 +                      far_ident,
473 +                      local_ident,
474 +                      t.pages_transferred,
475 +                      t.row_resolution,
476 +                      t.bit_rate,
477 +                      s->rx_file);
478 +        pbx_builtin_setvar_helper(chan, "REMOTESTATIONID", far_ident);
479 +        snprintf(buf, sizeof(buf), "%i", t.pages_transferred);
480 +        pbx_builtin_setvar_helper(chan, "FAXPAGES", buf);
481 +        snprintf(buf, sizeof(buf), "%i", t.row_resolution);
482 +        pbx_builtin_setvar_helper(chan, "FAXRESOLUTION", buf);
483 +        snprintf(buf, sizeof(buf), "%i", t.bit_rate);
484 +        pbx_builtin_setvar_helper(chan, "FAXBITRATE", buf);
485 +    }
486 +    else
487 +    {
488 +        ast_log(LOG_DEBUG, "==============================================================================\n");
489 +        ast_log(LOG_DEBUG, "Fax receive not successful.\n");
490 +        ast_log(LOG_DEBUG, "==============================================================================\n");
491 +    }
492 +}
493 +/*- End of function --------------------------------------------------------*/
494 +
495 +static void phase_d_handler(t30_state_t *s, void *user_data, int result)
496 +{
497 +    struct ast_channel *chan;
498 +    t30_stats_t t;
499 +    
500 +    chan = (struct ast_channel *) user_data;
501 +    if (result)
502 +    {
503 +        fax_get_transfer_statistics(s, &t);
504 +        ast_log(LOG_DEBUG, "==============================================================================\n");
505 +        ast_log(LOG_DEBUG, "Pages transferred:  %i\n", t.pages_transferred);
506 +        ast_log(LOG_DEBUG, "Image size:         %i x %i\n", t.columns, t.rows);
507 +        ast_log(LOG_DEBUG, "Image resolution    %i x %i\n", t.column_resolution, t.row_resolution);
508 +        ast_log(LOG_DEBUG, "Transfer Rate:      %i\n", t.bit_rate);
509 +        ast_log(LOG_DEBUG, "Bad rows            %i\n", t.bad_rows);
510 +        ast_log(LOG_DEBUG, "Longest bad row run %i\n", t.longest_bad_row_run);
511 +        ast_log(LOG_DEBUG, "Compression type    %i\n", t.encoding);
512 +        ast_log(LOG_DEBUG, "Image size (bytes)  %i\n", t.image_size);
513 +        ast_log(LOG_DEBUG, "==============================================================================\n");
514 +    }
515 +}
516 +/*- End of function --------------------------------------------------------*/
517 +
518 +static void *fax_gen_alloc(struct ast_channel *chan, void *params)
519 +{
520 +    return params;
521 +}
522 +/*- End of function --------------------------------------------------------*/
523 +
524 +static void fax_gen_release(struct ast_channel *chan, void *data)
525 +{
526 +    return;
527 +}
528 +/*- End of function --------------------------------------------------------*/
529 +
530 +static int fax_gen_generate(struct ast_channel *chan, void *data, int len, int samples)
531 +{
532 +    struct ast_frame f;
533 +    uint8_t buf[sizeof(uint16_t)*MAX_BLOCK_SIZE + 2*AST_FRIENDLY_OFFSET];
534 +    t30_state_t *fax;
535 +
536 +    fax = (t30_state_t *) data;
537 +    if (len > sizeof (buf))
538 +    {
539 +        ast_log (LOG_WARNING, "Only doing %d bytes (%d bytes requested)\n", (int)(sizeof (buf) / sizeof (signed short)), len);
540 +        len = sizeof (buf);
541 +        samples = len / 2;
542 +    }
543 +    len = fax_tx_process(fax, (int16_t *) &buf[AST_FRIENDLY_OFFSET], samples);
544 +    f.frametype = AST_FRAME_VOICE;
545 +    f.subclass = AST_FORMAT_SLINEAR;
546 +    f.offset = AST_FRIENDLY_OFFSET;
547 +    f.mallocd = 0;
548 +    f.data = &buf[AST_FRIENDLY_OFFSET];
549 +    f.datalen = len*sizeof(int16_t);
550 +    f.samples = len;
551 +    f.src = "app_txfax";
552 +    if (ast_write(chan, &f) < 0)
553 +    {
554 +        ast_log (LOG_WARNING, "Failed to write frame to '%s': %s\n", chan->name, strerror(errno));
555 +        return -1;
556 +    }
557 +    return 0;
558 +}
559 +/*- End of function --------------------------------------------------------*/
560 +
561 +static struct ast_generator fax_gen =
562 +{
563 +    alloc:fax_gen_alloc,
564 +    release:fax_gen_release,
565 +    generate:fax_gen_generate,
566 +};
567 +
568 +static int rxfax_exec(struct ast_channel *chan, void *data)
569 +{
570 +    int res = 0;
571 +    char template_file[256];
572 +    char target_file[256];
573 +    char *s;
574 +    char *t;
575 +    char *v;
576 +    char *x;
577 +    int option;
578 +    int i;
579 +    t30_state_t fax;
580 +    int calling_party;
581 +    int verbose;
582 +
583 +    struct localuser *u;
584 +    struct ast_frame *inf = NULL;
585 +
586 +    int original_read_fmt;
587 +    int original_write_fmt;
588 +    
589 +    if (chan == NULL)
590 +    {
591 +        ast_log(LOG_WARNING, "Fax receive channel is NULL. Giving up.\n");
592 +        return -1;
593 +    }
594 +
595 +    /* The next few lines of code parse out the filename and header from the input string */
596 +    if (data == NULL)
597 +    {
598 +        /* No data implies no filename or anything is present */
599 +        ast_log(LOG_WARNING, "Rxfax requires an argument (filename)\n");
600 +        return -1;
601 +    }
602 +    
603 +    calling_party = FALSE;
604 +    verbose = FALSE;
605 +    target_file[0] = '\0';
606 +
607 +    for (option = 0, v = s = data;  v;  option++, s++)
608 +    {
609 +        t = s;
610 +        v = strchr(s, '|');
611 +        s = (v)  ?  v  :  s + strlen(s);
612 +        strncpy(buf, t, s - t);
613 +        buf[s - t] = '\0';
614 +        if (option == 0)
615 +        {
616 +            /* The first option is always the file name */
617 +            len = s - t;
618 +            if (len > 255)
619 +                len = 255;
620 +            strncpy(target_file, t, len);
621 +            target_file[len] = '\0';
622 +            /* Allow the use of %d in the file name for a wild card of sorts, to
623 +               create a new file with the specified name scheme */
624 +            if ((x = strchr(target_file, '%'))  &&  x[1] == 'd')
625 +            {
626 +                strcpy(template_file, target_file);
627 +                i = 0;
628 +                do
629 +                {
630 +                    snprintf(target_file, 256, template_file, 1);
631 +                    i++;
632 +                }
633 +                while (ast_fileexists(target_file, "", chan->language) != -1);
634 +            }
635 +        }
636 +        else if (strncmp("caller", t, s - t) == 0)
637 +        {
638 +            calling_party = TRUE;
639 +        }
640 +        else if (strncmp("debug", t, s - t) == 0)
641 +        {
642 +            verbose = TRUE;
643 +        }
644 +    }
645 +
646 +    /* Done parsing */
647 +
648 +    LOCAL_USER_ADD(u);
649 +
650 +    if (chan->_state != AST_STATE_UP)
651 +    {
652 +        /* Shouldn't need this, but checking to see if channel is already answered
653 +         * Theoretically asterisk should already have answered before running the app */
654 +        res = ast_answer(chan);
655 +    }
656 +    
657 +    if (!res)
658 +    {
659 +        original_read_fmt = chan->readformat;
660 +        if (original_read_fmt != AST_FORMAT_SLINEAR)
661 +        {
662 +            res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
663 +            if (res < 0)
664 +            {
665 +                ast_log(LOG_WARNING, "Unable to set to linear read mode, giving up\n");
666 +                return -1;
667 +            }
668 +        }
669 +        original_write_fmt = chan->writeformat;
670 +        if (original_write_fmt != AST_FORMAT_SLINEAR)
671 +        {
672 +            res = ast_set_write_format(chan, AST_FORMAT_SLINEAR);
673 +            if (res < 0)
674 +            {
675 +                ast_log(LOG_WARNING, "Unable to set to linear write mode, giving up\n");
676 +                res = ast_set_read_format(chan, original_read_fmt);
677 +                if (res)
678 +                    ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", chan->name);
679 +                return -1;
680 +            }
681 +        }
682 +        fax_init(&fax, calling_party, NULL);
683 +        fax.verbose = verbose;
684 +        x = pbx_builtin_getvar_helper(chan, "LOCALSTATIONID");
685 +        if (x  &&  x[0])
686 +            fax_set_local_ident(&fax, x);
687 +        x = pbx_builtin_getvar_helper(chan, "LOCALHEADERINFO");
688 +        if (x  &&  x[0])
689 +            fax_set_header_info(&fax, x);
690 +        fax_set_rx_file(&fax, target_file);
691 +        //fax_set_phase_b_handler(&fax, phase_b_handler, chan);
692 +        fax_set_phase_d_handler(&fax, phase_d_handler, chan);
693 +        fax_set_phase_e_handler(&fax, phase_e_handler, chan);
694 +       if (ast_activate_generator(chan, &fax_gen, &fax) < 0)
695 +       {
696 +           LOCAL_USER_REMOVE (u);
697 +           ast_log (LOG_ERROR, "Failed to activate generator on '%s'\n", chan->name);
698 +           return -1;
699 +       }
700 +
701 +        while (ast_waitfor(chan, -1) > -1)
702 +        {
703 +            inf = ast_read(chan);
704 +            if (inf == NULL)
705 +            {
706 +                res = -1;
707 +                break;
708 +            }
709 +            if (inf->frametype == AST_FRAME_VOICE)
710 +            {
711 +                if (fax_rx_process(&fax, inf->data, inf->samples))
712 +                    break;
713 +            }
714 +            ast_frfree(inf);
715 +        }
716 +        if (inf == NULL)
717 +        {
718 +            ast_log(LOG_DEBUG, "Got hangup\n");
719 +            res = -1;
720 +        }
721 +       ast_deactivate_generator(chan);
722 +        if (original_read_fmt != AST_FORMAT_SLINEAR)
723 +        {
724 +            res = ast_set_read_format(chan, original_read_fmt);
725 +            if (res)
726 +                ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", chan->name);
727 +        }
728 +        if (original_write_fmt != AST_FORMAT_SLINEAR)
729 +        {
730 +            res = ast_set_write_format(chan, original_write_fmt);
731 +            if (res)
732 +                ast_log(LOG_WARNING, "Unable to restore write format on '%s'\n", chan->name);
733 +        }
734 +    }
735 +    else
736 +    {
737 +        ast_log(LOG_WARNING, "Could not answer channel '%s'\n", chan->name);
738 +    }
739 +    LOCAL_USER_REMOVE(u);
740 +    return res;
741 +}
742 +/*- End of function --------------------------------------------------------*/
743 +
744 +int unload_module(void)
745 +{
746 +    STANDARD_HANGUP_LOCALUSERS;
747 +    return ast_unregister_application(app);
748 +}
749 +/*- End of function --------------------------------------------------------*/
750 +
751 +int load_module(void)
752 +{
753 +    return ast_register_application(app, rxfax_exec, synopsis, descrip);
754 +}
755 +
756 +char *description(void)
757 +{
758 +    return tdesc;
759 +}
760 +/*- End of function --------------------------------------------------------*/
761 +
762 +int usecount(void)
763 +{
764 +    int res;
765 +    STANDARD_USECOUNT(res);
766 +    return res;
767 +}
768 +/*- End of function --------------------------------------------------------*/
769 +
770 +char *key(void)
771 +{
772 +    return ASTERISK_GPL_KEY;
773 +}
774 +/*- End of function --------------------------------------------------------*/
775 +/*- End of file ------------------------------------------------------------*/
776 diff -urN asterisk-1.0.9-o/apps/app_txfax.c asterisk-1.0.9-n/apps/app_txfax.c
777 --- asterisk-1.0.9-o/apps/app_txfax.c   1969-12-31 17:00:00.000000000 -0700
778 +++ asterisk-1.0.9-n/apps/app_txfax.c   2005-09-20 13:01:02.000000000 -0600
779 @@ -0,0 +1,290 @@
780 +/*
781 + * Asterisk -- A telephony toolkit for Linux.
782 + *
783 + * Trivial application to send a TIFF file as a FAX
784 + * 
785 + * Copyright (C) 2003, Steve Underwood
786 + *
787 + * Steve Underwood <steveu@coppice.org>
788 + *
789 + * This program is free software, distributed under the terms of
790 + * the GNU General Public License
791 + */
792
793 +#include <asterisk/lock.h>
794 +#include <asterisk/file.h>
795 +#include <asterisk/logger.h>
796 +#include <asterisk/channel.h>
797 +#include <asterisk/pbx.h>
798 +#include <asterisk/module.h>
799 +#include <asterisk/translate.h>
800 +#include <string.h>
801 +#include <stdlib.h>
802 +#include <stdint.h>
803 +#include <pthread.h>
804 +#include <errno.h>
805 +#include <tiffio.h>
806 +
807 +#include <spandsp.h>
808 +
809 +static char *tdesc = "Trivial FAX Transmit Application";
810 +
811 +static char *app = "TxFAX";
812 +
813 +static char *synopsis = "Send a FAX file";
814 +
815 +static char *descrip = 
816 +"  TxFAX(filename[|caller][|debug]):  Send a given TIFF file to the channel as a FAX.\n"
817 +"The \"caller\" option makes the application behave as a calling machine,\n"
818 +"rather than the answering machine. The default behaviour is to behave as\n"
819 +"an answering machine.\n"
820 +"Uses LOCALSTATIONID to identify itself to the remote end.\n"
821 +"     LOCALHEADERINFO to generate a header line on each page.\n"
822 +"Sets REMOTESTATIONID to the receiver CSID.\n"
823 +"Returns -1 when the user hangs up, or if the file does not exist.\n"
824 +"Returns 0 otherwise.\n";
825 +
826 +STANDARD_LOCAL_USER;
827 +
828 +LOCAL_USER_DECL;
829 +
830 +#define MAX_BLOCK_SIZE 240
831 +
832 +static void t30_flush(t30_state_t *s, int which)
833 +{
834 +    //TODO:
835 +}
836 +/*- End of function --------------------------------------------------------*/
837 +
838 +static void phase_e_handler(t30_state_t *s, void *user_data, int result)
839 +{
840 +    struct ast_channel *chan;
841 +    char far_ident[21];
842 +    
843 +    chan = (struct ast_channel *) user_data;
844 +    if (result)
845 +    {
846 +        fax_get_far_ident(s, far_ident);
847 +        pbx_builtin_setvar_helper(chan, "REMOTESTATIONID", far_ident);
848 +    }
849 +    else
850 +    {
851 +        ast_log(LOG_DEBUG, "==============================================================================\n");
852 +        ast_log(LOG_DEBUG, "Fax send not successful.\n");
853 +        ast_log(LOG_DEBUG, "==============================================================================\n");
854 +    }
855 +}
856 +/*- End of function --------------------------------------------------------*/
857 +
858 +static int txfax_exec(struct ast_channel *chan, void *data)
859 +{
860 +    int res = 0;
861 +    char source_file[256];
862 +    char *x;
863 +    char *s;
864 +    char *t;
865 +    char *v;
866 +    int option;
867 +    int len;
868 +    t30_state_t fax;
869 +    int calling_party;
870 +    int verbose;
871 +    int samples;
872 +    
873 +    struct localuser *u;
874 +    struct ast_frame *inf = NULL;
875 +    struct ast_frame outf;
876 +
877 +    int original_read_fmt;
878 +    int original_write_fmt;
879 +    
880 +    uint8_t __buf[sizeof(uint16_t)*MAX_BLOCK_SIZE + 2*AST_FRIENDLY_OFFSET];
881 +    uint8_t *buf = __buf + AST_FRIENDLY_OFFSET;
882 +
883 +    if (chan == NULL)
884 +    {
885 +        ast_log(LOG_WARNING, "Fax transmit channel is NULL. Giving up.\n");
886 +        return -1;
887 +    }
888 +
889 +    /* The next few lines of code parse out the filename and header from the input string */
890 +    if (data == NULL)
891 +    {
892 +        /* No data implies no filename or anything is present */
893 +        ast_log(LOG_WARNING, "Txfax requires an argument (filename)\n");
894 +        return -1;
895 +    }
896 +    
897 +    calling_party = FALSE;
898 +    verbose = FALSE;
899 +    source_file[0] = '\0'; 
900 +
901 +    for (option = 0, v = s = data;  v;  option++, s++)
902 +    {
903 +        t = s;
904 +        v = strchr(s, '|');
905 +        s = (v)  ?  v  :  s + strlen(s);
906 +        strncpy(buf, t, s - t);
907 +        buf[s - t] = '\0';
908 +        if (option == 0)
909 +        {
910 +            /* The first option is always the file name */
911 +            len = s - t;
912 +            if (len > 255)
913 +                len = 255;
914 +            strncpy(source_file, t, len);
915 +            source_file[len] = '\0';
916 +        }
917 +        else if (strncmp("caller", t, s - t) == 0)
918 +        {
919 +            calling_party = TRUE;
920 +        }
921 +        else if (strncmp("debug", t, s - t) == 0)
922 +        {
923 +            verbose = TRUE;
924 +        }
925 +    }
926 +
927 +    /* Done parsing */
928 +
929 +    LOCAL_USER_ADD(u);
930 +
931 +    if (chan->_state != AST_STATE_UP)
932 +    {
933 +        /* Shouldn't need this, but checking to see if channel is already answered
934 +         * Theoretically asterisk should already have answered before running the app */
935 +        res = ast_answer(chan);
936 +    }
937 +    
938 +    if (!res)
939 +    {
940 +        original_read_fmt = chan->readformat;
941 +        if (original_read_fmt != AST_FORMAT_SLINEAR)
942 +        {
943 +            res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
944 +            if (res < 0)
945 +            {
946 +                ast_log(LOG_WARNING, "Unable to set to linear read mode, giving up\n");
947 +                return -1;
948 +            }
949 +        }
950 +        original_write_fmt = chan->writeformat;
951 +        if (original_write_fmt != AST_FORMAT_SLINEAR)
952 +        {
953 +            res = ast_set_write_format(chan, AST_FORMAT_SLINEAR);
954 +            if (res < 0)
955 +            {
956 +                ast_log(LOG_WARNING, "Unable to set to linear write mode, giving up\n");
957 +                res = ast_set_read_format(chan, original_read_fmt);
958 +                if (res)
959 +                    ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", chan->name);
960 +                return -1;
961 +            }
962 +        }
963 +        fax_init(&fax, calling_party, NULL);
964 +        fax.verbose = verbose;
965 +
966 +        x = pbx_builtin_getvar_helper(chan, "LOCALSTATIONID");
967 +        if (x  &&  x[0])
968 +            fax_set_local_ident(&fax, x);
969 +        x = pbx_builtin_getvar_helper(chan, "LOCALHEADERINFO");
970 +        if (x  &&  x[0])
971 +            fax_set_header_info(&fax, x);
972 +        fax_set_tx_file(&fax, source_file);
973 +        //fax_set_phase_b_handler(&fax, phase_b_handler, chan);
974 +        //fax_set_phase_d_handler(&fax, phase_d_handler, chan);
975 +        fax_set_phase_e_handler(&fax, phase_e_handler, chan);
976 +        while (ast_waitfor(chan, -1) > -1)
977 +        {
978 +            inf = ast_read(chan);
979 +            if (inf == NULL)
980 +            {
981 +                res = -1;
982 +                break;
983 +            }
984 +            if (inf->frametype == AST_FRAME_VOICE)
985 +            {
986 +                if (fax_rx_process(&fax, inf->data, inf->samples))
987 +                    break;
988 +                samples = (inf->samples <= MAX_BLOCK_SIZE)  ?  inf->samples  :  MAX_BLOCK_SIZE;
989 +                len = fax_tx_process(&fax, (int16_t *) &buf[AST_FRIENDLY_OFFSET], samples);
990 +                if (len)
991 +                {
992 +                    memset(&outf, 0, sizeof(outf));
993 +                    outf.frametype = AST_FRAME_VOICE;
994 +                    outf.subclass = AST_FORMAT_SLINEAR;
995 +                    outf.datalen = len*sizeof(int16_t);
996 +                    outf.samples = len;
997 +                    outf.data = &buf[AST_FRIENDLY_OFFSET];
998 +                    outf.offset = AST_FRIENDLY_OFFSET;
999 +                    if (ast_write(chan, &outf) < 0)
1000 +                    {
1001 +                        ast_log(LOG_WARNING, "Unable to write frame to channel; %s\n", strerror(errno));
1002 +                        break;
1003 +                    }
1004 +                }
1005 +            }
1006 +            ast_frfree(inf);
1007 +        }
1008 +        if (inf == NULL)
1009 +        {
1010 +            ast_log(LOG_DEBUG, "Got hangup\n");
1011 +            res = -1;
1012 +        }
1013 +        if (original_read_fmt != AST_FORMAT_SLINEAR)
1014 +        {
1015 +            res = ast_set_read_format(chan, original_read_fmt);
1016 +            if (res)
1017 +                ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", chan->name);
1018 +        }
1019 +        if (original_write_fmt != AST_FORMAT_SLINEAR)
1020 +        {
1021 +            res = ast_set_write_format(chan, original_write_fmt);
1022 +            if (res)
1023 +                ast_log(LOG_WARNING, "Unable to restore write format on '%s'\n", chan->name);
1024 +        }
1025 +        fax_release(&fax);
1026 +    }
1027 +    else
1028 +    {
1029 +        ast_log(LOG_WARNING, "Could not answer channel '%s'\n", chan->name);
1030 +    }
1031 +    LOCAL_USER_REMOVE(u);
1032 +    return res;
1033 +}
1034 +/*- End of function --------------------------------------------------------*/
1035 +
1036 +int unload_module(void)
1037 +{
1038 +    STANDARD_HANGUP_LOCALUSERS;
1039 +    return ast_unregister_application(app);
1040 +}
1041 +/*- End of function --------------------------------------------------------*/
1042 +
1043 +int load_module(void)
1044 +{
1045 +    return ast_register_application(app, txfax_exec, synopsis, descrip);
1046 +}
1047 +/*- End of function --------------------------------------------------------*/
1048 +
1049 +char *description(void)
1050 +{
1051 +    return tdesc;
1052 +}
1053 +/*- End of function --------------------------------------------------------*/
1054 +
1055 +int usecount(void)
1056 +{
1057 +    int res;
1058 +
1059 +    STANDARD_USECOUNT(res);
1060 +    return res;
1061 +}
1062 +/*- End of function --------------------------------------------------------*/
1063 +
1064 +char *key(void)
1065 +{
1066 +    return ASTERISK_GPL_KEY;
1067 +}
1068 +/*- End of function --------------------------------------------------------*/
1069 +/*- End of file ------------------------------------------------------------*/
1070 diff -urN asterisk-1.0.9-o/apps/app_txfax_test.c asterisk-1.0.9-n/apps/app_txfax_test.c
1071 --- asterisk-1.0.9-o/apps/app_txfax_test.c      1969-12-31 17:00:00.000000000 -0700
1072 +++ asterisk-1.0.9-n/apps/app_txfax_test.c      2005-09-20 13:01:02.000000000 -0600
1073 @@ -0,0 +1,325 @@
1074 +/*
1075 + * Asterisk -- A telephony toolkit for Linux.
1076 + *
1077 + * Trivial application to send a TIFF file as a FAX
1078 + * 
1079 + * Copyright (C) 2003, Steve Underwood
1080 + *
1081 + * Steve Underwood <steveu@coppice.org>
1082 + *
1083 + * This program is free software, distributed under the terms of
1084 + * the GNU General Public License
1085 + */
1086
1087 +#include <asterisk/lock.h>
1088 +#include <asterisk/file.h>
1089 +#include <asterisk/logger.h>
1090 +#include <asterisk/channel.h>
1091 +#include <asterisk/pbx.h>
1092 +#include <asterisk/module.h>
1093 +#include <asterisk/translate.h>
1094 +#include <string.h>
1095 +#include <stdlib.h>
1096 +#include <stdint.h>
1097 +#include <pthread.h>
1098 +#include <errno.h>
1099 +#include <tiffio.h>
1100 +
1101 +#include <spandsp.h>
1102 +
1103 +static char *tdesc = "Trivial FAX Transmit Application";
1104 +
1105 +static char *app = "TxFAX";
1106 +
1107 +static char *synopsis = "Send a FAX file";
1108 +
1109 +static char *descrip = 
1110 +"  TxFAX(filename[|caller][|debug]):  Send a given TIFF file to the channel as a FAX.\n"
1111 +"The \"caller\" option makes the application behave as a calling machine,\n"
1112 +"rather than the answering machine. The default behaviour is to behave as\n"
1113 +"an answering machine.\n"
1114 +"Uses LOCALSTATIONID to identify itself to the remote end.\n"
1115 +"     LOCALHEADERINFO to generate a header line on each page.\n"
1116 +"Sets REMOTESTATIONID to the receiver CSID.\n"
1117 +"Returns -1 when the user hangs up, or if the file does not exist.\n"
1118 +"Returns 0 otherwise.\n";
1119 +
1120 +STANDARD_LOCAL_USER;
1121 +
1122 +LOCAL_USER_DECL;
1123 +
1124 +#define MAX_BLOCK_SIZE 240
1125 +
1126 +static void t30_flush(t30_state_t *s, int which)
1127 +{
1128 +    //TODO:
1129 +}
1130 +/*- End of function --------------------------------------------------------*/
1131 +
1132 +static void phase_e_handler(t30_state_t *s, void *user_data, int result)
1133 +{
1134 +    struct ast_channel *chan;
1135 +    char far_ident[21];
1136 +    
1137 +    chan = (struct ast_channel *) user_data;
1138 +    if (result)
1139 +    {
1140 +        fax_get_far_ident(s, far_ident);
1141 +        pbx_builtin_setvar_helper(chan, "REMOTESTATIONID", far_ident);
1142 +    }
1143 +    else
1144 +    {
1145 +        ast_log(LOG_DEBUG, "==============================================================================\n");
1146 +        ast_log(LOG_DEBUG, "Fax send not successful.\n");
1147 +        ast_log(LOG_DEBUG, "==============================================================================\n");
1148 +    }
1149 +}
1150 +/*- End of function --------------------------------------------------------*/
1151 +
1152 +static void *fax_gen_alloc(struct ast_channel *chan, void *params)
1153 +{
1154 +    return params;
1155 +}
1156 +/*- End of function --------------------------------------------------------*/
1157 +
1158 +static void fax_gen_release(struct ast_channel *chan, void *data)
1159 +{
1160 +    return;
1161 +}
1162 +/*- End of function --------------------------------------------------------*/
1163 +
1164 +static int fax_gen_generate(struct ast_channel *chan, void *data, int len, int samples)
1165 +{
1166 +    struct ast_frame f;
1167 +    uint8_t buf[sizeof(uint16_t)*MAX_BLOCK_SIZE + 2*AST_FRIENDLY_OFFSET];
1168 +    t30_state_t *fax;
1169 +
1170 +    fax = (t30_state_t *) data;
1171 +    if (len > sizeof (buf))
1172 +    {
1173 +        ast_log (LOG_WARNING, "Only doing %d bytes (%d bytes requested)\n", (int)(sizeof (buf) / sizeof (signed short)), len);
1174 +        len = sizeof (buf);
1175 +        samples = len / 2;
1176 +    }
1177 +    len = fax_tx_process(fax, (int16_t *) &buf[AST_FRIENDLY_OFFSET], samples);
1178 +    f.frametype = AST_FRAME_VOICE;
1179 +    f.subclass = AST_FORMAT_SLINEAR;
1180 +    f.offset = AST_FRIENDLY_OFFSET;
1181 +    f.mallocd = 0;
1182 +    f.data = &buf[AST_FRIENDLY_OFFSET];
1183 +    f.datalen = len*sizeof(int16_t);
1184 +    f.samples = len;
1185 +    f.src = "app_txfax";
1186 +    if (ast_write(chan, &f) < 0)
1187 +    {
1188 +        ast_log (LOG_WARNING, "Failed to write frame to '%s': %s\n", chan->name, strerror(errno));
1189 +        return -1;
1190 +    }
1191 +    return 0;
1192 +}
1193 +/*- End of function --------------------------------------------------------*/
1194 +
1195 +static struct ast_generator fax_gen =
1196 +{
1197 +    alloc:fax_gen_alloc,
1198 +    release:fax_gen_release,
1199 +    generate:fax_gen_generate,
1200 +};
1201 +
1202 +static int txfax_exec(struct ast_channel *chan, void *data)
1203 +{
1204 +    int res = 0;
1205 +    char source_file[256];
1206 +    char *x;
1207 +    char *s;
1208 +    char *t;
1209 +    char *v;
1210 +    int option;
1211 +    int len;
1212 +    t30_state_t fax;
1213 +    int calling_party;
1214 +    int verbose;
1215 +    
1216 +    struct localuser *u;
1217 +    struct ast_frame *inf = NULL;
1218 +
1219 +    int original_read_fmt;
1220 +    int original_write_fmt;
1221 +    
1222 +    if (chan == NULL)
1223 +    {
1224 +        ast_log(LOG_WARNING, "Fax transmit channel is NULL. Giving up.\n");
1225 +        return -1;
1226 +    }
1227 +
1228 +    /* The next few lines of code parse out the filename and header from the input string */
1229 +    if (data == NULL)
1230 +    {
1231 +        /* No data implies no filename or anything is present */
1232 +        ast_log(LOG_WARNING, "Txfax requires an argument (filename)\n");
1233 +        return -1;
1234 +    }
1235 +    
1236 +    calling_party = FALSE;
1237 +    verbose = FALSE;
1238 +    source_file[0] = '\0'; 
1239 +
1240 +    for (option = 0, v = s = data;  v;  option++, s++)
1241 +    {
1242 +        t = s;
1243 +        v = strchr(s, '|');
1244 +        s = (v)  ?  v  :  s + strlen(s);
1245 +        strncpy(buf, t, s - t);
1246 +        buf[s - t] = '\0';
1247 +        if (option == 0)
1248 +        {
1249 +            /* The first option is always the file name */
1250 +            len = s - t;
1251 +            if (len > 255)
1252 +                len = 255;
1253 +            strncpy(source_file, t, len);
1254 +            source_file[len] = '\0';
1255 +        }
1256 +        else if (strncmp("caller", t, s - t) == 0)
1257 +        {
1258 +            calling_party = TRUE;
1259 +        }
1260 +        else if (strncmp("debug", t, s - t) == 0)
1261 +        {
1262 +            verbose = TRUE;
1263 +        }
1264 +    }
1265 +
1266 +    /* Done parsing */
1267 +
1268 +    LOCAL_USER_ADD(u);
1269 +
1270 +    if (chan->_state != AST_STATE_UP)
1271 +    {
1272 +        /* Shouldn't need this, but checking to see if channel is already answered
1273 +         * Theoretically asterisk should already have answered before running the app */
1274 +        res = ast_answer(chan);
1275 +    }
1276 +    
1277 +    if (!res)
1278 +    {
1279 +        original_read_fmt = chan->readformat;
1280 +        if (original_read_fmt != AST_FORMAT_SLINEAR)
1281 +        {
1282 +            res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
1283 +            if (res < 0)
1284 +            {
1285 +                ast_log(LOG_WARNING, "Unable to set to linear read mode, giving up\n");
1286 +                return -1;
1287 +            }
1288 +        }
1289 +        original_write_fmt = chan->writeformat;
1290 +        if (original_write_fmt != AST_FORMAT_SLINEAR)
1291 +        {
1292 +            res = ast_set_write_format(chan, AST_FORMAT_SLINEAR);
1293 +            if (res < 0)
1294 +            {
1295 +                ast_log(LOG_WARNING, "Unable to set to linear write mode, giving up\n");
1296 +                res = ast_set_read_format(chan, original_read_fmt);
1297 +                if (res)
1298 +                    ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", chan->name);
1299 +                return -1;
1300 +            }
1301 +        }
1302 +        fax_init(&fax, calling_party, NULL);
1303 +        fax.verbose = verbose;
1304 +
1305 +        x = pbx_builtin_getvar_helper(chan, "LOCALSTATIONID");
1306 +        if (x  &&  x[0])
1307 +            fax_set_local_ident(&fax, x);
1308 +        x = pbx_builtin_getvar_helper(chan, "LOCALHEADERINFO");
1309 +        if (x  &&  x[0])
1310 +            fax_set_header_info(&fax, x);
1311 +        fax_set_tx_file(&fax, source_file);
1312 +        //fax_set_phase_b_handler(&fax, phase_b_handler, chan);
1313 +        //fax_set_phase_d_handler(&fax, phase_d_handler, chan);
1314 +        fax_set_phase_e_handler(&fax, phase_e_handler, chan);
1315 +       if (ast_activate_generator(chan, &fax_gen, &fax) < 0)
1316 +       {
1317 +           LOCAL_USER_REMOVE (u);
1318 +           ast_log (LOG_ERROR, "Failed to activate generator on '%s'\n", chan->name);
1319 +           return -1;
1320 +       }
1321 +
1322 +        while (ast_waitfor(chan, -1) > -1)
1323 +        {
1324 +            inf = ast_read(chan);
1325 +            if (inf == NULL)
1326 +            {
1327 +                res = -1;
1328 +                break;
1329 +            }
1330 +            if (inf->frametype == AST_FRAME_VOICE)
1331 +            {
1332 +                if (fax_rx_process(&fax, inf->data, inf->samples))
1333 +                    break;
1334 +            }
1335 +            ast_frfree(inf);
1336 +        }
1337 +        if (inf == NULL)
1338 +        {
1339 +            ast_log(LOG_DEBUG, "Got hangup\n");
1340 +            res = -1;
1341 +        }
1342 +       ast_deactivate_generator(chan);
1343 +        if (original_read_fmt != AST_FORMAT_SLINEAR)
1344 +        {
1345 +            res = ast_set_read_format(chan, original_read_fmt);
1346 +            if (res)
1347 +                ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", chan->name);
1348 +        }
1349 +        if (original_write_fmt != AST_FORMAT_SLINEAR)
1350 +        {
1351 +            res = ast_set_write_format(chan, original_write_fmt);
1352 +            if (res)
1353 +                ast_log(LOG_WARNING, "Unable to restore write format on '%s'\n", chan->name);
1354 +        }
1355 +    }
1356 +    else
1357 +    {
1358 +        ast_log(LOG_WARNING, "Could not answer channel '%s'\n", chan->name);
1359 +    }
1360 +    LOCAL_USER_REMOVE(u);
1361 +    return res;
1362 +}
1363 +/*- End of function --------------------------------------------------------*/
1364 +
1365 +int unload_module(void)
1366 +{
1367 +    STANDARD_HANGUP_LOCALUSERS;
1368 +    return ast_unregister_application(app);
1369 +}
1370 +/*- End of function --------------------------------------------------------*/
1371 +
1372 +int load_module(void)
1373 +{
1374 +    return ast_register_application(app, txfax_exec, synopsis, descrip);
1375 +}
1376 +/*- End of function --------------------------------------------------------*/
1377 +
1378 +char *description(void)
1379 +{
1380 +    return tdesc;
1381 +}
1382 +/*- End of function --------------------------------------------------------*/
1383 +
1384 +int usecount(void)
1385 +{
1386 +    int res;
1387 +
1388 +    STANDARD_USECOUNT(res);
1389 +    return res;
1390 +}
1391 +/*- End of function --------------------------------------------------------*/
1392 +
1393 +char *key(void)
1394 +{
1395 +    return ASTERISK_GPL_KEY;
1396 +}
1397 +/*- End of function --------------------------------------------------------*/
1398 +/*- End of file ------------------------------------------------------------*/
1399 diff -urN asterisk-1.0.9-o/apps/Makefile asterisk-1.0.9-n/apps/Makefile
1400 --- asterisk-1.0.9-o/apps/Makefile      2004-09-24 15:32:56.000000000 -0600
1401 +++ asterisk-1.0.9-n/apps/Makefile      2005-09-20 13:01:25.000000000 -0600
1402 @@ -43,6 +43,9 @@
1403  APPS+=$(shell if [ -f /usr/local/include/zaptel.h ]; then echo "app_zapras.so app_meetme.so app_flash.so app_zapbarge.so app_zapscan.so" ; fi)
1404  APPS+=$(shell if [ -f /usr/include/osp/osp.h ]; then echo "app_osplookup.so" ; fi)
1405  
1406 +APPS+=$(shell if [ -f /usr/include/spandsp.h ]; then echo "app_rxfax.so app_txfax.so" ; fi)
1407 +APPS+=$(shell if [ -f /usr/local/include/spandsp.h ]; then echo "app_rxfax.so app_txfax.so" ; fi)
1408 +
1409  CFLAGS+=-fPIC
1410  
1411  ifeq ($(USE_POSTGRES_VM_INTERFACE),1)
1412 @@ -68,6 +71,12 @@
1413         for x in $(APPS); do $(INSTALL) -m 755 $$x $(DESTDIR)$(MODULES_DIR) ; done
1414         rm -f $(DESTDIR)$(MODULES_DIR)/app_datetime.so
1415  
1416 +app_rxfax.so : app_rxfax.o
1417 +       $(CC) $(SOLINK) -o $@ $< -lspandsp -ltiff
1418 +
1419 +app_txfax.so : app_txfax.o
1420 +       $(CC) $(SOLINK) -o $@ $< -lspandsp -ltiff
1421 +
1422  app_voicemail.so : app_voicemail.o
1423  ifeq ($(USE_MYSQL_VM_INTERFACE),1)
1424         $(CC) $(SOLINK) -o $@ $(MLFLAGS) $< -L/usr/lib/mysql -lmysqlclient -lz
This page took 0.16161 seconds and 3 git commands to generate.