[Asterisk-cvs] asterisk/apps Makefile,1.64,1.65 app_rpt.c,1.3,1.4

jim at lists.digium.com jim at lists.digium.com
Mon May 31 11:48:20 CDT 2004


Update of /usr/cvsroot/asterisk/apps
In directory mongoose.digium.com:/tmp/cvs-serv8955/apps

Modified Files:
	Makefile app_rpt.c 
Log Message:
Complete re-vamp of Radio Repeater application (app_rpt) and VERY minor changes in chan_zap (to allow pseudo-channels to work properly (finally!)) and in dsp.c to allow for super-relaxed DTMF decoding which radio systems need to function properly.


Index: Makefile
===================================================================
RCS file: /usr/cvsroot/asterisk/apps/Makefile,v
retrieving revision 1.64
retrieving revision 1.65
diff -u -d -r1.64 -r1.65
--- Makefile	27 May 2004 22:12:55 -0000	1.64
+++ Makefile	31 May 2004 16:04:10 -0000	1.65
@@ -35,9 +35,9 @@
 
 #APPS+=app_sql_postgres.so
 #APPS+=app_sql_odbc.so
+#APPS+=app_rpt.so
 
 APPS+=$(shell if [ -f /usr/include/linux/zaptel.h ]; then echo "app_zapras.so app_meetme.so app_flash.so app_zapbarge.so app_zapscan.so" ; fi)
-#APPS+=$(shell if [ -f /usr/include/zap.h ]; then echo "app_rpt.so" ; fi)
 
 CFLAGS+=-fPIC
 
@@ -64,12 +64,6 @@
 	for x in $(APPS); do $(INSTALL) -m 755 $$x $(DESTDIR)$(MODULES_DIR) ; done
 	rm -f $(DESTDIR)$(MODULES_DIR)/app_datetime.so
 
-app_todd.o: app_todd.c
-	gcc -pipe -O6 -g  -Iinclude -I../include -D_REENTRANT -march=i586 -DDO_CRASH -c -o  app_todd.o app_todd.c
-
-app_todd.so: app_todd.o
-	$(CC) $(SOLINK) -o $@ $< -L/usr/local/ssl/lib -lssl -lcrypto
-
 app_voicemail.so : app_voicemail.o
 ifeq ($(USE_MYSQL_VM_INTERFACE),1)
 	$(CC) $(SOLINK) -o $@ $(MLFLAGS) $< -L/usr/lib/mysql -lmysqlclient -lz

Index: app_rpt.c
===================================================================
RCS file: /usr/cvsroot/asterisk/apps/app_rpt.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- app_rpt.c	7 Apr 2004 20:12:42 -0000	1.3
+++ app_rpt.c	31 May 2004 16:04:10 -0000	1.4
@@ -2,17 +2,40 @@
  *
  * Asterisk -- A telephony toolkit for Linux.
  *
- * Radio Repeater program
+ * Radio Repeater / Remote Base program 
+ *  version 0.2 5/30/04
  * 
- * Copyright (C) 2002, Jim Dixon
+ * Copyright (C) 2002-2004, Jim Dixon
  *
  * Jim Dixon <jim at lambdatel.com>
  *
  * This program is free software, distributed under the terms of
  * the GNU General Public License
  *
+ * Repeater / Remote Functions:
+ * "Simple" Mode:  * - autopatch access, # - autopatch hangup
+ * Normal mode:
+ *  *0 - autopatch access
+ *  *1 - remote base off
+ *  *2 - remote base monitor
+ *  *3 - remote base tranceive
+ *  *8 - force ID
+ *  *9 - system reset
+ *
+ *  To send an asterisk (*) while dialing or talking on phone,
+ *  use the autopatch acess code.
  */
  
+/* number of digits for function after *. Must be at least 1 */
+#define	FUNCTION_LEN 1
+
+/* maximum digits in DTMF buffer, and seconds after * for DTMF command timeout */
+
+#define	MAXDTMF 10
+#define	DTMF_TIMEOUT 3
+
+enum {REM_OFF,REM_MONITOR,REM_TX};
+
 #include <asterisk/lock.h>
 #include <asterisk/file.h>
 #include <asterisk/logger.h>
