Fri Jun 19 12:09:24 2009

Asterisk developer's documentation


app_dictate.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 2005, Anthony Minessale II
00005  *
00006  * Anthony Minessale II <anthmct@yahoo.com>
00007  *
00008  * Donated by Sangoma Technologies <http://www.samgoma.com>
00009  *
00010  * See http://www.asterisk.org for more information about
00011  * the Asterisk project. Please do not directly contact
00012  * any of the maintainers of this project for assistance;
00013  * the project provides a web site, mailing lists and IRC
00014  * channels for your use.
00015  *
00016  * This program is free software, distributed under the terms of
00017  * the GNU General Public License Version 2. See the LICENSE file
00018  * at the top of the source tree.
00019  */
00020 
00021 /*! \file
00022  *
00023  * \brief Virtual Dictation Machine Application For Asterisk
00024  *
00025  * \author Anthony Minessale II <anthmct@yahoo.com>
00026  *
00027  * \ingroup applications
00028  */
00029 
00030 #include "asterisk.h"
00031 
00032 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 174947 $")
00033 
00034 #include <sys/stat.h>
00035 
00036 #include "asterisk/paths.h" /* use ast_config_AST_SPOOL_DIR */
00037 #include "asterisk/file.h"
00038 #include "asterisk/pbx.h"
00039 #include "asterisk/module.h"
00040 #include "asterisk/say.h"
00041 #include "asterisk/app.h"
00042 
00043 static char *app = "Dictate";
00044 static char *synopsis = "Virtual Dictation Machine";
00045 static char *desc = "  Dictate([<base_dir>[,<filename>]])\n"
00046 "Start dictation machine using optional base dir for files.\n";
00047 
00048 
00049 typedef enum {
00050    DFLAG_RECORD = (1 << 0),
00051    DFLAG_PLAY = (1 << 1),
00052    DFLAG_TRUNC = (1 << 2),
00053    DFLAG_PAUSE = (1 << 3),
00054 } dflags;
00055 
00056 typedef enum {
00057    DMODE_INIT,
00058    DMODE_RECORD,
00059    DMODE_PLAY
00060 } dmodes;
00061 
00062 #define ast_toggle_flag(it,flag) if(ast_test_flag(it, flag)) ast_clear_flag(it, flag); else ast_set_flag(it, flag)
00063 
00064 static int play_and_wait(struct ast_channel *chan, char *file, char *digits)
00065 {
00066    int res = -1;
00067    if (!ast_streamfile(chan, file, chan->language)) {
00068       res = ast_waitstream(chan, digits);
00069    }
00070    return res;
00071 }
00072 
00073 static int dictate_exec(struct ast_channel *chan, void *data)
00074 {
00075    char *path = NULL, filein[256], *filename = "";
00076    char *parse;
00077    AST_DECLARE_APP_ARGS(args,
00078       AST_APP_ARG(base);
00079       AST_APP_ARG(filename);
00080    );
00081    char dftbase[256];
00082    char *base;
00083    struct ast_flags flags = {0};
00084    struct ast_filestream *fs;
00085    struct ast_frame *f = NULL;
00086    int ffactor = 320 * 80,
00087       res = 0,
00088       done = 0,
00089       oldr = 0,
00090       lastop = 0,
00091       samples = 0,
00092       speed = 1,
00093       digit = 0,
00094       len = 0,
00095       maxlen = 0,
00096       mode = 0;
00097 
00098    snprintf(dftbase, sizeof(dftbase), "%s/dictate", ast_config_AST_SPOOL_DIR);
00099    if (!ast_strlen_zero(data)) {
00100       parse = ast_strdupa(data);
00101       AST_STANDARD_APP_ARGS(args, parse);
00102    } else
00103       args.argc = 0;
00104 
00105    if (args.argc && !ast_strlen_zero(args.base)) {
00106       base = args.base;
00107    } else {
00108       base = dftbase;
00109    }
00110    if (args.argc > 1 && args.filename) {
00111       filename = args.filename;
00112    }
00113    oldr = chan->readformat;
00114    if ((res = ast_set_read_format(chan, AST_FORMAT_SLINEAR)) < 0) {
00115       ast_log(LOG_WARNING, "Unable to set to linear mode.\n");
00116       return -1;
00117    }
00118 
00119    if (chan->_state != AST_STATE_UP) {
00120       ast_answer(chan);
00121    }
00122    ast_safe_sleep(chan, 200);
00123    for (res = 0; !res;) {
00124       if (ast_strlen_zero(filename)) {
00125          if (ast_app_getdata(chan, "dictate/enter_filename", filein, sizeof(filein), 0) ||
00126             ast_strlen_zero(filein)) {
00127             res = -1;
00128             break;
00129          }
00130       } else {
00131          ast_copy_string(filein, filename, sizeof(filein));
00132          filename = "";
00133       }
00134       ast_mkdir(base, 0755);
00135       len = strlen(base) + strlen(filein) + 2;
00136       if (!path || len > maxlen) {
00137          path = alloca(len);
00138          memset(path, 0, len);
00139          maxlen = len;
00140       } else {
00141          memset(path, 0, maxlen);
00142       }
00143 
00144       snprintf(path, len, "%s/%s", base, filein);
00145       fs = ast_writefile(path, "raw", NULL, O_CREAT|O_APPEND, 0, AST_FILE_MODE);
00146       mode = DMODE_PLAY;
00147       memset(&flags, 0, sizeof(flags));
00148       ast_set_flag(&flags, DFLAG_PAUSE);
00149       digit = play_and_wait(chan, "dictate/forhelp", AST_DIGIT_ANY);
00150       done = 0;
00151       speed = 1;
00152       res = 0;
00153       lastop = 0;
00154       samples = 0;
00155       while (!done && ((res = ast_waitfor(chan, -1)) > -1) && fs && (f = ast_read(chan))) {
00156          if (digit) {
00157             struct ast_frame fr = {AST_FRAME_DTMF, digit};
00158             ast_queue_frame(chan, &fr);
00159             digit = 0;
00160          }
00161          if ((f->frametype == AST_FRAME_DTMF)) {
00162             int got = 1;
00163             switch(mode) {
00164             case DMODE_PLAY:
00165                switch(f->subclass) {
00166                case '1':
00167                   ast_set_flag(&flags, DFLAG_PAUSE);
00168                   mode = DMODE_RECORD;
00169                   break;
00170                case '2':
00171                   speed++;
00172                   if (speed > 4) {
00173                      speed = 1;
00174                   }
00175                   res = ast_say_number(chan, speed, AST_DIGIT_ANY, chan->language, NULL);
00176                   break;
00177                case '7':
00178                   samples -= ffactor;
00179                   if(samples < 0) {
00180                      samples = 0;
00181                   }
00182                   ast_seekstream(fs, samples, SEEK_SET);
00183                   break;
00184                case '8':
00185                   samples += ffactor;
00186                   ast_seekstream(fs, samples, SEEK_SET);
00187                   break;
00188                   
00189                default:
00190                   got = 0;
00191                }
00192                break;
00193             case DMODE_RECORD:
00194                switch(f->subclass) {
00195                case '1':
00196                   ast_set_flag(&flags, DFLAG_PAUSE);
00197                   mode = DMODE_PLAY;
00198                   break;
00199                case '8':
00200                   ast_toggle_flag(&flags, DFLAG_TRUNC);
00201                   lastop = 0;
00202                   break;
00203                default:
00204                   got = 0;
00205                }
00206                break;
00207             default:
00208                got = 0;
00209             }
00210             if (!got) {
00211                switch(f->subclass) {
00212                case '#':
00213                   done = 1;
00214                   continue;
00215                   break;
00216                case '*':
00217                   ast_toggle_flag(&flags, DFLAG_PAUSE);
00218                   if (ast_test_flag(&flags, DFLAG_PAUSE)) {
00219                      digit = play_and_wait(chan, "dictate/pause", AST_DIGIT_ANY);
00220                   } else {
00221                      digit = play_and_wait(chan, mode == DMODE_PLAY ? "dictate/playback" : "dictate/record", AST_DIGIT_ANY);
00222                   }
00223                   break;
00224                case '0':
00225                   ast_set_flag(&flags, DFLAG_PAUSE);
00226                   digit = play_and_wait(chan, "dictate/paused", AST_DIGIT_ANY);
00227                   switch(mode) {
00228                   case DMODE_PLAY:
00229                      digit = play_and_wait(chan, "dictate/play_help", AST_DIGIT_ANY);
00230                      break;
00231                   case DMODE_RECORD:
00232                      digit = play_and_wait(chan, "dictate/record_help", AST_DIGIT_ANY);
00233                      break;
00234                   }
00235                   if (digit == 0) {
00236                      digit = play_and_wait(chan, "dictate/both_help", AST_DIGIT_ANY);
00237                   } else if (digit < 0) {
00238                      done = 1;
00239                      break;
00240                   }
00241                   break;
00242                }
00243             }
00244             
00245          } else if (f->frametype == AST_FRAME_VOICE) {
00246             switch(mode) {
00247                struct ast_frame *fr;
00248                int x;
00249             case DMODE_PLAY:
00250                if (lastop != DMODE_PLAY) {
00251                   if (ast_test_flag(&flags, DFLAG_PAUSE)) {
00252                      digit = play_and_wait(chan, "dictate/playback_mode", AST_DIGIT_ANY);
00253                      if (digit == 0) {
00254                         digit = play_and_wait(chan, "dictate/paused", AST_DIGIT_ANY);
00255                      } else if (digit < 0) {
00256                         break;
00257                      }
00258                   }
00259                   if (lastop != DFLAG_PLAY) {
00260                      lastop = DFLAG_PLAY;
00261                      ast_closestream(fs);
00262                      if (!(fs = ast_openstream(chan, path, chan->language)))
00263                         break;
00264                      ast_seekstream(fs, samples, SEEK_SET);
00265                      chan->stream = NULL;
00266                   }
00267                   lastop = DMODE_PLAY;
00268                }
00269 
00270                if (!ast_test_flag(&flags, DFLAG_PAUSE)) {
00271                   for (x = 0; x < speed; x++) {
00272                      if ((fr = ast_readframe(fs))) {
00273                         ast_write(chan, fr);
00274                         samples += fr->samples;
00275                         ast_frfree(fr);
00276                         fr = NULL;
00277                      } else {
00278                         samples = 0;
00279                         ast_seekstream(fs, 0, SEEK_SET);
00280                      }
00281                   }
00282                }
00283                break;
00284             case DMODE_RECORD:
00285                if (lastop != DMODE_RECORD) {
00286                   int oflags = O_CREAT | O_WRONLY;
00287                   if (ast_test_flag(&flags, DFLAG_PAUSE)) {
00288                      digit = play_and_wait(chan, "dictate/record_mode", AST_DIGIT_ANY);
00289                      if (digit == 0) {
00290                         digit = play_and_wait(chan, "dictate/paused", AST_DIGIT_ANY);
00291                      } else if (digit < 0) {
00292                         break;
00293                      }
00294                   }
00295                   lastop = DMODE_RECORD;
00296                   ast_closestream(fs);
00297                   if ( ast_test_flag(&flags, DFLAG_TRUNC)) {
00298                      oflags |= O_TRUNC;
00299                      digit = play_and_wait(chan, "dictate/truncating_audio", AST_DIGIT_ANY);
00300                   } else {
00301                      oflags |= O_APPEND;
00302                   }
00303                   fs = ast_writefile(path, "raw", NULL, oflags, 0, AST_FILE_MODE);
00304                   if (ast_test_flag(&flags, DFLAG_TRUNC)) {
00305                      ast_seekstream(fs, 0, SEEK_SET);
00306                      ast_clear_flag(&flags, DFLAG_TRUNC);
00307                   } else {
00308                      ast_seekstream(fs, 0, SEEK_END);
00309                   }
00310                }
00311                if (!ast_test_flag(&flags, DFLAG_PAUSE)) {
00312                   res = ast_writestream(fs, f);
00313                }
00314                break;
00315             }
00316             
00317          }
00318 
00319          ast_frfree(f);
00320       }
00321    }
00322    if (oldr) {
00323       ast_set_read_format(chan, oldr);
00324    }
00325    return 0;
00326 }
00327 
00328 static int unload_module(void)
00329 {
00330    int res;
00331    res = ast_unregister_application(app);
00332    return res;
00333 }
00334 
00335 static int load_module(void)
00336 {
00337    return ast_register_application(app, dictate_exec, synopsis, desc);
00338 }
00339 
00340 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Virtual Dictation Machine");

Generated on Fri Jun 19 12:09:24 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7