diff options
author | russell <russell@f38db490-d61c-443f-a65b-d21fe96a405b> | 2008-01-19 00:19:29 +0000 |
---|---|---|
committer | russell <russell@f38db490-d61c-443f-a65b-d21fe96a405b> | 2008-01-19 00:19:29 +0000 |
commit | f8247040e6231c4b3b5099ea3a526348b7941566 (patch) | |
tree | 0cc92ad6ebf6ae49a62f6e7ef8ec819121d63630 /trunk/apps/app_dictate.c | |
parent | d88e56c61ce2042544c1a8a71c93b69ab2e6ffba (diff) |
Creating tag for the release of asterisk-1.6.0-beta1v1.6.0-beta1
git-svn-id: http://svn.digium.com/svn/asterisk/tags/1.6.0-beta1@99163 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'trunk/apps/app_dictate.c')
-rw-r--r-- | trunk/apps/app_dictate.c | 338 |
1 files changed, 338 insertions, 0 deletions
diff --git a/trunk/apps/app_dictate.c b/trunk/apps/app_dictate.c new file mode 100644 index 000000000..58d61116a --- /dev/null +++ b/trunk/apps/app_dictate.c @@ -0,0 +1,338 @@ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 2005, Anthony Minessale II + * + * Anthony Minessale II <anthmct@yahoo.com> + * + * Donated by Sangoma Technologies <http://www.samgoma.com> + * + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2. See the LICENSE file + * at the top of the source tree. + */ + +/*! \file + * + * \brief Virtual Dictation Machine Application For Asterisk + * + * \author Anthony Minessale II <anthmct@yahoo.com> + * + * \ingroup applications + */ + +#include "asterisk.h" + +ASTERISK_FILE_VERSION(__FILE__, "$Revision$") + +#include <sys/stat.h> + +#include "asterisk/paths.h" /* use ast_config_AST_SPOOL_DIR */ +#include "asterisk/file.h" +#include "asterisk/pbx.h" +#include "asterisk/module.h" +#include "asterisk/say.h" +#include "asterisk/app.h" + +static char *app = "Dictate"; +static char *synopsis = "Virtual Dictation Machine"; +static char *desc = " Dictate([<base_dir>[,<filename>]])\n" +"Start dictation machine using optional base dir for files.\n"; + + +typedef enum { + DFLAG_RECORD = (1 << 0), + DFLAG_PLAY = (1 << 1), + DFLAG_TRUNC = (1 << 2), + DFLAG_PAUSE = (1 << 3), +} dflags; + +typedef enum { + DMODE_INIT, + DMODE_RECORD, + DMODE_PLAY +} dmodes; + +#define ast_toggle_flag(it,flag) if(ast_test_flag(it, flag)) ast_clear_flag(it, flag); else ast_set_flag(it, flag) + +static int play_and_wait(struct ast_channel *chan, char *file, char *digits) +{ + int res = -1; + if (!ast_streamfile(chan, file, chan->language)) { + res = ast_waitstream(chan, digits); + } + return res; +} + +static int dictate_exec(struct ast_channel *chan, void *data) +{ + char *path = NULL, filein[256], *filename = ""; + char *parse; + AST_DECLARE_APP_ARGS(args, + AST_APP_ARG(base); + AST_APP_ARG(filename); + ); + char dftbase[256]; + char *base; + struct ast_flags flags = {0}; + struct ast_filestream *fs; + struct ast_frame *f = NULL; + int ffactor = 320 * 80, + res = 0, + done = 0, + oldr = 0, + lastop = 0, + samples = 0, + speed = 1, + digit = 0, + len = 0, + maxlen = 0, + mode = 0; + + snprintf(dftbase, sizeof(dftbase), "%s/dictate", ast_config_AST_SPOOL_DIR); + if (!ast_strlen_zero(data)) { + parse = ast_strdupa(data); + AST_STANDARD_APP_ARGS(args, parse); + } else + args.argc = 0; + + if (args.argc && !ast_strlen_zero(args.base)) { + base = args.base; + } else { + base = dftbase; + } + if (args.argc > 1 && args.filename) { + filename = args.filename; + } + oldr = chan->readformat; + if ((res = ast_set_read_format(chan, AST_FORMAT_SLINEAR)) < 0) { + ast_log(LOG_WARNING, "Unable to set to linear mode.\n"); + return -1; + } + + ast_answer(chan); + ast_safe_sleep(chan, 200); + for (res = 0; !res;) { + if (ast_strlen_zero(filename)) { + if (ast_app_getdata(chan, "dictate/enter_filename", filein, sizeof(filein), 0) || + ast_strlen_zero(filein)) { + res = -1; + break; + } + } else { + ast_copy_string(filein, filename, sizeof(filein)); + filename = ""; + } + ast_mkdir(base, 0755); + len = strlen(base) + strlen(filein) + 2; + if (!path || len > maxlen) { + path = alloca(len); + memset(path, 0, len); + maxlen = len; + } else { + memset(path, 0, maxlen); + } + + snprintf(path, len, "%s/%s", base, filein); + fs = ast_writefile(path, "raw", NULL, O_CREAT|O_APPEND, 0, AST_FILE_MODE); + mode = DMODE_PLAY; + memset(&flags, 0, sizeof(flags)); + ast_set_flag(&flags, DFLAG_PAUSE); + digit = play_and_wait(chan, "dictate/forhelp", AST_DIGIT_ANY); + done = 0; + speed = 1; + res = 0; + lastop = 0; + samples = 0; + while (!done && ((res = ast_waitfor(chan, -1)) > -1) && fs && (f = ast_read(chan))) { + if (digit) { + struct ast_frame fr = {AST_FRAME_DTMF, digit}; + ast_queue_frame(chan, &fr); + digit = 0; + } + if ((f->frametype == AST_FRAME_DTMF)) { + int got = 1; + switch(mode) { + case DMODE_PLAY: + switch(f->subclass) { + case '1': + ast_set_flag(&flags, DFLAG_PAUSE); + mode = DMODE_RECORD; + break; + case '2': + speed++; + if (speed > 4) { + speed = 1; + } + res = ast_say_number(chan, speed, AST_DIGIT_ANY, chan->language, NULL); + break; + case '7': + samples -= ffactor; + if(samples < 0) { + samples = 0; + } + ast_seekstream(fs, samples, SEEK_SET); + break; + case '8': + samples += ffactor; + ast_seekstream(fs, samples, SEEK_SET); + break; + + default: + got = 0; + } + break; + case DMODE_RECORD: + switch(f->subclass) { + case '1': + ast_set_flag(&flags, DFLAG_PAUSE); + mode = DMODE_PLAY; + break; + case '8': + ast_toggle_flag(&flags, DFLAG_TRUNC); + lastop = 0; + break; + default: + got = 0; + } + break; + default: + got = 0; + } + if (!got) { + switch(f->subclass) { + case '#': + done = 1; + continue; + break; + case '*': + ast_toggle_flag(&flags, DFLAG_PAUSE); + if (ast_test_flag(&flags, DFLAG_PAUSE)) { + digit = play_and_wait(chan, "dictate/pause", AST_DIGIT_ANY); + } else { + digit = play_and_wait(chan, mode == DMODE_PLAY ? "dictate/playback" : "dictate/record", AST_DIGIT_ANY); + } + break; + case '0': + ast_set_flag(&flags, DFLAG_PAUSE); + digit = play_and_wait(chan, "dictate/paused", AST_DIGIT_ANY); + switch(mode) { + case DMODE_PLAY: + digit = play_and_wait(chan, "dictate/play_help", AST_DIGIT_ANY); + break; + case DMODE_RECORD: + digit = play_and_wait(chan, "dictate/record_help", AST_DIGIT_ANY); + break; + } + if (digit == 0) { + digit = play_and_wait(chan, "dictate/both_help", AST_DIGIT_ANY); + } else if (digit < 0) { + done = 1; + break; + } + break; + } + } + + } else if (f->frametype == AST_FRAME_VOICE) { + switch(mode) { + struct ast_frame *fr; + int x; + case DMODE_PLAY: + if (lastop != DMODE_PLAY) { + if (ast_test_flag(&flags, DFLAG_PAUSE)) { + digit = play_and_wait(chan, "dictate/playback_mode", AST_DIGIT_ANY); + if (digit == 0) { + digit = play_and_wait(chan, "dictate/paused", AST_DIGIT_ANY); + } else if (digit < 0) { + break; + } + } + if (lastop != DFLAG_PLAY) { + lastop = DFLAG_PLAY; + ast_closestream(fs); + if (!(fs = ast_openstream(chan, path, chan->language))) + break; + ast_seekstream(fs, samples, SEEK_SET); + chan->stream = NULL; + } + lastop = DMODE_PLAY; + } + + if (!ast_test_flag(&flags, DFLAG_PAUSE)) { + for (x = 0; x < speed; x++) { + if ((fr = ast_readframe(fs))) { + ast_write(chan, fr); + samples += fr->samples; + ast_frfree(fr); + fr = NULL; + } else { + samples = 0; + ast_seekstream(fs, 0, SEEK_SET); + } + } + } + break; + case DMODE_RECORD: + if (lastop != DMODE_RECORD) { + int oflags = O_CREAT | O_WRONLY; + if (ast_test_flag(&flags, DFLAG_PAUSE)) { + digit = play_and_wait(chan, "dictate/record_mode", AST_DIGIT_ANY); + if (digit == 0) { + digit = play_and_wait(chan, "dictate/paused", AST_DIGIT_ANY); + } else if (digit < 0) { + break; + } + } + lastop = DMODE_RECORD; + ast_closestream(fs); + if ( ast_test_flag(&flags, DFLAG_TRUNC)) { + oflags |= O_TRUNC; + digit = play_and_wait(chan, "dictate/truncating_audio", AST_DIGIT_ANY); + } else { + oflags |= O_APPEND; + } + fs = ast_writefile(path, "raw", NULL, oflags, 0, AST_FILE_MODE); + if (ast_test_flag(&flags, DFLAG_TRUNC)) { + ast_seekstream(fs, 0, SEEK_SET); + ast_clear_flag(&flags, DFLAG_TRUNC); + } else { + ast_seekstream(fs, 0, SEEK_END); + } + } + if (!ast_test_flag(&flags, DFLAG_PAUSE)) { + res = ast_writestream(fs, f); + } + break; + } + + } + + ast_frfree(f); + } + } + if (oldr) { + ast_set_read_format(chan, oldr); + } + return 0; +} + +static int unload_module(void) +{ + int res; + res = ast_unregister_application(app); + return res; +} + +static int load_module(void) +{ + return ast_register_application(app, dictate_exec, synopsis, desc); +} + +AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Virtual Dictation Machine"); |