Via bug9228, no way to create macros via AEL, and some of the apps allow you to call...
[asterisk/asterisk.git] / apps / app_rpt.c
index 7ae10fb..40880da 100644 (file)
 
 #define        MAXDTMF 32
 #define        MAXMACRO 2048
+#define        MAXGOSUB 2048
 #define        MACROTIME 100
+#define        GOSUBTIME 100
 #define        MACROPTIME 500
+#define        GOSUBPTIME 500
 #define        DTMF_TIMEOUT 3
 
 #ifdef __RPT_NOTCH
 #define        NODES "nodes"
 #define MEMORY "memory"
 #define MACRO "macro"
+#define GOSUB "gosub"
 #define        FUNCTIONS "functions"
 #define TELEMETRY "telemetry"
 #define MORSE "morse"
@@ -183,7 +187,7 @@ 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,
-       TAILMSG, MACRO_NOTFOUND, MACRO_BUSY, LASTNODEKEY};
+       TAILMSG, MACRO_NOTFOUND, GOSUB_NOTFOUND, MACRO_BUSY, GOSUB_BUSY, LASTNODEKEY};
 
 enum {REM_SIMPLEX, REM_MINUS, REM_PLUS};
 
@@ -418,7 +422,9 @@ static struct rpt
                );
                char memory[80];
                char macro[80];
+               char gosub[80];
                char startupmacro[80];
+               char startupgosub[80];
                int iobase;
                char funcchar;
                char endchar;
@@ -437,6 +443,7 @@ static struct rpt
        char enable;
        char dtmfbuf[MAXDTMF];
        char macrobuf[MAXMACRO];
+       char gosubbuf[MAXGOSUB];
        char rem_dtmfbuf[MAXDTMF];
        char lastdtmfcommand[MAXDTMF];
        char cmdnode[50];
@@ -474,6 +481,7 @@ static struct rpt
        char patchcontext[MAXPATCHCONTEXT];
        int patchdialtime;
        int macro_longest;
+       int gosub_longest;
        int phone_longestfunc;
        int dphone_longestfunc;
        int link_longestfunc;
@@ -484,6 +492,7 @@ static struct rpt
        time_t disgorgetime;
        time_t lastthreadrestarttime;
        long macrotimer;
+       long gosubtimer;
        char lastnodewhichkeyedusup[MAXNODESTR];
 #ifdef __RPT_NOTCH
        struct rptfilter
