[asterisk-addons-commits] tilghman: trunk r497 - in /trunk: ./ build_tools/

SVN commits to the Asterisk addons project asterisk-addons-commits at lists.digium.com
Fri Dec 14 15:56:07 CST 2007


Author: tilghman
Date: Fri Dec 14 15:56:06 2007
New Revision: 497

URL: http://svn.digium.com/view/asterisk-addons?view=rev&rev=497
Log:
Add faxing application
Patch by: dimas
(Closes issue #10815)

Added:
    trunk/app_fax.c   (with props)
Modified:
    trunk/Makefile
    trunk/build_tools/menuselect-deps.in
    trunk/configure
    trunk/configure.ac
    trunk/makeopts.in
    trunk/menuselect-tree

Modified: trunk/Makefile
URL: http://svn.digium.com/view/asterisk-addons/trunk/Makefile?view=diff&rev=497&r1=496&r2=497
==============================================================================
--- trunk/Makefile (original)
+++ trunk/Makefile Fri Dec 14 15:56:06 2007
@@ -61,7 +61,7 @@
 endif
 MODULES_DIR=$(ASTLIBDIR)/modules
 
-MODS:=app_addon_sql_mysql app_saycountpl cdr_addon_mysql chan_ooh323 format_mp3 res_config_mysql chan_mobile
+MODS:=app_addon_sql_mysql app_saycountpl cdr_addon_mysql chan_ooh323 format_mp3 res_config_mysql chan_mobile app_fax
 
 SELECTED_MODS:=$(patsubst %,%.so,$(filter-out $(MENUSELECT_ADDONS),$(MODS)))
 
@@ -138,6 +138,9 @@
 endif
 
 ASTCFLAGS+=$(ASTERISK_INCLUDE)
+
+app_fax.so: app_fax.o
+	$(CC) $(SOLINK) -o $@ $< $(SPANDSP_LIB)
 
 cdr_addon_mysql.so: cdr_addon_mysql.o
 	$(CC) $(SOLINK) -o $@ $< $(MYSQLCLIENT_LIB)

Added: trunk/app_fax.c
URL: http://svn.digium.com/view/asterisk-addons/trunk/app_fax.c?view=auto&rev=497
==============================================================================
--- trunk/app_fax.c (added)
+++ trunk/app_fax.c Fri Dec 14 15:56:06 2007
@@ -1,0 +1,532 @@
+/*
+ * Asterisk -- A telephony toolkit for Linux.
+ *
+ * Simple fax applications
+ * 
+ * 2007, Dmitry Andrianov <asterisk at dima.spb.ru>
+ *
+ * Code based on original implementation by Steve Underwood <steveu at coppice.org>
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License
+ *
+ */
+
+/*** MODULEINFO
+	 <depend>spandsp</depend>
+***/
+ 
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision:$")
+
+#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/app.h"
+#include "asterisk/module.h"
+#include "asterisk/manager.h"
+
+#ifndef AST_MODULE
+#define AST_MODULE "app_fax"
+#endif
+
+static char *app_sndfax_name = "SendFAX";
+static char *app_sndfax_synopsis = "Send a FAX";
+static char *app_sndfax_desc = 
+"  SendFAX(filename[,options]):\n"
+"Send a given TIFF file to the channel as a FAX.\n"
+"The option string may contain zero or more of the following characters:\n"
+"     'a' -- makes the application behave as an answering machine\n"
+"            The default behaviour is to behave as a calling machine.\n"
+"     'd' -- turn on debug output. This option may be specified multiple\n"
+"            times (max 2) to increase verbosity.\n"
+"\n"
+"This application uses following variables:\n"
+"     LOCALSTATIONID to identify itself to the remote end.\n"
+"     LOCALHEADERINFO to generate a header line on each page.\n"
+"\n"
+"This application sets the following channel variables upon completion:\n"
+"     FAXSTATUS       - status of operation:\n"
+"                           SUCCESS | FAILED\n"
+"     FAXERROR        - Error when FAILED\n"
+"     REMOTESTATIONID - CSID of the remote side.\n"
+"     FAXPAGES        - number of pages sent.\n"
+"     FAXBITRATE      - transmition rate.\n"
+"     FAXRESOLUTION   - resolution.\n"
+"\n"
+"Returns -1 in case of user hang up or any channel error.\n"
+"Returns 0 on success.\n";
+
+static char *app_rcvfax_name = "ReceiveFAX";
+static char *app_rcvfax_synopsis = "Receive a FAX";
+static char *app_rcvfax_desc = 
+"  ReceiveFAX(filename[,options]):\n"
+"Receives a fax from the channel into the given filename overwriting\n"
+"the file if it already exists. File created will have TIFF format.\n"
+"The option string may contain zero or more of the following characters:\n"
+"     'c' -- makes the application behave as a calling machine\n"
+"            The default behaviour is to behave as an answering machine.\n"
+"     'd' -- turn on debug output. This option may be specified multiple\n"
+"            times (max 2) to increase verbosity.\n"
+"\n"
+"This application uses following variables:\n"
+"     LOCALSTATIONID to identify itself to the remote end.\n"
+"     LOCALHEADERINFO to generate a header line on each page.\n"
+"\n"
+"This application sets the following channel variables upon completion:\n"
+"     FAXSTATUS       - status of operation:\n"
+"                           SUCCESS | FAILED\n"
+"     FAXERROR        - Error when FAILED\n"
+"     REMOTESTATIONID - CSID of the remote side.\n"
+"     FAXPAGES        - number of pages sent.\n"
+"     FAXBITRATE      - transmition rate.\n"
+"     FAXRESOLUTION   - resolution.\n"
+"\n"
+"Returns -1 in case of user hang up or any channel error.\n"
+"Returns 0 on success.\n";
+
+#define MAX_BLOCK_SIZE 240
+
+typedef struct {
+	struct ast_channel *chan;
+	fax_state_t fax;
+	volatile int finished;
+} fax_session;
+
+static void span_message(int level, const char *msg)
+{
+	if (level == SPAN_LOG_ERROR)
+		ast_log(LOG_ERROR, msg);
+	else if (level == SPAN_LOG_WARNING)
+		ast_log(LOG_WARNING, msg);
+	else
+		ast_log(LOG_WARNING, msg);
+}
+
+static void phase_e_handler(t30_state_t *f, void *user_data, int result)
+{
+	char local_ident[T30_MAX_IDENT_LEN];
+	char far_ident[T30_MAX_IDENT_LEN];
+	char buf[20];
+	fax_session *s = (fax_session *) user_data;
+	t30_stats_t stat;
+
+	t30_get_transfer_statistics(f, &stat);
+
+	s = (fax_session *) user_data;
+
+	if (result == T30_ERR_OK) {
+		s->finished = 1; 
+
+		t30_get_local_ident(f, local_ident);
+		t30_get_far_ident(f, far_ident);
+		pbx_builtin_setvar_helper(s->chan, "FAXSTATUS", "SUCCESS"); 
+		pbx_builtin_setvar_helper(s->chan, "FAXERROR", NULL); 
+		pbx_builtin_setvar_helper(s->chan, "REMOTESTATIONID", far_ident);
+		snprintf(buf, sizeof(buf), "%d", stat.pages_transferred);
+		pbx_builtin_setvar_helper(s->chan, "FAXPAGES", buf);
+		snprintf(buf, sizeof(buf), "%d", stat.y_resolution);
+		pbx_builtin_setvar_helper(s->chan, "FAXRESOLUTION", buf);
+		snprintf(buf, sizeof(buf), "%d", stat.bit_rate);
+		pbx_builtin_setvar_helper(s->chan, "FAXBITRATE", buf); 
+
+		ast_debug(1, "Fax transmitted successfully.\n");
+		ast_debug(1, "  Remote station ID: %s\n", far_ident);
+		ast_debug(1, "  Pages transferred: %d\n", stat.pages_transferred);
+		ast_debug(1, "  Image resolution:  %d x %i\n", stat.x_resolution, stat.y_resolution);
+		ast_debug(1, "  Transfer Rate:     %d\n", stat.bit_rate);
+
+		manager_event(EVENT_FLAG_CALL,
+			f->tx_file ? "FaxSent" : "FaxReceived", 
+			"Channel: %s\r\n"
+			"Exten: %s\r\n"
+			"CallerID: %s\r\n"
+			"RemoteStationID: %s\r\n"
+			"LocalStationID: %s\r\n"
+			"PagesTransferred: %d\r\n"
+			"Resolution: %d\r\n"
+			"TransferRate: %d\r\n"
+			"FileName: %s\r\n",
+			s->chan->name,
+			s->chan->exten,
+			S_OR(s->chan->cid.cid_num, ""),
+			far_ident,
+			local_ident,
+			stat.pages_transferred,
+			stat.y_resolution,
+			stat.bit_rate,
+			S_OR(f->tx_file, f->rx_file));
+	} else {
+		s->finished = -1; 
+
+		/* FAXSTATUS is already set to FAILED */
+		pbx_builtin_setvar_helper(s->chan, "FAXERROR", t30_completion_code_to_str(result)); 
+
+		ast_log(LOG_WARNING, "Error sending fax - result (%d) %s.\n", result, t30_completion_code_to_str(result));
+	}
+}
+
+static int transmit(fax_session *s)
+{
+	int res = 0, res2;
+
+	int original_read_fmt;
+	int original_write_fmt;
+
+	const char *x;
+	int len;
+	int samples;
+
+	struct ast_frame *inf = NULL;
+	struct ast_frame outf;
+
+	uint8_t buffer[AST_FRIENDLY_OFFSET + MAX_BLOCK_SIZE * sizeof(uint16_t)];
+	int16_t *buf = (int16_t *) (buffer + AST_FRIENDLY_OFFSET);
+
+	int last_state = 0;
+	struct timeval now, start, state_change;
+	
+	pbx_builtin_setvar_helper(s->chan, "FAXSTATUS", "FAILED"); 
+	pbx_builtin_setvar_helper(s->chan, "FAXERROR", "Channel problems"); 
+
+	pbx_builtin_setvar_helper(s->chan, "REMOTESTATIONID", NULL);
+	pbx_builtin_setvar_helper(s->chan, "FAXPAGES", NULL);
+	pbx_builtin_setvar_helper(s->chan, "FAXRESOLUTION", NULL);
+	pbx_builtin_setvar_helper(s->chan, "FAXBITRATE", NULL); 
+
+	if (s->chan->_state != AST_STATE_UP) {
+		/* Shouldn't need this, but checking to see if channel is already answered
+		 * Theoretically asterisk should already have answered before running the app */
+		res = ast_answer(s->chan);
+		if (res) {
+			ast_log(LOG_WARNING, "Could not answer channel '%s'\n", s->chan->name);
+			goto done;
+		}
+	}
+	
+	original_read_fmt = s->chan->readformat;
+	if (original_read_fmt != AST_FORMAT_SLINEAR) {
+		res = ast_set_read_format(s->chan, AST_FORMAT_SLINEAR);
+		if (res < 0) {
+			ast_log(LOG_WARNING, "Unable to set to linear read mode, giving up\n");
+			res = -1;
+			goto done;
+		}
+	}
+
+	original_write_fmt = s->chan->writeformat;
+	if (original_write_fmt != AST_FORMAT_SLINEAR) {
+		res = ast_set_write_format(s->chan, AST_FORMAT_SLINEAR);
+		if (res < 0) {
+			ast_log(LOG_WARNING, "Unable to set to linear write mode, giving up\n");
+			res = -1;
+			goto done1;
+		}
+	}
+
+
+	x = pbx_builtin_getvar_helper(s->chan, "LOCALSTATIONID");
+	if (!ast_strlen_zero(x))
+		t30_set_local_ident(&s->fax.t30_state, x);
+
+	x = pbx_builtin_getvar_helper(s->chan, "LOCALHEADERINFO");
+	if (!ast_strlen_zero(x))
+		t30_set_header_info(&s->fax.t30_state, x);
+
+	t30_set_phase_e_handler(&s->fax.t30_state, phase_e_handler, s);
+
+	t30_set_ecm_capability(&s->fax.t30_state, TRUE);
+	t30_set_supported_compressions(&s->fax.t30_state, T30_SUPPORT_T4_1D_COMPRESSION | T30_SUPPORT_T4_2D_COMPRESSION | T30_SUPPORT_T6_COMPRESSION);
+
+	start = state_change = ast_tvnow();
+	while (!s->finished) {
+
+		if (ast_waitfor(s->chan, -1) < 0) {
+			res = -1;
+			break;
+		}
+
+		inf = ast_read(s->chan);
+		if (inf == NULL)
+			break;
+
+		/* Check the frame type. Format also must be checked because there is a chance
+		   that a frame in old format was already queued before we set chanel format
+		   to slinear so it will still be received by ast_read */
+		if (inf->frametype == AST_FRAME_VOICE && inf->subclass == AST_FORMAT_SLINEAR) {
+
+			if (fax_rx(&s->fax, inf->data, inf->samples) < 0) {
+				/* I know fax_rx never returns errors. The check here is for good style only */
+				ast_log(LOG_WARNING, "fax_rx returned error\n");
+				res = -1;
+				break;
+			}
+
+			samples = (inf->samples <= MAX_BLOCK_SIZE) ? inf->samples : MAX_BLOCK_SIZE;
+			len = fax_tx(&s->fax, buf, samples);
+
+			if (len < 0) {
+				/* fax_tx also never returns errors. The check here is for good style only */
+				ast_log(LOG_WARNING, "fax_tx returned error\n");
+				res = -1;
+				break;
+			} else if (len) {
+				memset(&outf, 0, sizeof(outf));
+				outf.frametype = AST_FRAME_VOICE;
+				outf.subclass = AST_FORMAT_SLINEAR;
+				outf.samples = len;
+				AST_FRAME_SET_BUFFER(&outf, buffer, AST_FRIENDLY_OFFSET, len * sizeof(int16_t));
+				if (ast_write(s->chan, &outf) < 0) {
+					ast_log(LOG_WARNING, "Unable to write frame to channel; %s\n", strerror(errno));
+					res = -1;
+					break;
+				}
+			}
+
+			if (last_state != s->fax.t30_state.state) {
+				state_change = ast_tvnow();
+				last_state = s->fax.t30_state.state;
+			}
+		}
+
+		ast_frfree(inf);
+		inf = NULL;
+
+		/* Watchdog. I have seen situations when remote fax disconnects (because of poor line
+		   quality) while SpanDSP continues staying in T30_STATE_IV_CTC state forever.
+		   To avoid this, we terminate when we see that T30 state does not change for 5 minutes.
+		   We also terminate application when more than 30 minutes passed regardless of
+		   state changes. This is just a precaution measure - no fax should take that long */
+
+		now = ast_tvnow();
+		if (ast_tvdiff_ms(now, start) > 30 * 60 * 1000 || ast_tvdiff_ms(now, state_change) > 5 * 60 * 1000) {
+			ast_log(LOG_WARNING, "It looks like we hung. Aborting.\n");
+			res = -1;
+			break;
+		}
+	}
+
+	if (inf)
+		ast_frfree(inf);
+
+	if (res) {
+		ast_log(LOG_WARNING, "Transmission loop error\n");
+		res = -1;
+	} else if (s->finished < 0) {
+		ast_log(LOG_WARNING, "Transmission error\n");
+	} else if (s->finished > 0) {
+		ast_debug(1, "Transmission finished Ok\n");
+	} else if (inf == NULL) {
+		ast_debug(1, "Channel hangup\n");
+		res = -1;
+	}
+
+
+	if (original_write_fmt != AST_FORMAT_SLINEAR) {
+		res2 = ast_set_write_format(s->chan, original_write_fmt);
+		if (res2)
+			ast_log(LOG_WARNING, "Unable to restore write format on '%s'\n", s->chan->name);
+	}
+
+done1:
+	if (original_read_fmt != AST_FORMAT_SLINEAR) {
+		res2 = ast_set_read_format(s->chan, original_read_fmt);
+		if (res2)
+			ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", s->chan->name);
+	}
+
+done:
+
+	return res;
+}
+
+static int sndfax_exec(struct ast_channel *chan, void *data)
+{
+	int res = 0;
+	char *parse;
+	char *pos;
+	int calling_party;
+	int verbose;
+
+	fax_session session;
+	
+	struct ast_module_user *u;
+
+	AST_DECLARE_APP_ARGS(args,
+		AST_APP_ARG(file_name);
+		AST_APP_ARG(options);
+	);
+
+	if (chan == NULL) {
+		ast_log(LOG_ERROR, "Fax channel is NULL. Giving up.\n");
+		return -1;
+	}
+
+	span_set_message_handler(span_message);
+
+	/* The next few lines of code parse out the filename and header from the input string */
+	if (ast_strlen_zero(data)) {
+		/* No data implies no filename or anything is present */
+		ast_log(LOG_ERROR, "SendFAX requires an argument (filename)\n");
+		return -1;
+	}
+
+	parse = ast_strdupa(data);
+	AST_STANDARD_APP_ARGS(args, parse);
+	
+	calling_party = TRUE;
+	verbose = 0;
+
+	if (args.options) {
+		if (strchr(args.options, 'a'))
+			calling_party = FALSE;
+
+		pos = args.options;
+		while ((pos = strchr(pos, 'd')) != NULL) {
+			verbose++;
+			pos++;
+		}
+	}
+
+	/* Done parsing */
+
+	u = ast_module_user_add(chan);
+
+	session.chan = chan;
+	session.finished = 0;
+
+	/* Initialize SpanDSP fax for transmission */
+	fax_init(&session.fax, calling_party);
+	t30_set_tx_file(&session.fax.t30_state, args.file_name, -1, -1);
+
+	if (verbose) {
+		span_log_set_level(&session.fax.logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); 
+		if (verbose > 1)
+			span_log_set_level(&session.fax.t30_state.logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); 
+	}
+
+	res = transmit(&session);
+
+	t30_terminate(&session.fax.t30_state);
+
+	ast_module_user_remove(u);
+
+	return res;
+}
+
+static int rcvfax_exec(struct ast_channel *chan, void *data)
+{
+	int res = 0;
+	char *parse;
+	char *pos;
+	int calling_party;
+	int verbose;
+
+	fax_session session;
+	
+	struct ast_module_user *u;
+
+	AST_DECLARE_APP_ARGS(args,
+		AST_APP_ARG(file_name);
+		AST_APP_ARG(options);
+	);
+
+	if (chan == NULL) {
+		ast_log(LOG_ERROR, "Fax channel is NULL. Giving up.\n");
+		return -1;
+	}
+
+	span_set_message_handler(span_message);
+
+	/* The next few lines of code parse out the filename and header from the input string */
+	if (ast_strlen_zero(data)) {
+		/* No data implies no filename or anything is present */
+		ast_log(LOG_ERROR, "ReceiveFAX requires an argument (filename)\n");
+		return -1;
+	}
+
+	parse = ast_strdupa(data);
+	AST_STANDARD_APP_ARGS(args, parse);
+	
+	calling_party = FALSE;
+	verbose = 0;
+
+	if (args.options) {
+		if (strchr(args.options, 'c'))
+			calling_party = TRUE;
+
+		pos = args.options;
+		while ((pos = strchr(pos, 'd')) != NULL) {
+			verbose++;
+			pos++;
+		}
+	}
+
+	/* Done parsing */
+
+	u = ast_module_user_add(chan);
+
+	session.chan = chan;
+	session.finished = 0;
+
+	/* Initialize SpanDSP fax for receiving */
+	fax_init(&session.fax, calling_party);
+	t30_set_rx_file(&session.fax.t30_state, args.file_name, -1);
+
+	if (verbose) {
+		span_log_set_level(&session.fax.logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); 
+		if (verbose > 1)
+			span_log_set_level(&session.fax.t30_state.logging, SPAN_LOG_SHOW_SEVERITY | SPAN_LOG_SHOW_PROTOCOL | SPAN_LOG_FLOW); 
+	}
+
+	res = transmit(&session);
+
+	t30_terminate(&session.fax.t30_state);
+
+	ast_module_user_remove(u);
+
+	return res;
+}
+
+static int unload_module(void)
+{
+	int res;
+
+	ast_module_user_hangup_all();
+
+	res = ast_unregister_application(app_sndfax_name);	
+	res |= ast_unregister_application(app_rcvfax_name);	
+
+	return res;
+}
+
+static int load_module(void)
+{
+	int res ;
+
+	res = ast_register_application(app_sndfax_name, sndfax_exec, app_sndfax_synopsis, app_sndfax_desc);
+	res |= ast_register_application(app_rcvfax_name, rcvfax_exec, app_rcvfax_synopsis, app_rcvfax_desc);
+
+	return res;
+}
+
+
+AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Simple FAX Application",
+		.load = load_module,
+		.unload = unload_module,
+		);
+
+