@@ -40,7 +63,7 @@
 #include <tonezone.h>
 #include <linux/zaptel.h>
 
-static  char *tdesc = "Radio Repeater";
+static  char *tdesc = "Radio Repeater / Remote Base  version 0.2  05/30/2004";
 static int debug = 0;
 STANDARD_LOCAL_USER;
 LOCAL_USER_DECL;
@@ -58,17 +81,25 @@
 	char *name;
 	char *rxchanname;
 	char *txchanname;
+	char *rem_rxchanname;
+	char *rem_txchanname;
 	char *ourcontext;
 	char *ourcallerid;
 	char *acctcode;
 	char *idrecording;
+	char *tonezone;
 	int hangtime;
 	int totime;
 	int idtime;
-	struct ast_channel *rxchannel,*txchannel,*pchannel;
+	char remoterx;
+	char remotetx;
+	char remotemode;
+	char simple;
+	struct ast_channel *rxchannel,*txchannel,*rem_rxchannel;
+	struct ast_channel *rem_txchannel,*pchannel;
 	int tailtimer,totimer,idtimer,txconf,pconf,callmode,cidx;
 	pthread_t rpt_id_thread,rpt_term_thread,rpt_proc_thread,rpt_call_thread;
-	char mydtmf,iding,terming;
+	char mydtmf,iding,terming,teleing,comping,procing;
 	char exten[AST_MAX_EXTENSION];
 } rpt_vars[MAXRPTS];		
 
@@ -130,7 +161,7 @@
 	}
 	/* make a conference for the tx */
 	ci.chan = 0;
-	ci.confno = myrpt->pconf; /* use the tx conference */
+	ci.confno = myrpt->txconf; /* use the tx conference */
 	ci.confmode = ZT_CONF_CONFANN;
 	/* first put the channel on the conference in announce mode */
 	if (ioctl(mychannel->fds[0],ZT_SETCONF,&ci) == -1)
@@ -138,7 +169,7 @@
 		ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
 		pthread_exit(NULL);
 	}
-	myrpt->terming = 1;
+	myrpt->procing = 1;
 	ast_stopstream(mychannel);
 	res = ast_streamfile(mychannel, "callproceeding", mychannel->language);
 	if (!res) 
@@ -147,7 +178,7 @@
 		ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
 		res = 0;
 	}
-	myrpt->terming = 0;
+	myrpt->procing = 0;
 	ast_stopstream(mychannel);
 	ast_hangup(mychannel);
 	pthread_exit(NULL);
@@ -171,7 +202,7 @@
 	}
 	/* make a conference for the tx */
 	ci.chan = 0;
-	ci.confno = myrpt->pconf; /* use the tx conference */
+	ci.confno = myrpt->txconf; /* use the tx conference */
 	ci.confmode = ZT_CONF_CONFANN;
 	/* first put the channel on the conference in announce mode */
 	if (ioctl(mychannel->fds[0],ZT_SETCONF,&ci) == -1)
@@ -194,6 +225,89 @@
 	pthread_exit(NULL);
 }
 
