Add pause one second W dial modifier.
authorRichard Mudgett <rmudgett@digium.com>
Fri, 28 Sep 2012 18:27:02 +0000 (18:27 +0000)
committerRichard Mudgett <rmudgett@digium.com>
Fri, 28 Sep 2012 18:27:02 +0000 (18:27 +0000)
* The following dialplan applications now recognize 'W' to pause sending
DTMF for one second in addition to the previously existing 'w' that paused
sending DTMF for half a second.  Dial, ExternalIVR, and SendDTMF.

* The chan_dahdi analog port dialing and deferred DTMF dialing for PRI now
distinguishes between 'w' and 'W'.  The 'w' pauses dialing for half a
second.  The 'W' pauses dialing for one second.

* Created dahdi_dial_str() in chan_dahdi that eliminated a lot of
duplicated dialing code and diagnostic messages for the channel driver.

(closes issue ASTERISK-20039)
Reported by: Jeremiah Gowdy
Patches:
      jgowdy-wait-6-22-2012.diff (license #5621) patch uploaded by Jeremiah Gowdy
      Expanded patch to add support in chan_dahdi.
Tested by: rmudgett

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@374030 65c4cc65-6c06-0410-ace0-fbb531ad65f3

UPGRADE.txt
apps/app_senddtmf.c
channels/chan_dahdi.c
channels/sig_analog.c
main/app.c

index 73e67ff..dd5ce7c 100644 (file)
@@ -32,6 +32,23 @@ Queue:
  - Queue logging for PAUSEALL/UNPAUSEALL now only occurs if the interface this is
    performed on is a member of at least one queue.
 
+Dial:
+ - Now recognizes 'W' to pause sending DTMF for one second in addition to
+   the previously existing 'w' that paused sending DTMF for half a second.
+
+ExternalIVR:
+ - Now recognizes 'W' to pause sending DTMF for one second in addition to
+   the previously existing 'w' that paused sending DTMF for half a second.
+
+SendDTMF:
+ - Now recognizes 'W' to pause sending DTMF for one second in addition to
+   the previously existing 'w' that paused sending DTMF for half a second.
+
+chan_dahdi:
+ - Analog port dialing and deferred DTMF dialing for PRI now distinguishes
+   between 'w' and 'W'.  The 'w' pauses dialing for half a second.  The 'W'
+   pauses dialing for one second.
+
 From 10 to 11:
 
 Voicemail:
index 7db9a3f..be70d7b 100644 (file)
@@ -47,7 +47,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
                <syntax>
                        <parameter name="digits" required="true">
                                <para>List of digits 0-9,*#,a-d,A-D to send also w for a half second pause,
-                               and f or F for a flash-hook if the channel supports
+                               W for a one second pause, and f or F for a flash-hook if the channel supports
                                flash-hook.</para>
                        </parameter>
                        <parameter name="timeout_ms" required="false">
index 8506b01..f669e2e 100644 (file)
@@ -1738,6 +1738,60 @@ static int analogsub_to_dahdisub(enum analog_sub analogsub)
        return index;
 }
 
