aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xfile.c62
-rwxr-xr-xinclude/asterisk/file.h10
-rwxr-xr-xpbx.c43
3 files changed, 108 insertions, 7 deletions
diff --git a/file.c b/file.c
index ce24fa0e8..9cb6d2393 100755
--- a/file.c
+++ b/file.c
@@ -37,6 +37,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/utils.h"
#include "asterisk/lock.h"
#include "asterisk/app.h"
+#include "asterisk/pbx.h"
struct ast_format {
/* Name of format */
@@ -1140,6 +1141,67 @@ int ast_waitstream_full(struct ast_channel *c, const char *breakon, int audiofd,
return (c->_softhangup ? -1 : 0);
}
+int ast_waitstream_exten(struct ast_channel *c, const char *context)
+{
+ /* Waitstream, with return in the case of a valid 1 digit extension */
+ /* in the current or specified context being pressed */
+ /* XXX Maybe I should just front-end ast_waitstream_full ? XXX */
+ int res;
+ struct ast_frame *fr;
+ char exten[AST_MAX_EXTENSION] = "";
+
+ if (!context) context = c->context;
+ while(c->stream) {
+ res = ast_sched_wait(c->sched);
+ if ((res < 0) && !c->timingfunc) {
+ ast_stopstream(c);
+ break;
+ }
+ if (res < 0)
+ res = 1000;
+ res = ast_waitfor(c, res);
+ if (res < 0) {
+ ast_log(LOG_WARNING, "Select failed (%s)\n", strerror(errno));
+ return res;
+ } else if (res > 0) {
+ fr = ast_read(c);
+ if (!fr) {
+#if 0
+ ast_log(LOG_DEBUG, "Got hung up\n");
+#endif
+ return -1;
+ }
+
+ switch(fr->frametype) {
+ case AST_FRAME_DTMF:
+ res = fr->subclass;
+ snprintf(exten, sizeof(exten), "%c", res);
+ if (ast_exists_extension(c, context, exten, 1, c->cid.cid_num)) {
+ ast_frfree(fr);
+ return res;
+ }
+ break;
+ case AST_FRAME_CONTROL:
+ switch(fr->subclass) {
+ case AST_CONTROL_HANGUP:
+ ast_frfree(fr);
+ return -1;
+ case AST_CONTROL_RINGING:
+ case AST_CONTROL_ANSWER:
+ /* Unimportant */
+ break;
+ default:
+ ast_log(LOG_WARNING, "Unexpected control subclass '%d'\n", fr->subclass);
+ }
+ }
+ /* Ignore */
+ ast_frfree(fr);
+ }
+ ast_sched_runq(c->sched);
+ }
+ return (c->_softhangup ? -1 : 0);
+}
+
static int show_file_formats(int fd, int argc, char *argv[])
{
#define FORMAT "%-10s %-10s %-20s\n"
diff --git a/include/asterisk/file.h b/include/asterisk/file.h
index 8b6104df8..7c4442f67 100755
--- a/include/asterisk/file.h
+++ b/include/asterisk/file.h
@@ -124,6 +124,16 @@ int ast_filecopy(const char *oldname, const char *newname, const char *fmt);
*/
int ast_waitstream(struct ast_channel *c, const char *breakon);
+/*! Waits for a stream to stop or digit matching a valid one digit exten to be pressed */
+/*!
+ * \param c channel to waitstram on
+ * \param context string of context to match digits to break upon
+ * Begins playback of a stream...
+ * Wait for a stream to stop or for any one of a valid extension digit to arrive, Returns 0
+ * if the stream finishes, the character if it was interrupted, and -1 on error
+ */
+int ast_waitstream_exten(struct ast_channel *c, const char *context);
+
/*! Same as waitstream but allows stream to be forwarded or rewound */
/*!
* \param c channel to waitstram on
diff --git a/pbx.c b/pbx.c
index d872bd233..423d1e492 100755
--- a/pbx.c
+++ b/pbx.c
@@ -72,10 +72,14 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#define BACKGROUND_SKIP (1 << 0)
#define BACKGROUND_NOANSWER (1 << 1)
+#define BACKGROUND_MATCHEXTEN (1 << 2)
+#define BACKGROUND_PLAYBACK (1 << 3)
AST_DECLARE_OPTIONS(background_opts,{
['s'] = { BACKGROUND_SKIP },
['n'] = { BACKGROUND_NOANSWER },
+ ['m'] = { BACKGROUND_MATCHEXTEN },
+ ['p'] = { BACKGROUND_PLAYBACK },
});
#define WAITEXTEN_MOH (1 << 0)
@@ -243,19 +247,23 @@ static struct pbx_builtin {
{ "BackGround", pbx_builtin_background,
"Play a file while awaiting extension",
- " Background(filename1[&filename2...][|options[|langoverride]]): Plays\n"
- "given files, while simultaneously waiting for the user to begin typing\n"
+ " Background(filename1[&filename2...][|options[|langoverride][|context]]):\n"
+ "Plays given files, while simultaneously waiting for the user to begin typing\n"
"an extension. The timeouts do not count until the last BackGround\n"
"application has ended. Options may also be included following a pipe \n"
"symbol. The 'langoverride' may be a language to use for playing the prompt\n"
- "which differs from the current language of the channel. Returns -1 if \n"
- "the channel was hung up, or if the file does not exist. Returns 0 otherwise.\n\n"
+ "which differs from the current language of the channel. The optional\n"
+ "'context' can be used to specify an optional context to exit into.\n"
+ "Returns -1 if thhe channel was hung up, or if the file does not exist./n"
+ "Returns 0 otherwise.\n\n"
" Options:\n"
" 's' - causes the playback of the message to be skipped\n"
" if the channel is not in the 'up' state (i.e. it\n"
" hasn't been answered yet.) If this happens, the\n"
" application will return immediately.\n"
" 'n' - don't answer the channel before playing the files\n"
+ " 'm' - only break if a digit hit matches a one digit\n"
+ " extension in the destination context\n"
},
{ "Busy", pbx_builtin_busy,
@@ -5440,11 +5448,12 @@ static int pbx_builtin_background(struct ast_channel *chan, void *data)
int res = 0;
int argc;
char *args;
- char *argv[3];
+ char *argv[4];
char *options = NULL;
char *filename = NULL;
char *front = NULL, *back = NULL;
char *lang = NULL;
+ char *context = NULL;
struct ast_flags flags = {0};
args = ast_strdupa(data);
@@ -5456,6 +5465,8 @@ static int pbx_builtin_background(struct ast_channel *chan, void *data)
options = argv[1];
if (argc > 2)
lang = argv[2];
+ if (argc > 3)
+ context = argv[3];
} else {
ast_log(LOG_WARNING, "Background requires an argument (filename)\n");
}
@@ -5464,6 +5475,9 @@ static int pbx_builtin_background(struct ast_channel *chan, void *data)
if (!lang)
lang = chan->language;
+ if (!context)
+ context = chan->context;
+
if (options) {
if (!strcasecmp(options, "skip"))
flags.flags = BACKGROUND_SKIP;
@@ -5494,7 +5508,15 @@ static int pbx_builtin_background(struct ast_channel *chan, void *data)
}
res = ast_streamfile(chan, front, lang);
if (!res) {
- res = ast_waitstream(chan, AST_DIGIT_ANY);
+ if (ast_test_flag(&flags, BACKGROUND_PLAYBACK)) {
+ res = ast_waitstream(chan, "");
+ } else {
+ if (ast_test_flag(&flags, BACKGROUND_MATCHEXTEN)) {
+ res = ast_waitstream_exten(chan, context);
+ } else {
+ res = ast_waitstream(chan, AST_DIGIT_ANY);
+ }
+ }
ast_stopstream(chan);
} else {
ast_log(LOG_WARNING, "ast_streamfile failed on %s for %s\n", chan->name, (char*)data);
@@ -5504,7 +5526,14 @@ static int pbx_builtin_background(struct ast_channel *chan, void *data)
front = back;
}
}
- return res;
+ if (context != chan->context && res) {
+ snprintf(chan->exten, sizeof(chan->exten), "%c", res);
+ ast_copy_string(chan->context, context, sizeof(chan->context));
+ chan->priority = 0;
+ return 0;
+ } else {
+ return res;
+ }
}
static int pbx_builtin_atimeout(struct ast_channel *chan, void *data)