+static void *rpt_complete(void *this)
+{
+ZT_CONFINFO ci;  /* conference info */
+int	res;
+struct	rpt *myrpt = (struct rpt *)this;
+struct ast_channel *mychannel;
+
+	/* wait a little bit */
+	usleep(1000000);
+	/* allocate a pseudo-channel thru asterisk */
+	mychannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo");
+	if (!mychannel)
+	{
+		fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
+		pthread_exit(NULL);
+	}
+	/* make a conference for the tx */
+	ci.chan = 0;
+	ci.confno = myrpt->txconf; /* use the tx conference */
+	ci.confmode = ZT_CONF_CONFANN;
+	/* first put the channel on the conference in announce mode */
+	if (ioctl(mychannel->fds[0],ZT_SETCONF,&ci) == -1)
+	{
+		ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
+		pthread_exit(NULL);
+	}
+	myrpt->comping = 1;
+	ast_stopstream(mychannel);
+	res = ast_streamfile(mychannel, "functioncomplete", mychannel->language);
+	if (!res) 
+		res = ast_waitstream(mychannel, "");
+	else {
+		ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
+		res = 0;
+	}
+	myrpt->comping = 0;
+	ast_stopstream(mychannel);
+	ast_hangup(mychannel);
+	pthread_exit(NULL);
+}
+
+static void *rpt_remote_telemetry(void *this)
+{
+ZT_CONFINFO ci;  /* conference info */
+int res;
+struct	rpt *myrpt = (struct rpt *)this;
+struct ast_channel *mychannel;
+
+	/* wait a little bit */
+	usleep(1000000);
+	/* allocate a pseudo-channel thru asterisk */
+	mychannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo");
+	if (!mychannel)
+	{
+		fprintf(stderr,"rpt:Sorry unable to obtain pseudo channel\n");
+		pthread_exit(NULL);
+	}
+	/* make a conference for the tx */
+	ci.chan = 0;
+	ci.confno = myrpt->txconf; /* use the tx conference */
+	ci.confmode = ZT_CONF_CONFANN;
+	/* first put the channel on the conference in announce mode */
+	if (ioctl(mychannel->fds[0],ZT_SETCONF,&ci) == -1)
+	{
+		ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
+		pthread_exit(NULL);
+	}
+	myrpt->teleing = 1;
+	ast_stopstream(mychannel);
+	res = ast_streamfile(mychannel, 
+		((myrpt->remotemode == REM_MONITOR) ? "remote_monitor" : "remote_tx"),
+			mychannel->language);
+	if (!res) 
+		res = ast_waitstream(mychannel, "");
+	else {
+		ast_log(LOG_WARNING, "ast_streamfile failed on %s\n", mychannel->name);
+		res = 0;
+	}
+	myrpt->teleing = 0;
+	ast_hangup(mychannel);
+	pthread_exit(NULL);
+}
+
 static void *rpt_call(void *this)
 {
 ZT_CONFINFO ci;  /* conference info */
@@ -244,6 +358,22 @@
 		myrpt->callmode = 0;
 		pthread_exit(NULL);
 	}
+	if (myrpt->tonezone && (tone_zone_set_zone(mychannel->fds[0],myrpt->tonezone) == -1))
+	{
+		ast_log(LOG_WARNING, "Unable to set tone zone %s\n",myrpt->tonezone);
+		ast_hangup(mychannel);
+		ast_hangup(genchannel);
+		myrpt->callmode = 0;
+		pthread_exit(NULL);
+	}
+	if (myrpt->tonezone && (tone_zone_set_zone(genchannel->fds[0],myrpt->tonezone) == -1))
+	{
+		ast_log(LOG_WARNING, "Unable to set tone zone %s\n",myrpt->tonezone);
+		ast_hangup(mychannel);
+		ast_hangup(genchannel);
+		myrpt->callmode = 0;
+		pthread_exit(NULL);
+	}
 	/* start dialtone */
 	if (tone_zone_play_tone(mychannel->fds[0],ZT_TONE_DIALTONE) < 0)
 	{
@@ -358,14 +488,104 @@
 	pthread_exit(NULL);
 }
 