Propchange: trunk/app_fax.c
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: trunk/app_fax.c
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Propchange: trunk/app_fax.c
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: trunk/build_tools/menuselect-deps.in
URL: http://svn.digium.com/view/asterisk-addons/trunk/build_tools/menuselect-deps.in?view=diff&rev=497&r1=496&r2=497
==============================================================================
--- trunk/build_tools/menuselect-deps.in (original)
+++ trunk/build_tools/menuselect-deps.in Fri Dec 14 15:56:06 2007
@@ -1,3 +1,4 @@
 BLUETOOTH=@PBX_BLUETOOTH@
 MYSQLCLIENT=@PBX_MYSQLCLIENT@
 ASTERISK=@PBX_ASTERISK@
+SPANDSP=@PBX_SPANDSP@

Modified: trunk/configure
URL: http://svn.digium.com/view/asterisk-addons/trunk/configure?view=diff&rev=497&r1=496&r2=497
==============================================================================
--- trunk/configure (original)
+++ trunk/configure Fri Dec 14 15:56:06 2007
@@ -714,6 +714,9 @@
 ASTERISK_LIB
 ASTERISK_INCLUDE
 PBX_ASTERISK
+SPANDSP_LIB
+SPANDSP_INCLUDE
+PBX_SPANDSP
 CPP
 EGREP
 AST_DECLARATION_AFTER_STATEMENT
