Index: file.c =================================================================== RCS file: /usr/cvsroot/asterisk/file.c,v retrieving revision 1.69 diff -u -r1.69 file.c --- file.c 6 Jun 2005 22:12:18 -0000 1.69 +++ file.c 30 Jun 2005 05:01:17 -0000 @@ -37,6 +37,7 @@ #include "asterisk/utils.h" #include "asterisk/lock.h" #include "asterisk/app.h" +#include "asterisk/pbx.h" struct ast_format { /* Name of format */ @@ -1123,6 +1124,67 @@ /* Write audio if appropriate */ if (audiofd > -1) write(audiofd, fr->data, fr->datalen); + } + /* Ignore */ + ast_frfree(fr); + } + ast_sched_runq(c->sched); + } + 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); Index: pbx.c =================================================================== RCS file: /usr/cvsroot/asterisk/pbx.c,v retrieving revision 1.256 diff -u -r1.256 pbx.c --- pbx.c 20 Jun 2005 23:37:01 -0000 1.256 +++ pbx.c 30 Jun 2005 05:01:26 -0000 @@ -71,10 +71,14 @@ #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) @@ -251,19 +255,23 @@ { "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, @@ -5530,11 +5538,12 @@ 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); @@ -5546,6 +5555,8 @@ 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"); } @@ -5554,6 +5565,9 @@ if (!lang) lang = chan->language; + if (!context) + context = chan->context; + if (options) { if (!strcasecmp(options, "skip")) flags.flags = BACKGROUND_SKIP; @@ -5584,7 +5598,15 @@ } 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); @@ -5594,7 +5616,14 @@ 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) Index: include/asterisk/file.h =================================================================== RCS file: /usr/cvsroot/asterisk/include/asterisk/file.h,v retrieving revision 1.24 diff -u -r1.24 file.h --- include/asterisk/file.h 5 Jun 2005 15:04:43 -0000 1.24 +++ include/asterisk/file.h 30 Jun 2005 05:01:28 -0000 @@ -124,6 +124,16 @@ */ 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