+static void process_dtmf(char *cmd,struct rpt *myrpt)
+{
+pthread_attr_t attr;
+ZT_CONFINFO ci;  /* conference info */
+
+	switch(atoi(cmd))
+	{
+	case 0:	/* autopatch on / send asterisk (*) */
+		/* if on call, force * into current audio stream */
+		if ((myrpt->callmode == 2) || (myrpt->callmode == 3))
+		{
+			myrpt->mydtmf = '*';
+			break;
+		}
+		if (myrpt->callmode) return;
+		myrpt->callmode = 1;
+		myrpt->cidx = 0;
+		myrpt->exten[myrpt->cidx] = 0;
+	        pthread_attr_init(&attr);
+	        pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+		pthread_create(&myrpt->rpt_call_thread,&attr,rpt_call,(void *)myrpt);
+		return;
+	case 9: /* master reset */
+		myrpt->callmode = 0;
+		/* fall thru intentionally */
+	case 1: /* remote base off */
+		if (myrpt->rem_rxchannel == NULL) return;
+		myrpt->remotemode = REM_OFF;
+		ci.chan = 0;
+		ci.confno = 0;
+		ci.confmode = 0;
+		/* Take off conf */
+		if (ioctl(myrpt->rem_rxchannel->fds[0],ZT_SETCONF,&ci) == -1)
+		{
+			ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
+			pthread_exit(NULL);
+		}
+		/* Take off conf */
+		if (ioctl(myrpt->rem_txchannel->fds[0],ZT_SETCONF,&ci) == -1)
+		{
+			ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
+			pthread_exit(NULL);
+		}
+		break;
+	case 2: /* remote base monitor */
+		if (myrpt->rem_rxchannel == NULL) return;
+		myrpt->remotemode = REM_MONITOR;
+		if (myrpt->remoterx && (!myrpt->remotetx))
+		{
+			ci.chan = 0;
+			ci.confno = myrpt->pconf;
+			ci.confmode = ZT_CONF_CONF | ZT_CONF_TALKER;
+			/* Put on conf */
+			if (ioctl(myrpt->rem_rxchannel->fds[0],ZT_SETCONF,&ci) == -1)
+			{
+				ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
+				pthread_exit(NULL);
+			}
+		}
+		break;
+	case 3: /* remote base tranceieve */
+		if (myrpt->rem_rxchannel == NULL) return;
+		myrpt->remotemode = REM_TX;
+		if (myrpt->remoterx && (!myrpt->remotetx))
+		{
+			ci.chan = 0;
+			ci.confno = myrpt->pconf;
+			ci.confmode = ZT_CONF_CONF | ZT_CONF_TALKER;
+			/* Put on conf */
+			if (ioctl(myrpt->rem_rxchannel->fds[0],ZT_SETCONF,&ci) == -1)
+			{
+				ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
+				pthread_exit(NULL);
+			}
+		}
+		break;
+	case 8: /* force ID */
+		myrpt->idtimer = 0;
+		return;
+	default:
+		return;
+	}
+	/* send function complete */
+        pthread_attr_init(&attr);
+        pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+	pthread_create(&myrpt->rpt_call_thread,&attr,rpt_complete,(void *)myrpt);
+}
+
 /* single thread with one file (request) to dial */
 static void *rpt(void *this)
 {
 struct	rpt *myrpt = (struct rpt *)this;
 char *tele;
-int ms = MSWAIT,lasttx,keyed,val;
+int ms = MSWAIT,lasttx,keyed,val,dtmfidx;
+char dtmfbuf[MAXDTMF];
 struct ast_channel *who;
 ZT_CONFINFO ci;  /* conference info */
+time_t	dtmf_time,t;
 pthread_attr_t attr;
 
 	tele = strchr(myrpt->rxchanname,'/');
@@ -390,7 +610,7 @@
 	}
 	else
 	{
-		fprintf(stderr,"rpt:Sorry unable to obtain channel\n");
+		fprintf(stderr,"rpt:Sorry unable to obtain Rx channel\n");
 		pthread_exit(NULL);
 	}
 	if (myrpt->txchanname)
@@ -417,7 +637,7 @@
 		}
 		else
 		{
-			fprintf(stderr,"rpt:Sorry unable to obtain channel\n");
+			fprintf(stderr,"rpt:Sorry unable to obtain Tx channel\n");
 			pthread_exit(NULL);
 		}
 	}
@@ -425,6 +645,70 @@
 	{
 		myrpt->txchannel = myrpt->rxchannel;
 	}