+/*!
+ * \internal
+ * \brief Send a dial string to DAHDI.
+ * \since 12.0.0
+ *
+ * \param pvt DAHDI private pointer
+ * \param operation DAHDI dial operation to do to string
+ * \param dial_str Dial string to send
+ *
+ * \retval 0 on success.
+ * \retval non-zero on error.
+ */
+static int dahdi_dial_str(struct dahdi_pvt *pvt, int operation, const char *dial_str)
+{
+       int res;
+       int offset;
+       const char *pos;
+       struct dahdi_dialoperation zo = {
+               .op = operation,
+       };
+
+       /* Convert the W's to ww. */
+       pos = dial_str;
+       for (offset = 0; offset < sizeof(zo.dialstr) - 1; ++offset) {
+               if (!*pos) {
+                       break;
+               }
+               if (*pos == 'W') {
+                       /* Convert 'W' to "ww" */
+                       ++pos;
+                       if (offset >= sizeof(zo.dialstr) - 3) {
+                               /* No room to expand */
+                               break;
+                       }
+                       zo.dialstr[offset] = 'w';
+                       ++offset;
+                       zo.dialstr[offset] = 'w';
+                       continue;
+               }
+               zo.dialstr[offset] = *pos++;
+       }
+       /* The zo initialization has already terminated the dialstr. */
+
+       ast_debug(1, "Channel %d: Dial str '%s' expanded to '%s' sent to DAHDI_DIAL.\n",
+               pvt->channel, dial_str, zo.dialstr);
+       res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo);
+       if (res) {
+               ast_log(LOG_WARNING, "Channel %d: Couldn't dial '%s': %s\n",
+                       pvt->channel, dial_str, strerror(errno));
+       }
+
+       return res;
+}
+
 static enum analog_event dahdievent_to_analogevent(int event);
 static int bump_gains(struct dahdi_pvt *p);
 static int dahdi_setlinear(int dfd, int linear);
@@ -2792,19 +2846,13 @@ static void my_pri_ss7_open_media(void *p)
  */
 static void my_pri_dial_digits(void *p, const char *dial_string)
 {
-       struct dahdi_dialoperation zo = {
-               .op = DAHDI_DIAL_OP_APPEND,
-       };
+       char dial_str[DAHDI_MAX_DTMF_BUF];
        struct dahdi_pvt *pvt = p;
        int res;
 
-       snprintf(zo.dialstr, sizeof(zo.dialstr), "T%s", dial_string);
-       ast_debug(1, "Channel %d: Sending '%s' to DAHDI_DIAL.\n", pvt->channel, zo.dialstr);
-       res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo);
-       if (res) {
-               ast_log(LOG_WARNING, "Channel %d: Couldn't dial '%s': %s\n",
-                       pvt->channel, dial_string, strerror(errno));
-       } else {
+       snprintf(dial_str, sizeof(dial_str), "T%s", dial_string);
+       res = dahdi_dial_str(pvt, DAHDI_DIAL_OP_APPEND, dial_str);
+       if (!res) {
                pvt->dialing = 1;
        }
 }
@@ -3095,10 +3143,7 @@ static int my_start(void *pvt)
 
 static int my_dial_digits(void *pvt, enum analog_sub sub, struct analog_dialoperation *dop)
 {
-       int index = analogsub_to_dahdisub(sub);
-       int res;
        struct dahdi_pvt *p = pvt;
-       struct dahdi_dialoperation ddop;
 
        if (dop->op != ANALOG_DIAL_OP_REPLACE) {
                ast_log(LOG_ERROR, "Fix the dial_digits callback!\n");
@@ -3111,17 +3156,7 @@ static int my_dial_digits(void *pvt, enum analog_sub sub, struct analog_dialoper
                return -1;
        }
 
-       ddop.op = DAHDI_DIAL_OP_REPLACE;
-       ast_copy_string(ddop.dialstr, dop->dialstr, sizeof(ddop.dialstr));
-
-       ast_debug(1, "Channel %d: Sending '%s' to DAHDI_DIAL.\n", p->channel, ddop.dialstr);
-
-       res = ioctl(p->subs[index].dfd, DAHDI_DIAL, &ddop);
-       if (res == -1) {
-               ast_debug(1, "DAHDI_DIAL ioctl failed on %s: %s\n", ast_channel_name(p->owner), strerror(errno));
-       }
-
-       return res;
+       return dahdi_dial_str(p, DAHDI_DIAL_OP_REPLACE, dop->dialstr);
 }
 
 static void dahdi_train_ec(struct dahdi_pvt *p);
@@ -4635,18 +4670,12 @@ static int dahdi_digit_begin(struct ast_channel *chan, char digit)
                goto out;
 
        if (pvt->pulse || ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_SENDTONE, &dtmf)) {
-               struct dahdi_dialoperation zo = {
-                       .op = DAHDI_DIAL_OP_APPEND,
-               };
+               char dial_str[] = { 'T', digit, '\0' };
 
-               zo.dialstr[0] = 'T';
-               zo.dialstr[1] = digit;
-               zo.dialstr[2] = '\0';
-               if ((res = ioctl(pvt->subs[SUB_REAL].dfd, DAHDI_DIAL, &zo)))
-                       ast_log(LOG_WARNING, "Channel %s couldn't dial digit %c: %s\n",
-                               ast_channel_name(chan), digit, strerror(errno));
-               else
+               res = dahdi_dial_str(pvt, DAHDI_DIAL_OP_APPEND, dial_str);
+               if (!res) {
                        pvt->dialing = 1;
+               }
        } else {
                ast_debug(1, "Channel %s started VLDTMF digit '%c'\n",
                        ast_channel_name(chan), digit);
@@ -8196,7 +8225,7 @@ static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
                                dahdi_train_ec(p);
                                ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
                                p->dop.op = DAHDI_DIAL_OP_REPLACE;
-                               res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
+                               res = dahdi_dial_str(p, p->dop.op, p->dop.dialstr);
                                p->echobreak = 0;
                        } else {
                                p->dialing = 0;
@@ -8431,14 +8460,11 @@ static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
                                p->dop.dialstr[strlen(p->dop.dialstr)-2] = '\0';
                        } else
                                p->echobreak = 0;
