add app_dictate (bug #3893)

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@5579 65c4cc65-6c06-0410-ace0-fbb531ad65f3
1.2-netsec
Kevin P. Fleming 20 years ago
parent 0575c11d72
commit 358238b170

@ -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

@ -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)

@ -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;
}

@ -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

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.
Loading…
Cancel
Save