@@ -784,6 +793,7 @@ static int function_status(struct rpt *myrpt, char *param, char *digitbuf, int c
 static int function_cop(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
 static int function_remote(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
 static int function_macro(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
+static int function_gosub(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink);
 /*
 * Function table
 */
@@ -796,6 +806,7 @@ static struct function_table_tag function_table[] = {
        {"status", function_status},
        {"remote", function_remote},
        {"macro", function_macro}
+       {"gosub", function_gosub}
 } ;
 
 /*
@@ -955,6 +966,7 @@ static void load_rpt_vars(int n, int init)
        rpt_vars[n].p.politeid = POLITEID;
        ast_copy_string(rpt_vars[n].p.memory, MEMORY, sizeof(rpt_vars[n].p.memory));
        ast_copy_string(rpt_vars[n].p.macro, MACRO, sizeof(rpt_vars[n].p.macro));
+       ast_copy_string(rpt_vars[n].p.gosub, GOSUB, sizeof(rpt_vars[n].p.gosub));
        rpt_vars[n].p.iobase = DEFAULT_IOBASE;
        ast_copy_string(rpt_vars[n].p.functions, FUNCTIONS, sizeof(rpt_vars[n].p.functions));
        rpt_vars[n].p.simple = 1;
@@ -1014,8 +1026,12 @@ static void load_rpt_vars(int n, int init)
                        ast_copy_string(rpt_vars[n].p.memory, var->value, sizeof(rpt_vars[n].p.memory));
                } else if (!strcmp(var->name, "macro")) {
                        ast_copy_string(rpt_vars[n].p.macro, var->value, sizeof(rpt_vars[n].p.macro));
+               } else if (!strcmp(var->name, "gosub")) {
+                       ast_copy_string(rpt_vars[n].p.gosub, var->value, sizeof(rpt_vars[n].p.gosub));
                } else if (!strcmp(var->name, "startup_macro")) {
                        ast_copy_string(rpt_vars[n].p.startupmacro, var->value, sizeof(rpt_vars[n].p.startupmacro));
+               } else if (!strcmp(var->name, "startup_gosub")) {
+                       ast_copy_string(rpt_vars[n].p.startupgosub, var->value, sizeof(rpt_vars[n].p.startupgosub));
                } else if (!strcmp(var->name, "iobase")) {
                        /* do not use atoi() here, we need to be able to have
                           the input specified in hex or decimal so we use
@@ -1101,6 +1117,12 @@ static void load_rpt_vars(int n, int init)
                if ((j = strlen(vp->name)) > rpt_vars[n].macro_longest)
                        rpt_vars[n].macro_longest = j;
        }
+
+       rpt_vars[n].gosub_longest = 1;
+       for (vp = ast_variable_browse(cfg, rpt_vars[n].p.gosub); vp; vp = vp->next) {
+               if ((j = strlen(vp->name)) > rpt_vars[n].gosub_longest)
+                       rpt_vars[n].gosub_longest = j;
+       }
        ast_mutex_unlock(&rpt_vars[n].lock);
 }
 
@@ -1961,11 +1983,21 @@ static void *rpt_tele_thread(void *this)
                wait_interval(myrpt, DLY_TELEM, mychannel);
                res = ast_streamfile(mychannel, "rpt/macro_notfound", mychannel->language);
                break;
+       case GOSUB_NOTFOUND:
+               /* wait a little bit */
+               wait_interval(myrpt, DLY_TELEM, mychannel);
+               res = ast_streamfile(mychannel, "rpt/gosub_notfound", mychannel->language);
+               break;
        case MACRO_BUSY:
                /* wait a little bit */
                wait_interval(myrpt, DLY_TELEM, mychannel);
                res = ast_streamfile(mychannel, "rpt/macro_busy", mychannel->language);
                break;
+       case GOSUB_BUSY:
+               /* wait a little bit */
+               wait_interval(myrpt, DLY_TELEM, mychannel);
+               res = ast_streamfile(mychannel, "rpt/gosub_busy", mychannel->language);
+               break;
        case UNKEY:
                if (myrpt->patchnoct && myrpt->callmode) { /* If no CT during patch configured, then don't send one */
                        imdone = 1;
@@ -3284,6 +3316,54 @@ static int function_macro(struct rpt *myrpt, char *param, char *digitbuf, int co
 }
 
 /*
+*  Gosub
+*/
+
+static int function_gosub(struct rpt *myrpt, char *param, char *digitbuf, int command_source, struct rpt_link *mylink)
+{
+
+       const char *val;
+       int     i;
+       struct ast_channel *mychannel;
+
+       if ((!myrpt->remote) && (!myrpt->enable))
+               return DC_ERROR;
+
+       if (debug) 
+               ast_log(LOG_DEBUG, "@@@@ gosub param = %s, digitbuf = %s\n", (param)? param : "(null)", digitbuf);
+       
+       mychannel = myrpt->remchannel;
+
+       if (ast_strlen_zero(digitbuf)) /* needs 1 digit */
+               return DC_INDETERMINATE;
+                       
+       for (i = 0; i < digitbuf[i]; i++) {
+               if ((digitbuf[i] < '0') || (digitbuf[i] > '9'))
+                       return DC_ERROR;
+       }
+   
+       if (*digitbuf == '0')
+               val = myrpt->p.startupgosub;
+       else
+               val = ast_variable_retrieve(myrpt->cfg, myrpt->p.gosub, digitbuf);
+       /* param was 1 for local buf */
+       if (!val) {
+               rpt_telemetry(myrpt, GOSUB_NOTFOUND, NULL);
+               return DC_COMPLETE;
+       }                       
+       rpt_mutex_lock(&myrpt->lock);
+       if ((sizeof(myrpt->gosubbuf) - strlen(myrpt->gosubbuf)) < strlen(val)) {
+               rpt_mutex_unlock(&myrpt->lock);
+               rpt_telemetry(myrpt, GOSUB_BUSY, NULL);
+               return DC_ERROR;
+       }
+       myrpt->gosubtimer = GOSUBTIME;
+       strncat(myrpt->gosubbuf, val, sizeof(myrpt->gosubbuf) - 1);
+       rpt_mutex_unlock(&myrpt->lock);
+       return DC_COMPLETE;     
+}
+
+/*
 * COP - Control operator
 */
 
@@ -5798,6 +5878,9 @@ static void *rpt(void *this)
        if (myrpt->p.startupmacro) {
                snprintf(myrpt->macrobuf, sizeof(myrpt->macrobuf), "PPPP%s", myrpt->p.startupmacro);
        }
+       if (myrpt->p.startupgosub) {
+               snprintf(myrpt->gosubbuf, sizeof(myrpt->gosubbuf), "PPPP%s", myrpt->p.startupgosub);
+       }
        rpt_mutex_unlock(&myrpt->lock);
        val = 0;
        ast_channel_setoption(myrpt->rxchannel, AST_OPTION_TONE_VERIFY, &val, sizeof(char), 0);
@@ -6228,6 +6311,11 @@ static void *rpt(void *this)
                        myrpt->macrotimer -= elap;
                if (myrpt->macrotimer < 0)
                        myrpt->macrotimer = 0;
+               /* do gosub timers */
+               if (myrpt->gosubtimer)
+                       myrpt->gosubtimer -= elap;
+               if (myrpt->gosubtimer < 0)
+                       myrpt->gosubtimer = 0;
                /* Execute scheduler appx. every 2 tenths of a second */
                if (myrpt->skedtimer <= 0) {
                        myrpt->skedtimer = 200;
@@ -6248,6 +6336,16 @@ static void *rpt(void *this)
                        local_dtmf_helper(myrpt, c);
                } else
                        rpt_mutex_unlock(&myrpt->lock);
+               c = myrpt->gosubbuf[0];
+               if (c && (!myrpt->gosubtimer)) {
+                       myrpt->gosubtimer = GOSUBTIME;
+                       memmove(myrpt->gosubbuf, myrpt->gosubbuf + 1, sizeof(myrpt->gosubbuf) - 1);
+                       if ((c == 'p') || (c == 'P'))
+                               myrpt->gosubtimer = GOSUBPTIME;
+                       rpt_mutex_unlock(&myrpt->lock);
+                       local_dtmf_helper(myrpt, c);
+               } else
+                       rpt_mutex_unlock(&myrpt->lock);
                if (who == myrpt->rxchannel) { /* if it was a read from rx */
                        f = ast_read(myrpt->rxchannel);
                        if (!f) {
@@ -7072,6 +7170,10 @@ static int rpt_exec(struct ast_channel *chan, void *data)
                myrpt->remchannel = chan; /* Save copy of channel */
                snprintf(myrpt->macrobuf, sizeof(myrpt->macrobuf), "PPPP%s", myrpt->p.startupmacro);
        }
+       if (myrpt->p.startupgosub) {
+               myrpt->remchannel = chan; /* Save copy of channel */
+               snprintf(myrpt->gosubbuf, sizeof(myrpt->gosubbuf), "PPPP%s", myrpt->p.startupgosub);
+       }
        myrpt->reload = 0;
        rpt_mutex_unlock(&myrpt->lock);
        setrem(myrpt); 
@@ -7123,6 +7225,10 @@ static int rpt_exec(struct ast_channel *chan, void *data)
                        myrpt->macrotimer -= elap;
                if (myrpt->macrotimer < 0)
                        myrpt->macrotimer = 0;
+               if (myrpt->gosubtimer)
+                       myrpt->gosubtimer -= elap;
+               if (myrpt->gosubtimer < 0)
+                       myrpt->gosubtimer = 0;
                rpt_mutex_unlock(&myrpt->lock);
                if (!ms)
                        continue;
@@ -7244,6 +7350,17 @@ static int rpt_exec(struct ast_channel *chan, void *data)
                                if (handle_remote_dtmf_digit(myrpt, c, &keyed, 0) == -1)
                                        break;
                                continue;
+                       }
+                       c = myrpt->gosubbuf[0];
+                       if (c && (!myrpt->gosubtimer)) {
+                               myrpt->gosubtimer = GOSUBTIME;
+                               memmove(myrpt->gosubbuf, myrpt->gosubbuf + 1, sizeof(myrpt->gosubbuf) - 1);
+                               if ((c == 'p') || (c == 'P'))
+                                       myrpt->gosubtimer = GOSUBPTIME;
+                               rpt_mutex_unlock(&myrpt->lock);
+                               if (handle_remote_dtmf_digit(myrpt, c, &keyed, 0) == -1)
+                                       break;
+                               continue;
                        } 
                        rpt_mutex_unlock(&myrpt->lock);
                        continue;