@@ -1316,6 +1319,7 @@
   --with-ncurses=PATH     use ncurses files in PATH
   --with-mysqlclient=PATH use mysqlclient files in PATH
   --with-asterisk=PATH    use asterisk files in PATH
+  --with-spandsp=PATH     use spandsp Library files in PATH
 
 Some influential environment variables:
   CC          C compiler command
@@ -4614,6 +4618,33 @@
 
 
 
+SPANDSP_DESCRIP="spandsp Library"
+SPANDSP_OPTION="spandsp"
+
+# Check whether --with-spandsp was given.
+if test "${with_spandsp+set}" = set; then
+  withval=$with_spandsp;
+case ${withval} in
+     n|no)
+     USE_SPANDSP=no
+     ;;
+     y|ye|yes)
+     SPANDSP_MANDATORY="yes"
+     ;;
+     *)
+     SPANDSP_DIR="${withval}"
+     SPANDSP_MANDATORY="yes"
+     ;;
+esac
+
+fi
+
+PBX_SPANDSP=0
+
+
+
+
+
 
 ac_ext=c
 ac_cpp='$CPP $CPPFLAGS'
@@ -6432,6 +6463,401 @@
 echo "$as_me: *** Either correct the installation" >&or run configure;}
       { echo "$as_me:$LINENO: *** without explicitly specifying --with-${NCURSES_OPTION}" >&5
 echo "$as_me: *** without explicitly specifying --with-${NCURSES_OPTION}" >&6;}