+	myrpt->rem_rxchannel = NULL;
+	myrpt->rem_txchannel = NULL;
+	myrpt->remoterx = 0;
+	myrpt->remotemode = REM_OFF;
+	if (myrpt->rem_rxchanname)
+	{
+		tele = strchr(myrpt->rem_rxchanname,'/');
+		if (!tele)
+		{
+			fprintf(stderr,"rpt:Dial number must be in format tech/number\n");
+			pthread_exit(NULL);
+		}
+		*tele++ = 0;
+		myrpt->rem_rxchannel = ast_request(myrpt->rem_rxchanname,AST_FORMAT_SLINEAR,tele);
+		if (myrpt->rem_rxchannel)
+		{
+			ast_set_read_format(myrpt->rem_rxchannel,AST_FORMAT_SLINEAR);
+			ast_set_write_format(myrpt->rem_rxchannel,AST_FORMAT_SLINEAR);
+			myrpt->rem_rxchannel->whentohangup = 0;
+			myrpt->rem_rxchannel->appl = "Apprpt";
+			myrpt->rem_rxchannel->data = "(Repeater/Remote Rx)";
+			if (option_verbose > 2)
+				ast_verbose(VERBOSE_PREFIX_3 "rpt (RemoteRx) initiating call to %s/%s on %s\n",
+					myrpt->rem_rxchanname,tele,myrpt->rem_rxchannel->name);
+			ast_call(myrpt->rem_rxchannel,tele,999);
+		}
+		else
+		{
+			fprintf(stderr,"rpt:Sorry unable to obtain RemoteRx channel\n");
+			pthread_exit(NULL);
+		}
+		if (myrpt->rem_txchanname)  /* if in remote base mode */
+		{
+			tele = strchr(myrpt->rem_txchanname,'/');
+			if (!tele)
+			{
+				fprintf(stderr,"rpt:Dial number must be in format tech/number\n");
+				pthread_exit(NULL);
+			}
+			*tele++ = 0;
+			myrpt->rem_txchannel = ast_request(myrpt->rem_txchanname,AST_FORMAT_SLINEAR,tele);
+			if (myrpt->rem_txchannel)
+			{
+				ast_set_read_format(myrpt->rem_txchannel,AST_FORMAT_SLINEAR);
+				ast_set_write_format(myrpt->rem_txchannel,AST_FORMAT_SLINEAR);
+				myrpt->rem_txchannel->whentohangup = 0;
+				myrpt->rem_txchannel->appl = "Apprpt";
+				myrpt->rem_txchannel->data = "(Repeater/Remote Tx)";
+				if (option_verbose > 2)
+					ast_verbose(VERBOSE_PREFIX_3 "rpt (RemoteTx) initiating call to %s/%s on %s\n",
+						myrpt->rem_txchanname,tele,myrpt->rem_txchannel->name);
+				ast_call(myrpt->rem_txchannel,tele,999);
+			}
+			else
+			{
+				fprintf(stderr,"rpt:Sorry unable to obtain Tx channel\n");
+				pthread_exit(NULL);
+			}
+		}
+		else
+		{
+			myrpt->rem_txchannel = myrpt->rem_rxchannel;
+		}
+	}
 	/* allocate a pseudo-channel thru asterisk */
 	myrpt->pchannel = ast_request("zap",AST_FORMAT_SLINEAR,"pseudo");
 	if (!myrpt->pchannel)
@@ -463,19 +747,39 @@
 	myrpt->totimer = 0;
 	myrpt->idtimer = 0;
 	lasttx = 0;
+	myrpt->remotetx = 0;
 	keyed = 0;
 	myrpt->callmode = 0;
+	dtmfidx = -1;
+	dtmfbuf[0] = 0;
+	dtmf_time = 0;
 	val = 0;
 	ast_channel_setoption(myrpt->rxchannel,AST_OPTION_TONE_VERIFY,&val,sizeof(char),0);
 	val = 1;
 	ast_channel_setoption(myrpt->rxchannel,AST_OPTION_RELAXDTMF,&val,sizeof(char),0);