-                       if (ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop)) {
-                               int saveerr = errno;
-
+                       if (dahdi_dial_str(p, p->dop.op, p->dop.dialstr)) {
                                x = DAHDI_ONHOOK;
                                ioctl(p->subs[SUB_REAL].dfd, DAHDI_HOOK, &x);
-                               ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
                                return NULL;
-                               }
+                       }
                        p->dialing = 1;
                        return &p->subs[idx].f;
                }
@@ -8470,9 +8496,8 @@ static struct ast_frame *dahdi_handle_event(struct ast_channel *ast)
                                        p->subs[idx].f.subclass.integer = 0;
                                } else if (!ast_strlen_zero(p->dop.dialstr)) {
                                        /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
-                                       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
-                                       if (res < 0) {
-                                               ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
+                                       res = dahdi_dial_str(p, p->dop.op, p->dop.dialstr);
+                                       if (res) {
                                                p->dop.dialstr[0] = '\0';
                                                return NULL;
                                        } else {
@@ -8843,9 +8868,8 @@ winkflashdone:
                case SIG_EMWINK:
                        /* FGD MF and EMWINK *Must* wait for wink */
                        if (!ast_strlen_zero(p->dop.dialstr)) {
-                               res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
-                               if (res < 0) {
-                                       ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
+                               res = dahdi_dial_str(p, p->dop.op, p->dop.dialstr);
+                               if (res) {
                                        p->dop.dialstr[0] = '\0';
                                        return NULL;
                                } else
@@ -8873,9 +8897,8 @@ winkflashdone:
                case SIG_SFWINK:
                case SIG_SF_FEATD:
                        if (!ast_strlen_zero(p->dop.dialstr)) {
-                               res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
-                               if (res < 0) {
-                                       ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
+                               res = dahdi_dial_str(p, p->dop.op, p->dop.dialstr);
+                               if (res) {
                                        p->dop.dialstr[0] = '\0';
                                        return NULL;
                                } else
@@ -9473,9 +9496,8 @@ static struct ast_frame *dahdi_read(struct ast_channel *ast)
                                                ast_dsp_set_features(p->dsp, p->dsp_features);
                                                ast_debug(1, "Got 10 samples of dialtone!\n");
                                                if (!ast_strlen_zero(p->dop.dialstr)) { /* Dial deferred digits */
-                                                       res = ioctl(p->subs[SUB_REAL].dfd, DAHDI_DIAL, &p->dop);
-                                                       if (res < 0) {
-                                                               ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d\n", p->channel);
+                                                       res = dahdi_dial_str(p, p->dop.op, p->dop.dialstr);
+                                                       if (res) {
                                                                p->dop.dialstr[0] = '\0';
                                                                ast_mutex_unlock(&p->lock);
                                                                ast_frfree(f);
index 79e8e7c..395f1a5 100644 (file)
@@ -1257,10 +1257,7 @@ int analog_call(struct analog_pvt *p, struct ast_channel *ast, const char *rdest
                analog_set_waitingfordt(p, ast);
                if (!res) {
                        if (analog_dial_digits(p, ANALOG_SUB_REAL, &p->dop)) {
-                               int saveerr = errno;
-
                                analog_on_hook(p);
-                               ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
                                return -1;
                        }
                } else {
@@ -2767,10 +2764,7 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
                                analog_train_echocanceller(p);
                                ast_copy_string(p->dop.dialstr, p->echorest, sizeof(p->dop.dialstr));
                                p->dop.op = ANALOG_DIAL_OP_REPLACE;
-                               if (analog_dial_digits(p, ANALOG_SUB_REAL, &p->dop)) {
-                                       int dial_err = errno;
-                                       ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(dial_err));
-                               }
+                               analog_dial_digits(p, ANALOG_SUB_REAL, &p->dop);
                                p->echobreak = 0;
                        } else {
                                analog_set_dialing(p, 0);
@@ -2963,9 +2957,7 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
                                p->echobreak = 0;
                        }
                        if (analog_dial_digits(p, ANALOG_SUB_REAL, &p->dop)) {
-                               int saveerr = errno;
                                analog_on_hook(p);
-                               ast_log(LOG_WARNING, "Dialing failed on channel %d: %s\n", p->channel, strerror(saveerr));
                                return NULL;
                        }
                        analog_set_dialing(p, 1);
@@ -2999,8 +2991,7 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
                                } else if (!ast_strlen_zero(p->dop.dialstr)) {
                                        /* nick@dccinc.com 4/3/03 - fxo should be able to do deferred dialing */
                                        res = analog_dial_digits(p, ANALOG_SUB_REAL, &p->dop);
-                                       if (res < 0) {
-                                               ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
+                                       if (res) {
                                                p->dop.dialstr[0] = '\0';
                                                return NULL;
                                        } else {
@@ -3409,8 +3400,7 @@ winkflashdone:
                        /* FGD MF and EMWINK *Must* wait for wink */
                        if (!ast_strlen_zero(p->dop.dialstr)) {
                                res = analog_dial_digits(p, ANALOG_SUB_REAL, &p->dop);
-                               if (res < 0) {
-                                       ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
+                               if (res) {
                                        p->dop.dialstr[0] = '\0';
                                        return NULL;
                                } else {
@@ -3441,8 +3431,7 @@ winkflashdone:
                case ANALOG_SIG_SF_FEATD:
                        if (!ast_strlen_zero(p->dop.dialstr)) {
                                res = analog_dial_digits(p, ANALOG_SUB_REAL, &p->dop);
-                               if (res < 0) {
-                                       ast_log(LOG_WARNING, "Unable to initiate dialing on trunk channel %d: %s\n", p->channel, strerror(errno));
+                               if (res) {
                                        p->dop.dialstr[0] = '\0';
                                        return NULL;
                                } else {
index 8f90ddf..875bed1 100644 (file)
@@ -757,6 +757,11 @@ int ast_dtmf_stream(struct ast_channel *chan, struct ast_channel *peer, const ch
                        if ((res = ast_safe_sleep(chan, 500))) {
                                break;
                        }
+               } else if (*ptr == 'W') {
+                       /* 'W' -- wait a second */
+                       if ((res = ast_safe_sleep(chan, 1000))) {
+                               break;
+                       }
                } else if (strchr("0123456789*#abcdfABCDF", *ptr)) {
                        if (*ptr == 'f' || *ptr == 'F') {
                                /* ignore return values if not supported by channel */