From 13e757450d36779e67a130493c63e0fe7826c099 Mon Sep 17 00:00:00 2001 From: Jim Dixon Date: Tue, 20 Dec 2005 23:41:59 +0000 Subject: New version, including half/semi-half duplex modes and system announcements git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@7566 65c4cc65-6c06-0410-ace0-fbb531ad65f3 --- apps/app_rpt.c | 142 ++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 121 insertions(+), 21 deletions(-) (limited to 'apps/app_rpt.c') diff --git a/apps/app_rpt.c b/apps/app_rpt.c index c8b10e44d..f3dafad52 100644 --- a/apps/app_rpt.c +++ b/apps/app_rpt.c @@ -20,7 +20,7 @@ /* * * Radio Repeater / Remote Base program - * version 0.37 11/3/05 + * version 0.39 12/19/05 * * See http://www.zapatatelephony.org/app_rpt.html * @@ -114,6 +114,9 @@ #define MAXREMSTR 15 +#define DELIMCHR ',' +#define QUOTECHR 34 + #define NODES "nodes" #define MEMORY "memory" #define FUNCTIONS "functions" @@ -139,7 +142,8 @@ enum {REM_OFF,REM_MONITOR,REM_TX}; enum{ID,PROC,TERM,COMPLETE,UNKEY,REMDISC,REMALREADY,REMNOTFOUND,REMGO, CONNECTED,CONNFAIL,STATUS,TIMEOUT,ID1, STATS_TIME, - STATS_VERSION, IDTALKOVER, ARB_ALPHA, TEST_TONE, REV_PATCH}; + STATS_VERSION, IDTALKOVER, ARB_ALPHA, TEST_TONE, REV_PATCH, + TAILMSG}; enum {REM_SIMPLEX,REM_MINUS,REM_PLUS}; @@ -153,7 +157,8 @@ enum {DLY_TELEM, DLY_ID, DLY_UNKEY, DLY_CALLTERM}; enum {REM_MODE_FM,REM_MODE_USB,REM_MODE_LSB,REM_MODE_AM}; -enum {HF_SCAN_OFF,HF_SCAN_DOWN_SLOW,HF_SCAN_DOWN_QUICK,HF_SCAN_DOWN_FAST,HF_SCAN_UP_SLOW,HF_SCAN_UP_QUICK,HF_SCAN_UP_FAST}; +enum {HF_SCAN_OFF,HF_SCAN_DOWN_SLOW,HF_SCAN_DOWN_QUICK, + HF_SCAN_DOWN_FAST,HF_SCAN_UP_SLOW,HF_SCAN_UP_QUICK,HF_SCAN_UP_FAST}; #include "asterisk.h" @@ -197,7 +202,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$") #include "asterisk/say.h" #include "asterisk/localtime.h" -static char *tdesc = "Radio Repeater / Remote Base version 0.37 11/03/2005"; +static char *tdesc = "Radio Repeater / Remote Base version 0.39 12/19/2005"; static char *app = "Rpt"; @@ -341,6 +346,7 @@ static struct rpt int totime; int idtime; int unkeytocttimer; + int duplex; char keyed; char exttx; char localtx; @@ -360,7 +366,7 @@ static struct rpt struct rpt_tele tele; pthread_t rpt_call_thread,rpt_thread; time_t rem_dtmf_time,dtmf_time_rem; - int tailtimer,totimer,idtimer,txconf,conf,callmode,cidx,scantimer; + int tailtimer,totimer,idtimer,txconf,conf,callmode,cidx,scantimer,tmsgtimer; int mustid; int politeid; int dtmfidx,rem_dtmfidx; @@ -387,6 +393,11 @@ static struct rpt int longestfunc; int longestnode; int threadrestarts; + int tailmessagetime; + int tailsquashedtime; + char *tailmessages[500]; + int tailmessagemax; + int tailmessagen; time_t disgorgetime; time_t lastthreadrestarttime; char nobusyout; @@ -459,6 +470,44 @@ static struct function_table_tag function_table[] = { {"remote", function_remote} } ; +static int finddelim(char *str,char *strp[]) +{ +int i,inquo; + + inquo = 0; + i = 0; + strp[i++] = str; + if (!*str) + { + strp[0] = 0; + return(0); + } + for(; *str; str++) + { + if (*str == QUOTECHR) + { + if (inquo) + { + *str = 0; + inquo = 0; + } + else + { + strp[i - 1] = str + 1; + inquo = 1; + } + } + if ((*str == DELIMCHR) && (!inquo)) + { + *str = 0; + strp[i++] = str + 1; + } + } + strp[i] = 0; + return(i); + +} + static int myatoi(char *str) { int ret; @@ -1006,8 +1055,9 @@ struct tm localtm; ci.chan = 0; /* If there's an ID queued, only connect the ID audio to the local tx conference so linked systems can't hear it */ - ci.confno = (((mytele->mode == ID) || (mytele->mode == IDTALKOVER) || (mytele->mode == UNKEY)) ? - myrpt->txconf : myrpt->conf); + ci.confno = (((mytele->mode == ID) || (mytele->mode == IDTALKOVER) || (mytele->mode == UNKEY) || + (mytele->mode == TAILMSG)) ? + myrpt->txconf : myrpt->conf); ci.confmode = ZT_CONF_CONFANN; /* first put the channel on the conference in announce mode */ if (ioctl(mychannel->fds[0],ZT_SETCONF,&ci) == -1) @@ -1023,15 +1073,18 @@ struct tm localtm; ast_stopstream(mychannel); switch(mytele->mode) { + case ID: case ID1: /* wait a bit */ wait_interval(myrpt, (mytele->mode == ID) ? DLY_ID : DLY_TELEM,mychannel); res = telem_any(mychannel, ident); - imdone=1; - + imdone=1; break; + case TAILMSG: + res = ast_streamfile(mychannel, myrpt->tailmessages[myrpt->tailmessagen], mychannel->language); + break; case IDTALKOVER: p = ast_variable_retrieve(cfg, nodename, "idtalkover"); @@ -1482,6 +1535,18 @@ struct tm localtm; } ast_stopstream(mychannel); ast_mutex_lock(&myrpt->lock); + if (mytele->mode == TAILMSG) + { + if (!res) + { + myrpt->tailmessagen++; + if(myrpt->tailmessagen >= myrpt->tailmessagemax) myrpt->tailmessagen = 0; + } + else + { + myrpt->tmsgtimer = myrpt->tailsquashedtime; + } + } remque((struct qelem *)mytele); ast_mutex_unlock(&myrpt->lock); free(mytele); @@ -2823,7 +2888,7 @@ struct zt_radio_param r; } } -static int serial_remote_io(struct rpt *myrpt, char *txbuf, int txbytes, char *rxbuf, +static int serial_remote_io(struct rpt *myrpt, unsigned char *txbuf, int txbytes, char *rxbuf, int rxmaxbytes, int asciiflag) { int i; @@ -2855,7 +2920,8 @@ static int serial_remote_io(struct rpt *myrpt, char *txbuf, int txbytes, char *r static int setrbi(struct rpt *myrpt) { -char tmp[MAXREMSTR] = "",rbicmd[5],*s; +char tmp[MAXREMSTR] = "",*s; +unsigned char rbicmd[5]; int band,txoffset = 0,txpower = 0,txpl; /* must be a remote system */ @@ -4528,7 +4594,7 @@ static void *rpt(void *this) { struct rpt *myrpt = (struct rpt *)this; char *tele,*idtalkover; -int ms = MSWAIT,lasttx=0,val,remrx=0,identqueued,nonidentqueued,res; +int ms = MSWAIT,i,lasttx=0,val,remrx=0,identqueued,nonidentqueued,res, tailmessagequeued; struct ast_channel *who; ZT_CONFINFO ci; /* conference info */ time_t dtmf_time,t; @@ -4676,7 +4742,8 @@ char cmd[MAXDTMF+1] = ""; /* make a conference for the pseudo */ ci.chan = 0; ci.confno = -1; /* make a new conf */ - ci.confmode = ZT_CONF_CONFANNMON; + ci.confmode = (myrpt->duplex == 2) ? ZT_CONF_CONFANNMON : + (ZT_CONF_CONF | ZT_CONF_LISTENER | ZT_CONF_TALKER); /* first put the channel on the conference in announce mode */ if (ioctl(myrpt->pchannel->fds[0],ZT_SETCONF,&ci) == -1) { @@ -4728,6 +4795,7 @@ char cmd[MAXDTMF+1] = ""; myrpt->links.prev = &myrpt->links; myrpt->tailtimer = 0; myrpt->totimer = 0; + myrpt->tmsgtimer = myrpt->tailmessagetime; myrpt->idtimer = myrpt->politeid; myrpt->mustid = 0; myrpt->callmode = 0; @@ -4835,35 +4903,46 @@ char cmd[MAXDTMF+1] = ""; /* Build a fresh totx from myrpt->keyed and autopatch activated */ - totx = myrpt->localtx || myrpt->callmode; + totx = myrpt->callmode; + if (myrpt->duplex > 1) totx = totx || myrpt->localtx; /* Traverse the telemetry list to see if there's an ID queued and if there is not an ID queued */ identqueued = 0; nonidentqueued = 0; - + tailmessagequeued = 0; + telem = myrpt->tele.next; while(telem != &myrpt->tele) { + if((telem->mode == ID) || (telem->mode == IDTALKOVER)){ identqueued = 1; } + else if(telem->mode == TAILMSG) + { + tailmessagequeued = 1; + } else - nonidentqueued = 1; + { + if (telem->mode != UNKEY) nonidentqueued = 1; + } telem = telem->next; } /* Add in any non-id telemetry */ - totx = totx || nonidentqueued; + if (myrpt->duplex > 0) totx = totx || nonidentqueued; /* Update external transmitter PTT state with everything but ID telemetry */ myrpt->exttx = totx; + if (myrpt->duplex < 2) myrpt->exttx = myrpt->exttx || myrpt->localtx; /* Add in ID telemetry to local transmitter */ - totx = totx || remrx || identqueued; + totx = totx || remrx; + if (myrpt->duplex > 0) totx = totx || identqueued || (telem->mode == UNKEY); if (!totx) { @@ -4905,7 +4984,8 @@ char cmd[MAXDTMF+1] = ""; /* if not timed-out, add in tail */ if (myrpt->totimer) totx = totx || myrpt->tailtimer; /* If user or links key up or are keyed up over standard ID, switch to talkover ID, if one is defined */ - if (identqueued && (myrpt->keyed || remrx) && idtalkover) { + /* If tail message, kill the message if someone keys up over it */ + if ((myrpt->keyed || remrx) && ((identqueued && idtalkover) || (tailmessagequeued))) { int hasid = 0,hastalkover = 0; telem = myrpt->tele.next; @@ -4914,6 +4994,9 @@ char cmd[MAXDTMF+1] = ""; if (telem->chan) ast_softhangup(telem->chan, AST_SOFTHANGUP_DEV); /* Whoosh! */ hasid = 1; } + if(telem->mode == TAILMSG){ + if (telem->chan) ast_softhangup(telem->chan, AST_SOFTHANGUP_DEV); /* Whoosh! */ + } if (telem->mode == IDTALKOVER) hastalkover = 1; telem = telem->next; } @@ -4936,7 +5019,7 @@ char cmd[MAXDTMF+1] = ""; ast_mutex_lock(&myrpt->lock); } /* let telemetry transmit anyway (regardless of timeout) */ - totx = totx || (myrpt->tele.next != &myrpt->tele); + if (myrpt->duplex > 0) totx = totx || (myrpt->tele.next != &myrpt->tele); if (totx && (!lasttx)) { lasttx = 1; @@ -5114,12 +5197,21 @@ char cmd[MAXDTMF+1] = ""; #endif l = l->next; } + i = myrpt->tailtimer; if (myrpt->tailtimer) myrpt->tailtimer -= elap; if (myrpt->tailtimer < 0) myrpt->tailtimer = 0; + if ((myrpt->tailmessagetime) && (myrpt->tailtimer == 0) && i && (myrpt->tmsgtimer == 0)){ + myrpt->tmsgtimer = myrpt->tailmessagetime; + rpt_telemetry(myrpt, TAILMSG, NULL); + } + if (myrpt->tailtimer < 0) myrpt->tailtimer = 0; if (myrpt->totimer) myrpt->totimer -= elap; if (myrpt->totimer < 0) myrpt->totimer = 0; if (myrpt->idtimer) myrpt->idtimer -= elap; if (myrpt->idtimer < 0) myrpt->idtimer = 0; + if (myrpt->tmsgtimer) myrpt->tmsgtimer -= elap; + if (myrpt->tmsgtimer < 0) myrpt->tmsgtimer = 0; + ast_mutex_unlock(&myrpt->lock); if (!ms) continue; if (who == myrpt->rxchannel) /* if it was a read from rx */ @@ -5652,11 +5744,19 @@ pthread_attr_t attr; val = ast_variable_retrieve(cfg,this,"totime"); if (val) rpt_vars[n].totime = atoi(val); else rpt_vars[n].totime = TOTIME; - + + rpt_vars[n].tailmessagetime = retrieve_astcfgint(this, "tailmessagetime", 0, 2400000, 0); + rpt_vars[n].tailsquashedtime = retrieve_astcfgint(this, "tailsquashedtime", 0, 2400000, 0); + rpt_vars[n].duplex = retrieve_astcfgint(this,"duplex",0,3,2); rpt_vars[n].idtime = retrieve_astcfgint( this, "idtime", 60000, 2400000, IDTIME); /* Enforce a min max */ rpt_vars[n].politeid = retrieve_astcfgint( this, "politeid", 30000, 300000, POLITEID); /* Enforce a min max */ rpt_vars[n].remote = ast_variable_retrieve(cfg,this,"remote"); rpt_vars[n].tonezone = ast_variable_retrieve(cfg,this,"tonezone"); + rpt_vars[n].tailmessages[0] = 0; + rpt_vars[n].tailmessagemax = 0; + rpt_vars[n].tailmessagen = 0; + val = ast_variable_retrieve(cfg,this,"tailmessagelist"); + if (val) rpt_vars[n].tailmessagemax = finddelim(val,rpt_vars[n].tailmessages); val = ast_variable_retrieve(cfg,this,"iobase"); /* do not use atoi() here, we need to be able to have the input specified in hex or decimal so we use -- cgit v1.2.3