+	if (myrpt->rem_rxchannel)
+	{
+		val = 0;
+		ast_channel_setoption(myrpt->rem_rxchannel,AST_OPTION_TONE_VERIFY,&val,sizeof(char),0);
+		val = 1;
+		ast_channel_setoption(myrpt->rem_rxchannel,AST_OPTION_RELAXDTMF,&val,sizeof(char),0);
+	}
 	while (ms >= 0)
 	{
 		struct ast_frame *f;
-		struct ast_channel *cs[3];
-		int totx,elap;
+		struct ast_channel *cs[5];
+		int totx,rem_totx,elap,n;
 
-		totx = (keyed || myrpt->callmode || myrpt->iding || myrpt->terming);
+		if (ast_check_hangup(myrpt->rxchannel)) break;
+		if (ast_check_hangup(myrpt->txchannel)) break;
+		if (myrpt->rem_rxchannel)
+		{
+			if (ast_check_hangup(myrpt->rem_rxchannel)) break;
+			if (ast_check_hangup(myrpt->rem_txchannel)) break;
+		}
+		totx = (keyed || myrpt->callmode || myrpt->iding || myrpt->terming
+		    || ((myrpt->remotemode != REM_OFF) && myrpt->remoterx) ||
+			myrpt->teleing || myrpt->comping || myrpt->procing);
 		if (!totx) myrpt->totimer = myrpt->totime;
 		else myrpt->tailtimer = myrpt->hangtime;
 		totx = (totx || myrpt->tailtimer) && myrpt->totimer;
@@ -486,6 +790,11 @@
 			myrpt->totimer = myrpt->totime;
 			continue;
 		}
+		/* if timed-out and in circuit busy after call */
+		if ((!totx) && (!myrpt->totimer) && (myrpt->callmode == 4))
+		{
+			myrpt->callmode = 0;
+		}
 		if (totx && (!myrpt->idtimer))
 		{
 			myrpt->idtimer = myrpt->idtime;
@@ -503,12 +812,75 @@
 			lasttx = 0;
 			ast_indicate(myrpt->txchannel,AST_CONTROL_RADIO_UNKEY);
 		}
-
-		cs[0] = myrpt->rxchannel;
-		cs[1] = myrpt->pchannel;
-		cs[2] = myrpt->txchannel;
+		rem_totx = ((keyed && (myrpt->remotemode == REM_TX)) && myrpt->totimer);
+		if (rem_totx && (!myrpt->remotetx))
+		{
+			myrpt->remotetx = 1;
+			ci.chan = 0;
+			ci.confno = 0;
+			ci.confmode = 0;
+			/* Take off conf */
+			if (ioctl(myrpt->rem_rxchannel->fds[0],ZT_SETCONF,&ci) == -1)
+			{
+				ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
+				pthread_exit(NULL);
+			}
+			ast_indicate(myrpt->rem_txchannel,AST_CONTROL_RADIO_KEY);
+			ci.chan = 0;
+			ci.confno = myrpt->txconf;
+			ci.confmode = ZT_CONF_CONF | ZT_CONF_LISTENER; 
+			/* Put the channel on the conference in listener mode */
+			if (ioctl(myrpt->rem_txchannel->fds[0],ZT_SETCONF,&ci) == -1)
+			{
+				ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
+				pthread_exit(NULL);
+			}
+		}
+		if ((!rem_totx) && myrpt->remotetx)
+		{
+			myrpt->remotetx = 0;
+			ast_indicate(myrpt->rem_txchannel,AST_CONTROL_RADIO_UNKEY);
+			ci.chan = 0;
+			ci.confno = 0;
+			ci.confmode = 0;
+			/* Take off conf */
+			if (ioctl(myrpt->rem_txchannel->fds[0],ZT_SETCONF,&ci) == -1)
+			{
+				ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
+				pthread_exit(NULL);
+			}
+			if (myrpt->remotemode != REM_OFF)
+			{
+				ci.chan = 0;
+				ci.confno = myrpt->pconf;
+				ci.confmode = ZT_CONF_CONF | ZT_CONF_TALKER;
+				/* Put on conf */
+				if (ioctl(myrpt->rem_rxchannel->fds[0],ZT_SETCONF,&ci) == -1)
+				{
+					ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
+					pthread_exit(NULL);
+				}
+			}
+		}
+		time(&t);
+		/* if DTMF timeout */
+		if ((dtmfidx >= 0) && ((dtmf_time + DTMF_TIMEOUT) < t))
+		{
+			dtmfidx = -1;
+			dtmfbuf[0] = 0;
+		}			
+		n = 0;
+		cs[n++] = myrpt->rxchannel;
+		cs[n++] = myrpt->pchannel;
+		if (myrpt->txchannel != myrpt->rxchannel) cs[n++] = myrpt->txchannel;
+		if (myrpt->rem_rxchannel)
+		{
+			cs[n++] = myrpt->rem_rxchannel;
+			if (myrpt->rem_txchannel != myrpt->rem_rxchannel)
+				cs[n++] = myrpt->rem_txchannel;
+		}
 		ms = MSWAIT;