+      exit 1
+   fi
+fi
+
+
+if test "${USE_SPANDSP}" != "no"; then
+   pbxlibdir=""
+   if test "x${SPANDSP_DIR}" != "x"; then
+      if test -d ${SPANDSP_DIR}/lib; then
+      	 pbxlibdir="-L${SPANDSP_DIR}/lib"
+      else
+      	 pbxlibdir="-L${SPANDSP_DIR}"
+      fi
+   fi
+   { echo "$as_me:$LINENO: checking for fax_init in -lspandsp" >&5
+echo $ECHO_N "checking for fax_init in -lspandsp... $ECHO_C" >&6; }
+if test "${ac_cv_lib_spandsp_fax_init+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_check_lib_save_LIBS=$LIBS
+LIBS="-lspandsp ${pbxlibdir} -ltiff $LIBS"
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+
+/* Override any GCC internal prototype to avoid an error.
+   Use char because int might match the return type of a GCC
+   builtin and then its argument prototype would still apply.  */
+#ifdef __cplusplus
+extern "C"
+#endif
+char fax_init ();
+int
+main ()
+{
+return fax_init ();
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (ac_try="$ac_link"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_link") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest$ac_exeext &&
+       $as_test_x conftest$ac_exeext; then
+  ac_cv_lib_spandsp_fax_init=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_cv_lib_spandsp_fax_init=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
+      conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_lib_spandsp_fax_init" >&5
+echo "${ECHO_T}$ac_cv_lib_spandsp_fax_init" >&6; }
+if test $ac_cv_lib_spandsp_fax_init = yes; then
+  AST_SPANDSP_FOUND=yes
+else
+  AST_SPANDSP_FOUND=no
+fi
+
+
+   if test "${AST_SPANDSP_FOUND}" = "yes"; then
+      SPANDSP_LIB="-lspandsp -ltiff"
+      SPANDSP_HEADER_FOUND="1"
+      if test "x${SPANDSP_DIR}" != "x"; then
+         SPANDSP_LIB="${pbxlibdir} ${SPANDSP_LIB}"
+	 SPANDSP_INCLUDE="-I${SPANDSP_DIR}/include"
+	 if test "xspandsp.h" != "x" ; then
+	    as_ac_Header=`echo "ac_cv_header_${SPANDSP_DIR}/include/spandsp.h" | $as_tr_sh`
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  { echo "$as_me:$LINENO: checking for ${SPANDSP_DIR}/include/spandsp.h" >&5
+echo $ECHO_N "checking for ${SPANDSP_DIR}/include/spandsp.h... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+else
+  # Is the header compilable?
+{ echo "$as_me:$LINENO: checking ${SPANDSP_DIR}/include/spandsp.h usability" >&5
+echo $ECHO_N "checking ${SPANDSP_DIR}/include/spandsp.h usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <${SPANDSP_DIR}/include/spandsp.h>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking ${SPANDSP_DIR}/include/spandsp.h presence" >&5
+echo $ECHO_N "checking ${SPANDSP_DIR}/include/spandsp.h presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <${SPANDSP_DIR}/include/spandsp.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: ${SPANDSP_DIR}/include/spandsp.h: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: ${SPANDSP_DIR}/include/spandsp.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: ${SPANDSP_DIR}/include/spandsp.h: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: ${SPANDSP_DIR}/include/spandsp.h: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: ${SPANDSP_DIR}/include/spandsp.h: present but cannot be compiled" >&5
+echo "$as_me: WARNING: ${SPANDSP_DIR}/include/spandsp.h: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: ${SPANDSP_DIR}/include/spandsp.h:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: ${SPANDSP_DIR}/include/spandsp.h:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: ${SPANDSP_DIR}/include/spandsp.h: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: ${SPANDSP_DIR}/include/spandsp.h: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: ${SPANDSP_DIR}/include/spandsp.h:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: ${SPANDSP_DIR}/include/spandsp.h:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: ${SPANDSP_DIR}/include/spandsp.h: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: ${SPANDSP_DIR}/include/spandsp.h: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: ${SPANDSP_DIR}/include/spandsp.h: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: ${SPANDSP_DIR}/include/spandsp.h: in the future, the compiler will take precedence" >&2;}
+
+    ;;
+esac
+{ echo "$as_me:$LINENO: checking for ${SPANDSP_DIR}/include/spandsp.h" >&5
+echo $ECHO_N "checking for ${SPANDSP_DIR}/include/spandsp.h... $ECHO_C" >&6; }
+if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  eval "$as_ac_Header=\$ac_header_preproc"
+fi
+ac_res=`eval echo '${'$as_ac_Header'}'`
+	       { echo "$as_me:$LINENO: result: $ac_res" >&5
+echo "${ECHO_T}$ac_res" >&6; }
+
+fi
+if test `eval echo '${'$as_ac_Header'}'` = yes; then
+  SPANDSP_HEADER_FOUND=1
+else
+  SPANDSP_HEADER_FOUND=0
+fi
+
+
+	 fi
+      else
+	 if test "xspandsp.h" != "x" ; then
+            if test "${ac_cv_header_spandsp_h+set}" = set; then
+  { echo "$as_me:$LINENO: checking for spandsp.h" >&5
+echo $ECHO_N "checking for spandsp.h... $ECHO_C" >&6; }
+if test "${ac_cv_header_spandsp_h+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_header_spandsp_h" >&5
+echo "${ECHO_T}$ac_cv_header_spandsp_h" >&6; }
+else
+  # Is the header compilable?
+{ echo "$as_me:$LINENO: checking spandsp.h usability" >&5
+echo $ECHO_N "checking spandsp.h usability... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+$ac_includes_default
+#include <spandsp.h>
+_ACEOF
+rm -f conftest.$ac_objext
+if { (ac_try="$ac_compile"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_compile") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } && {
+	 test -z "$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       } && test -s conftest.$ac_objext; then
+  ac_header_compiler=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+	ac_header_compiler=no
+fi
+
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5
+echo "${ECHO_T}$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ echo "$as_me:$LINENO: checking spandsp.h presence" >&5
+echo $ECHO_N "checking spandsp.h presence... $ECHO_C" >&6; }
+cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <spandsp.h>
+_ACEOF
+if { (ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+  *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+  *) ac_try_echo=$ac_try;;
+esac
+eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
+  (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } >/dev/null && {
+	 test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+	 test ! -s conftest.err
+       }; then
+  ac_header_preproc=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+  ac_header_preproc=no
+fi
+
+rm -f conftest.err conftest.$ac_ext
+{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5
+echo "${ECHO_T}$ac_header_preproc" >&6; }
+
+# So?  What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in
+  yes:no: )
+    { echo "$as_me:$LINENO: WARNING: spandsp.h: accepted by the compiler, rejected by the preprocessor!" >&5
+echo "$as_me: WARNING: spandsp.h: accepted by the compiler, rejected by the preprocessor!" >&2;}
+    { echo "$as_me:$LINENO: WARNING: spandsp.h: proceeding with the compiler's result" >&5
+echo "$as_me: WARNING: spandsp.h: proceeding with the compiler's result" >&2;}
+    ac_header_preproc=yes
+    ;;
+  no:yes:* )
+    { echo "$as_me:$LINENO: WARNING: spandsp.h: present but cannot be compiled" >&5
+echo "$as_me: WARNING: spandsp.h: present but cannot be compiled" >&2;}
+    { echo "$as_me:$LINENO: WARNING: spandsp.h:     check for missing prerequisite headers?" >&5
+echo "$as_me: WARNING: spandsp.h:     check for missing prerequisite headers?" >&2;}
+    { echo "$as_me:$LINENO: WARNING: spandsp.h: see the Autoconf documentation" >&5
+echo "$as_me: WARNING: spandsp.h: see the Autoconf documentation" >&2;}
+    { echo "$as_me:$LINENO: WARNING: spandsp.h:     section \"Present But Cannot Be Compiled\"" >&5
+echo "$as_me: WARNING: spandsp.h:     section \"Present But Cannot Be Compiled\"" >&2;}
+    { echo "$as_me:$LINENO: WARNING: spandsp.h: proceeding with the preprocessor's result" >&5
+echo "$as_me: WARNING: spandsp.h: proceeding with the preprocessor's result" >&2;}
+    { echo "$as_me:$LINENO: WARNING: spandsp.h: in the future, the compiler will take precedence" >&5
+echo "$as_me: WARNING: spandsp.h: in the future, the compiler will take precedence" >&2;}
+
+    ;;
+esac
+{ echo "$as_me:$LINENO: checking for spandsp.h" >&5
+echo $ECHO_N "checking for spandsp.h... $ECHO_C" >&6; }
+if test "${ac_cv_header_spandsp_h+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  ac_cv_header_spandsp_h=$ac_header_preproc
+fi
+{ echo "$as_me:$LINENO: result: $ac_cv_header_spandsp_h" >&5
+echo "${ECHO_T}$ac_cv_header_spandsp_h" >&6; }
+
+fi
+if test $ac_cv_header_spandsp_h = yes; then
+  SPANDSP_HEADER_FOUND=1
+else
+  SPANDSP_HEADER_FOUND=0
+fi
+
+
+	 fi
+      fi
+      if test "x${SPANDSP_HEADER_FOUND}" = "x0" ; then
+         if test ! -z "${SPANDSP_MANDATORY}" ;
+         then
+            { echo "$as_me:$LINENO: ***" >&5
+echo "$as_me: ***" >&6;}
+            { echo "$as_me:$LINENO: *** It appears that you do not have the spandsp development package installed." >&5
+echo "$as_me: *** It appears that you do not have the spandsp development package installed." >&6;}
+            { echo "$as_me:$LINENO: *** Please install it to include ${SPANDSP_DESCRIP} support" >&5
+echo "$as_me: *** Please install it to include ${SPANDSP_DESCRIP} support" >&or re-run configure;}
+            { echo "$as_me:$LINENO: *** without explicitly specifying --with-${SPANDSP_OPTION}" >&5
+echo "$as_me: *** without explicitly specifying --with-${SPANDSP_OPTION}" >&6;}
+            exit 1
+         fi
+         SPANDSP_LIB=""
+         SPANDSP_INCLUDE=""
+         PBX_SPANDSP=0
+      else
+         PBX_SPANDSP=1
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_SPANDSP 1
+_ACEOF
+
+      fi
+   elif test ! -z "${SPANDSP_MANDATORY}";
+   then
+      { echo "$as_me:$LINENO: ***" >&5
+echo "$as_me: ***" >&6;}
+      { echo "$as_me:$LINENO: *** The ${SPANDSP_DESCRIP} installation on this system appears to be broken." >&5
+echo "$as_me: *** The ${SPANDSP_DESCRIP} installation on this system appears to be broken." >&6;}
+      { echo "$as_me:$LINENO: *** Either correct the installation" >&5
+echo "$as_me: *** Either correct the installation" >&or run configure;}
+      { echo "$as_me:$LINENO: *** without explicitly specifying --with-${SPANDSP_OPTION}" >&5
+echo "$as_me: *** without explicitly specifying --with-${SPANDSP_OPTION}" >&6;}
       exit 1
    fi
 fi
@@ -7630,6 +8056,9 @@
 ac_delim='%!_!# '
 for ac_last_try in false false false false false :; do
   cat >conf$$subs.sed <<_ACEOF
+SPANDSP_LIB!$SPANDSP_LIB$ac_delim
+SPANDSP_INCLUDE!$SPANDSP_INCLUDE$ac_delim
+PBX_SPANDSP!$PBX_SPANDSP$ac_delim
 CPP!$CPP$ac_delim
 EGREP!$EGREP$ac_delim
 AST_DECLARATION_AFTER_STATEMENT!$AST_DECLARATION_AFTER_STATEMENT$ac_delim
@@ -7638,7 +8067,7 @@
 LTLIBOBJS!$LTLIBOBJS$ac_delim
 _ACEOF
 
-  if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 6; then
+  if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 9; then
     break
   elif $ac_last_try; then
     { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5

Modified: trunk/configure.ac
URL: http://svn.digium.com/view/asterisk-addons/trunk/configure.ac?view=diff&rev=497&r1=496&r2=497
==============================================================================
--- trunk/configure.ac (original)
+++ trunk/configure.ac Fri Dec 14 15:56:06 2007
@@ -173,10 +173,12 @@
 AST_EXT_LIB_SETUP([NCURSES], [ncurses], [ncurses])
 AST_EXT_LIB_SETUP([MYSQLCLIENT], [mysqlclient], [mysqlclient])
 AST_EXT_LIB_SETUP([ASTERISK], [asterisk], [asterisk])
+AST_EXT_LIB_SETUP([SPANDSP], [spandsp Library], [spandsp])
 
 AST_EXT_LIB_CHECK([BLUETOOTH], [bluetooth], [ba2str], [bluetooth/bluetooth.h])
 AST_EXT_LIB_CHECK([CURSES], [curses], [initscr], [curses.h])
 AST_EXT_LIB_CHECK([NCURSES], [ncurses], [initscr], [curses.h])
+AST_EXT_LIB_CHECK([SPANDSP], [spandsp], [fax_init], [spandsp.h], [-ltiff])
 
 AC_MSG_CHECKING(for -Wdeclaration-after-statement support)
 if $(${CC} -Wdeclaration-after-statement -S -o /dev/null -xc /dev/null > /dev/null 2>&1); then

Modified: trunk/makeopts.in
URL: http://svn.digium.com/view/asterisk-addons/trunk/makeopts.in?view=diff&rev=497&r1=496&r2=497
==============================================================================
--- trunk/makeopts.in (original)
+++ trunk/makeopts.in Fri Dec 14 15:56:06 2007
@@ -49,3 +49,6 @@
 
 NCURSES_LIB=@NCURSES_LIB@
 NCURSES_INCLUDE=@NCURSES_INCLUDE@
+
+SPANDSP_INCLUDE=@SPANDSP_INCLUDE@
+SPANDSP_LIB=@SPANDSP_LIB@

Modified: trunk/menuselect-tree
URL: http://svn.digium.com/view/asterisk-addons/trunk/menuselect-tree?view=diff&rev=497&r1=496&r2=497
==============================================================================
--- trunk/menuselect-tree (original)
+++ trunk/menuselect-tree Fri Dec 14 15:56:06 2007
@@ -7,6 +7,10 @@
 			<depend>asterisk</depend>
 		</member>
 		<member name="app_saycountpl" remove_on_change="app_saycountpl.so app_saycountpl.so" displayname="Say Polish Counting Words">
+			<depend>asterisk</depend>
+		</member>
+		<member name="app_fax" remove_on_change="app_fax.so app_fax.o" displayname="Send and receive FAXes">
+			<depend>spandsp</depend>
 			<depend>asterisk</depend>
 		</member>
 		<member name="cdr_addon_mysql" remove_on_change="cdr_addon_mysql.so cdr_addon_mysql.o" displayname="MySQL CDR Backend">




More information about the asterisk-addons-commits mailing list