add app_dictate (bug #3893)
authorKevin P. Fleming <kpfleming@digium.com>
Wed, 4 May 2005 19:33:33 +0000 (19:33 +0000)
committerKevin P. Fleming <kpfleming@digium.com>
Wed, 4 May 2005 19:33:33 +0000 (19:33 +0000)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@5579 65c4cc65-6c06-0410-ace0-fbb531ad65f3

16 files changed:
Makefile
apps/Makefile
apps/app_dictate.c [new file with mode: 0755]
sounds.txt
sounds/dictate/both_help.gsm [new file with mode: 0755]
sounds/dictate/enter_filename.gsm [new file with mode: 0755]
sounds/dictate/forhelp.gsm [new file with mode: 0755]
sounds/dictate/pause.gsm [new file with mode: 0755]
sounds/dictate/paused.gsm [new file with mode: 0755]
sounds/dictate/play_help.gsm [new file with mode: 0755]
sounds/dictate/playback.gsm [new file with mode: 0755]
sounds/dictate/playback_mode.gsm [new file with mode: 0755]
sounds/dictate/record.gsm [new file with mode: 0755]
sounds/dictate/record_help.gsm [new file with mode: 0755]
sounds/dictate/record_mode.gsm [new file with mode: 0755]
sounds/dictate/truncating_audio.gsm [new file with mode: 0755]

index 56a5067..2d30559 100755 (executable)
--- a/Makefile
+++ b/Makefile
@@ -15,7 +15,6 @@
 
 # Create OPTIONS variable
 OPTIONS=
 
 # 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/
 # 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
                        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 \
        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)$(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
        mkdir -p $(DESTDIR)$(ASTSPOOLDIR)/system
        mkdir -p $(DESTDIR)$(ASTSPOOLDIR)/tmp
        mkdir -p $(DESTDIR)$(ASTSPOOLDIR)/meetme
index 5d86910..e1eb61f 100755 (executable)
@@ -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_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)
 
 ifneq (${OSARCH},Darwin)
 ifneq (${OSARCH},SunOS)
diff --git a/apps/app_dictate.c b/apps/app_dictate.c
new file mode 100755 (executable)
index 0000000..b88fbf2
--- /dev/null
@@ -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;
+}
+
index dd8946b..4250ce5 100755 (executable)
 
 %tt-weasels.gsm%Weasels have eaten our phone system
 
 
 %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
 ;digits directory  - File Name Sound File Script
 
 %minus.gsm%minus
diff --git a/sounds/dictate/both_help.gsm b/sounds/dictate/both_help.gsm
new file mode 100755 (executable)
index 0000000..6416c58
Binary files /dev/null and b/sounds/dictate/both_help.gsm differ
diff --git a/sounds/dictate/enter_filename.gsm b/sounds/dictate/enter_filename.gsm
new file mode 100755 (executable)
index 0000000..9de8237
Binary files /dev/null and b/sounds/dictate/enter_filename.gsm differ
diff --git a/sounds/dictate/forhelp.gsm b/sounds/dictate/forhelp.gsm
new file mode 100755 (executable)
index 0000000..3824a33
Binary files /dev/null and b/sounds/dictate/forhelp.gsm differ
diff --git a/sounds/dictate/pause.gsm b/sounds/dictate/pause.gsm
new file mode 100755 (executable)
index 0000000..55fb96f
Binary files /dev/null and b/sounds/dictate/pause.gsm differ
diff --git a/sounds/dictate/paused.gsm b/sounds/dictate/paused.gsm
new file mode 100755 (executable)
index 0000000..b48f394
Binary files /dev/null and b/sounds/dictate/paused.gsm differ
diff --git a/sounds/dictate/play_help.gsm b/sounds/dictate/play_help.gsm
new file mode 100755 (executable)
index 0000000..5f854ac
Binary files /dev/null and b/sounds/dictate/play_help.gsm differ
diff --git a/sounds/dictate/playback.gsm b/sounds/dictate/playback.gsm
new file mode 100755 (executable)
index 0000000..48c16c1
Binary files /dev/null and b/sounds/dictate/playback.gsm differ
diff --git a/sounds/dictate/playback_mode.gsm b/sounds/dictate/playback_mode.gsm
new file mode 100755 (executable)
index 0000000..98fd711
Binary files /dev/null and b/sounds/dictate/playback_mode.gsm differ
diff --git a/sounds/dictate/record.gsm b/sounds/dictate/record.gsm
new file mode 100755 (executable)
index 0000000..fe3cee8
Binary files /dev/null and b/sounds/dictate/record.gsm differ
diff --git a/sounds/dictate/record_help.gsm b/sounds/dictate/record_help.gsm
new file mode 100755 (executable)
index 0000000..daf49ba
Binary files /dev/null and b/sounds/dictate/record_help.gsm differ
diff --git a/sounds/dictate/record_mode.gsm b/sounds/dictate/record_mode.gsm
new file mode 100755 (executable)
index 0000000..52203a9
Binary files /dev/null and b/sounds/dictate/record_mode.gsm differ
diff --git a/sounds/dictate/truncating_audio.gsm b/sounds/dictate/truncating_audio.gsm
new file mode 100755 (executable)
index 0000000..90db786
Binary files /dev/null and b/sounds/dictate/truncating_audio.gsm differ