-		who = ast_waitfor_n(cs,3,&ms);
+		who = ast_waitfor_n(cs,n,&ms);
 		if (who == NULL) ms = 0;
 		elap = MSWAIT - ms;
 		if (myrpt->tailtimer) myrpt->tailtimer -= elap;
@@ -535,15 +907,44 @@
 				char c;
 
 				c = (char) f->subclass; /* get DTMF char */
-				if ((!myrpt->callmode) && (c == '*'))
+				if (!myrpt->simple)
 				{
-					myrpt->callmode = 1;
-					myrpt->cidx = 0;
-					myrpt->exten[myrpt->cidx] = 0;
-				        pthread_attr_init(&attr);
-		 		        pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
-					pthread_create(&myrpt->rpt_call_thread,&attr,rpt_call,(void *)myrpt);
-					continue;
+					if (c == '*')
+					{
+						dtmfidx = 0;
+						dtmfbuf[dtmfidx] = 0;
+						time(&dtmf_time);
+						continue;
+					} 
+					else if ((c != '#') && (dtmfidx >= 0))
+					{
+						time(&dtmf_time);
+						if (dtmfidx < MAXDTMF)
+						{
+							dtmfbuf[dtmfidx++] = c;
+							dtmfbuf[dtmfidx] = 0;
+						}
+						if (dtmfidx == FUNCTION_LEN)
+						{
+							process_dtmf(dtmfbuf,myrpt);
+							dtmfbuf[0] = 0;
+							dtmfidx = -1;
+							continue;
+						}
+					}
+				}
+				else
+				{
+					if ((!myrpt->callmode) && (c == '*'))
+					{
+						myrpt->callmode = 1;
+						myrpt->cidx = 0;
+						myrpt->exten[myrpt->cidx] = 0;
+					        pthread_attr_init(&attr);
+			 		        pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+						pthread_create(&myrpt->rpt_call_thread,&attr,rpt_call,(void *)myrpt);
+						continue;
+					}
 				}
 				if (myrpt->callmode && (c == '#'))
 				{
@@ -595,9 +996,16 @@
 				{
 					if (debug) printf("@@@@ rx un-key\n");
 					keyed = 0;
+					if (myrpt->remotemode != REM_OFF)
+					{
+					        pthread_attr_init(&attr);
+			 		        pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+						pthread_create(&myrpt->rpt_proc_thread,&attr,rpt_remote_telemetry,(void *) myrpt);
+					}
 				}
 			}
 			ast_frfree(f);
+			continue;
 		}
 		if (who == myrpt->pchannel) /* if it was a read from pseudo */
 		{
@@ -610,6 +1018,8 @@
 			if (f->frametype == AST_FRAME_VOICE)
 			{
 				ast_write(myrpt->txchannel,f);
+				if (myrpt->remotemode == REM_TX)
+					ast_write(myrpt->rem_txchannel,f);
 			}
 			if (f->frametype == AST_FRAME_CONTROL)
 			{
@@ -621,6 +1031,7 @@
 				}
 			}
 			ast_frfree(f);
+			continue;
 		}
 		if (who == myrpt->txchannel) /* if it was a read from tx */
 		{
@@ -640,12 +1051,95 @@
 				}
 			}
 			ast_frfree(f);
