diff options
author | kpfleming <kpfleming@f38db490-d61c-443f-a65b-d21fe96a405b> | 2005-05-04 19:33:33 +0000 |
---|---|---|
committer | kpfleming <kpfleming@f38db490-d61c-443f-a65b-d21fe96a405b> | 2005-05-04 19:33:33 +0000 |
commit | 3aea9a1dc72c50caece12b2a299f3a9a0dd6c639 (patch) | |
tree | eb8ab6fb7eeeaf7e9dfbc23e581a9a4d41ba16c4 | |
parent | cb019df918733bf9c839ca6fac8042f85941908f (diff) |
add app_dictate (bug #3893)
git-svn-id: http://svn.digium.com/svn/asterisk/trunk@5579 f38db490-d61c-443f-a65b-d21fe96a405b
-rwxr-xr-x | Makefile | 11 | ||||
-rwxr-xr-x | apps/Makefile | 3 | ||||
-rwxr-xr-x | apps/app_dictate.c | 335 | ||||
-rwxr-xr-x | sounds.txt | 28 | ||||
-rwxr-xr-x | sounds/dictate/both_help.gsm | bin | 0 -> 8415 bytes | |||
-rwxr-xr-x | sounds/dictate/enter_filename.gsm | bin | 0 -> 9339 bytes | |||
-rwxr-xr-x | sounds/dictate/forhelp.gsm | bin | 0 -> 2475 bytes | |||
-rwxr-xr-x | sounds/dictate/pause.gsm | bin | 0 -> 1122 bytes | |||
-rwxr-xr-x | sounds/dictate/paused.gsm | bin | 0 -> 1287 bytes | |||
-rwxr-xr-x | sounds/dictate/play_help.gsm | bin | 0 -> 14388 bytes | |||
-rwxr-xr-x | sounds/dictate/playback.gsm | bin | 0 -> 1386 bytes | |||
-rwxr-xr-x | sounds/dictate/playback_mode.gsm | bin | 0 -> 1848 bytes | |||
-rwxr-xr-x | sounds/dictate/record.gsm | bin | 0 -> 1386 bytes | |||
-rwxr-xr-x | sounds/dictate/record_help.gsm | bin | 0 -> 8646 bytes | |||
-rwxr-xr-x | sounds/dictate/record_mode.gsm | bin | 0 -> 1650 bytes | |||
-rwxr-xr-x | sounds/dictate/truncating_audio.gsm | bin | 0 -> 2508 bytes |
16 files changed, 375 insertions, 2 deletions
@@ -15,7 +15,6 @@ # Create OPTIONS variable OPTIONS= - # If cross compiling, define these to suit # CROSS_COMPILE=/opt/montavista/pro/devkit/arm/xscale_be/bin/xscale_be- # CROSS_COMPILE_BIN=/opt/montavista/pro/devkit/arm/xscale_be/bin/ @@ -411,6 +410,15 @@ datafiles: all exit 1; \ fi; \ done + mkdir -p $(DESTDIR)$(ASTVARLIBDIR)/sounds/dictate + for x in sounds/dictate/*.gsm; do \ + if $(GREP) -q "^%`basename $$x`%" sounds.txt; then \ + install -m 644 $$x $(DESTDIR)$(ASTVARLIBDIR)/sounds/dictate ; \ + else \ + echo "No description for $$x"; \ + exit 1; \ + fi; \ + done mkdir -p $(DESTDIR)$(ASTVARLIBDIR)/sounds/letters for x in sounds/letters/*.gsm; do \ if $(GREP) -q "^%`basename $$x`%" sounds.txt; then \ @@ -490,6 +498,7 @@ bininstall: all mkdir -p $(DESTDIR)$(ASTSBINDIR) mkdir -p $(DESTDIR)$(ASTVARRUNDIR) mkdir -p $(DESTDIR)$(ASTSPOOLDIR)/voicemail + mkdir -p $(DESTDIR)$(ASTSPOOLDIR)/dictate mkdir -p $(DESTDIR)$(ASTSPOOLDIR)/system mkdir -p $(DESTDIR)$(ASTSPOOLDIR)/tmp mkdir -p $(DESTDIR)$(ASTSPOOLDIR)/meetme diff --git a/apps/Makefile b/apps/Makefile index 5d8691088..e1eb61fb9 100755 --- a/apps/Makefile +++ b/apps/Makefile @@ -31,7 +31,8 @@ APPS=app_dial.so app_playback.so app_voicemail.so app_directory.so app_mp3.so\ app_talkdetect.so app_alarmreceiver.so app_userevent.so app_verbose.so \ app_test.so app_forkcdr.so app_math.so app_realtime.so \ app_dumpchan.so app_waitforsilence.so app_while.so app_setrdnis.so \ - app_md5.so app_readfile.so app_chanspy.so app_settransfercapability.so + app_md5.so app_readfile.so app_chanspy.so app_settransfercapability.so \ + app_dictate.so ifneq (${OSARCH},Darwin) ifneq (${OSARCH},SunOS) diff --git a/apps/app_dictate.c b/apps/app_dictate.c new file mode 100755 index 000000000..b88fbf2c3 --- /dev/null +++ b/apps/app_dictate.c @@ -0,0 +1,335 @@ +/* + * Asterisk -- A telephony toolkit for Linux. + * + * Virtual Dictation Machine Application For Asterisk + * + * Copyright (C) 2005, Anthony Minessale II + * + * Anthony Minessale II <anthmct@yahoo.com> + * + * Donated by Sangoma Technologies <http://www.samgoma.com> + * + * This program is free software, distributed under the terms of + * the GNU General Public License + */ + +#include <stdlib.h> +#include <unistd.h> +#include <string.h> + +#include "asterisk/file.h" +#include "asterisk/logger.h" +#include "asterisk/channel.h" +#include "asterisk/pbx.h" +#include "asterisk/module.h" +#include "asterisk/say.h" +#include "asterisk/lock.h" +#include "asterisk/app.h" +#include "astconf.h" + +static char *tdesc = "Virtual Dictation Machine"; +static char *app = "Dictate"; +static char *synopsis = "Virtual Dictation Machine"; +static char *desc = " Dictate([<base_dir>])\n" +"Start dictation machine using optional base dir for files.\n"; + + +STANDARD_LOCAL_USER; +LOCAL_USER_DECL; + +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 *mydata, *argv[2], *path = NULL, filein[256]; + char dftbase[256]; + char *base; + struct ast_flags flags = {0}; + struct ast_filestream *fs; + struct ast_frame *f = NULL; + struct localuser *u; + int ffactor = 320 * 80, + res = 0, + argc = 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 (data && !ast_strlen_zero(data) && (mydata = ast_strdupa(data))) { + argc = ast_separate_app_args(mydata, '|', argv, sizeof(argv) / sizeof(argv[0])); + } + + if (argc) { + base = argv[0]; + } else { + base = dftbase; + } + + 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; + } + + LOCAL_USER_ADD(u); + ast_answer(chan); + ast_safe_sleep(chan, 200); + for(res = 0; !res;) { + if (ast_app_getdata(chan, "dictate/enter_filename", filein, sizeof(filein), 0) || + ast_strlen_zero(filein)) { + res = -1; + break; + } + + 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, 0700); + 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, (char *) 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); + fs = ast_openstream(chan, path, chan->language); + 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, 0700); + 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); + } + LOCAL_USER_REMOVE(u); + return res; +} + +int unload_module(void) +{ + STANDARD_HANGUP_LOCALUSERS; + return ast_unregister_application(app); +} + +int load_module(void) +{ + return ast_register_application(app, dictate_exec, synopsis, desc); +} + +char *description(void) +{ + return tdesc; +} + +int usecount(void) +{ + int res; + STANDARD_USECOUNT(res); + return res; +} + +char *key() +{ + return ASTERISK_GPL_KEY; +} + diff --git a/sounds.txt b/sounds.txt index dd8946b67..4250ce5ee 100755 --- a/sounds.txt +++ b/sounds.txt @@ -268,6 +268,34 @@ %tt-weasels.gsm%Weasels have eaten our phone system +;dictate directory - app_dictate + +%both_help.gsm%press * to toggle pause, press # to enter a new dictation filename + +%enter_filename.gsm%Enter a numeric dictation filename followed by # or just # to exit + +%forhelp.gsm%press 0 for help + +%inithelp.gsm%1 to switch to playback mode + +%pause.gsm%pause + +%paused.gsm%paused + +%play_help.gsm%press 1 to switch to record mode, press 2 to toggle fast playback, press 7 to jump backwards, press 8 to jump forwards + +%playback.gsm%playback + +%playback_mode.gsm%playback mode + +%record.gsm%record + +%record_help.gsm%press 1 to switch to playback mode, press 8 to truncate the file and start over + +%record_mode.gsm%record mode + +%truncating_audio.gsm%truncating audio + ;digits directory - File Name Sound File Script %minus.gsm%minus diff --git a/sounds/dictate/both_help.gsm b/sounds/dictate/both_help.gsm Binary files differnew file mode 100755 index 000000000..6416c5855 --- /dev/null +++ b/sounds/dictate/both_help.gsm diff --git a/sounds/dictate/enter_filename.gsm b/sounds/dictate/enter_filename.gsm Binary files differnew file mode 100755 index 000000000..9de823758 --- /dev/null +++ b/sounds/dictate/enter_filename.gsm diff --git a/sounds/dictate/forhelp.gsm b/sounds/dictate/forhelp.gsm Binary files differnew file mode 100755 index 000000000..3824a3308 --- /dev/null +++ b/sounds/dictate/forhelp.gsm diff --git a/sounds/dictate/pause.gsm b/sounds/dictate/pause.gsm Binary files differnew file mode 100755 index 000000000..55fb96f85 --- /dev/null +++ b/sounds/dictate/pause.gsm diff --git a/sounds/dictate/paused.gsm b/sounds/dictate/paused.gsm Binary files differnew file mode 100755 index 000000000..b48f394b1 --- /dev/null +++ b/sounds/dictate/paused.gsm diff --git a/sounds/dictate/play_help.gsm b/sounds/dictate/play_help.gsm Binary files differnew file mode 100755 index 000000000..5f854ac98 --- /dev/null +++ b/sounds/dictate/play_help.gsm diff --git a/sounds/dictate/playback.gsm b/sounds/dictate/playback.gsm Binary files differnew file mode 100755 index 000000000..48c16c186 --- /dev/null +++ b/sounds/dictate/playback.gsm diff --git a/sounds/dictate/playback_mode.gsm b/sounds/dictate/playback_mode.gsm Binary files differnew file mode 100755 index 000000000..98fd711fc --- /dev/null +++ b/sounds/dictate/playback_mode.gsm diff --git a/sounds/dictate/record.gsm b/sounds/dictate/record.gsm Binary files differnew file mode 100755 index 000000000..fe3cee8c6 --- /dev/null +++ b/sounds/dictate/record.gsm diff --git a/sounds/dictate/record_help.gsm b/sounds/dictate/record_help.gsm Binary files differnew file mode 100755 index 000000000..daf49ba5c --- /dev/null +++ b/sounds/dictate/record_help.gsm diff --git a/sounds/dictate/record_mode.gsm b/sounds/dictate/record_mode.gsm Binary files differnew file mode 100755 index 000000000..52203a951 --- /dev/null +++ b/sounds/dictate/record_mode.gsm diff --git a/sounds/dictate/truncating_audio.gsm b/sounds/dictate/truncating_audio.gsm Binary files differnew file mode 100755 index 000000000..90db78679 --- /dev/null +++ b/sounds/dictate/truncating_audio.gsm |