+			continue;
+		}
+		if (who == myrpt->rem_rxchannel) /* if it was a read from rx */
+		{
+			f = ast_read(myrpt->rem_rxchannel);
+			if (!f)
+			{
+				if (debug) printf("@@@@ rpt:Hung Up\n");
+				break;
+			}
+			if (f->frametype == AST_FRAME_CONTROL)
+			{
+				if (f->subclass == AST_CONTROL_HANGUP)
+				{
+					if (debug) printf("@@@@ rpt:Hung Up\n");
+					ast_frfree(f);
+					break;
+				}
+				/* if RX key */
+				if (f->subclass == AST_CONTROL_RADIO_KEY)
+				{
+					if (debug) printf("@@@@ remote rx key\n");
+					if (!myrpt->remotetx)
+					{
+						myrpt->remoterx = 1;
+						ci.chan = 0;
+						ci.confno = myrpt->pconf;
+						ci.confmode = ZT_CONF_CONF | ZT_CONF_TALKER;
+						/* Put on conf */
+						if (ioctl(myrpt->rem_rxchannel->fds[0],ZT_SETCONF,&ci) == -1)
+						{
+							ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
+							pthread_exit(NULL);
+						}
+					}
+				}
+				/* if RX un-key */
+				if (f->subclass == AST_CONTROL_RADIO_UNKEY)
+				{
+					if (debug) printf("@@@@ remote rx un-key\n");
+					if (!myrpt->remotetx) 
+					{
+						myrpt->remoterx = 0;
+						ci.chan = 0;
+						ci.confno = 0;
+						ci.confmode = 0;
+						/* Take off conf */
+						if (ioctl(myrpt->rem_rxchannel->fds[0],ZT_SETCONF,&ci) == -1)
+						{
+							ast_log(LOG_WARNING, "Unable to set conference mode to Announce\n");
+							pthread_exit(NULL);
+						}
+					}
+				}
+			}
+			ast_frfree(f);
+			continue;
+		}
+		if (who == myrpt->rem_txchannel) /* if it was a read from remote tx */
+		{
+			f = ast_read(myrpt->rem_txchannel);
+			if (!f)
+			{
+				if (debug) printf("@@@@ rpt:Hung Up\n");
+				break;
+			}
+			if (f->frametype == AST_FRAME_CONTROL)
+			{
+				if (f->subclass == AST_CONTROL_HANGUP)
+				{
+					if (debug) printf("@@@@ rpt:Hung Up\n");
+					ast_frfree(f);
+					break;
+				}
+			}
+			ast_frfree(f);
+			continue;
 		}
 
 	}
 	ast_hangup(myrpt->pchannel);
 	ast_hangup(myrpt->rxchannel);
-	ast_hangup(myrpt->txchannel);
+	if (myrpt->txchannel != myrpt->rxchannel) ast_hangup(myrpt->txchannel);
+	if (myrpt->rem_rxchannel)
+	{
+		ast_hangup(myrpt->rem_rxchannel);
+		if (myrpt->rem_txchannel != myrpt->rem_rxchannel) 
+			ast_hangup(myrpt->rem_txchannel);
+	}
 	if (debug) printf("@@@@ rpt:Hung up channel\n");
 	pthread_exit(NULL);
 	return NULL;
@@ -675,6 +1169,8 @@
 		rpt_vars[n].name = this;
 		rpt_vars[n].rxchanname = ast_variable_retrieve(cfg,this,"rxchannel");
 		rpt_vars[n].txchanname = ast_variable_retrieve(cfg,this,"txchannel");
+		rpt_vars[n].rem_rxchanname = ast_variable_retrieve(cfg,this,"remote_rxchannel");
+		rpt_vars[n].rem_txchanname = ast_variable_retrieve(cfg,this,"remote_txchannel");
 		rpt_vars[n].ourcontext = ast_variable_retrieve(cfg,this,"context");
 		if (!rpt_vars[n].ourcontext) rpt_vars[n].ourcontext = this;
 		rpt_vars[n].ourcallerid = ast_variable_retrieve(cfg,this,"callerid");
@@ -689,6 +1185,10 @@
 		val = ast_variable_retrieve(cfg,this,"idtime");
 		if (val) rpt_vars[n].idtime = atoi(val);
 			else rpt_vars[n].idtime = IDTIME;
+		val = ast_variable_retrieve(cfg,this,"simple");
+		if (val) rpt_vars[n].simple = ast_true(val); 
+			else rpt_vars[n].simple = 0;
+		rpt_vars[n].tonezone = ast_variable_retrieve(cfg,this,"tonezone");
 		n++;
 	}
 	ast_log(LOG_DEBUG, "Total of %d repeaters configured.\n",n);




More information about the svn-commits mailing list