Mon Mar 20 08:25:36 2006

Asterisk developer's documentation


Main Page | Modules | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

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  * \ingroup applications
00026  */
00027 
00028 #include <stdlib.h>
00029 #include <stdio.h>
00030 #include <string.h>
00031 #include <unistd.h>
00032 #include <sys/stat.h>   /* for mkdir */
00033 
00034 #include "asterisk.h"
00035 
00036 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 7221 $")
00037 
00038 #include "asterisk/file.h"
00039 #include "asterisk/logger.h"
00040 #include "asterisk/channel.h"
00041 #include "asterisk/pbx.h"
00042 #include "asterisk/module.h"
00043 #include "asterisk/say.h"
00044 #include "asterisk/lock.h"
00045 #include "asterisk/app.h"
00046 
00047 static char *tdesc = "Virtual Dictation Machine";
00048 static char *app = "Dictate";
00049 static char *synopsis = "Virtual Dictation Machine";
00050 static char *desc = "  Dictate([<base_dir>])\n"
00051 "Start dictation machine using optional base dir for files.\n";
00052 
00053 
00054 STANDARD_LOCAL_USER;
00055 LOCAL_USER_DECL;
00056 
00057 typedef enum {
00058    DFLAG_RECORD = (1 << 0),
00059    DFLAG_PLAY = (1 << 1),
00060    DFLAG_TRUNC = (1 << 2),
00061    DFLAG_PAUSE = (1 << 3),
00062 } dflags;
00063 
00064 typedef enum {
00065    DMODE_INIT,
00066    DMODE_RECORD,
00067    DMODE_PLAY
00068 } dmodes;
00069 
00070 #define ast_toggle_flag(it,flag) if(ast_test_flag(it, flag)) ast_clear_flag(it, flag); else ast_set_flag(it, flag)
00071 
00072 static int play_and_wait(struct ast_channel *chan, char *file, char *digits) 
00073 {
00074    int res = -1;
00075    if (!ast_streamfile(chan, file, chan->language)) {
00076       res = ast_waitstream(chan, digits);
00077    }
00078    return res;
00079 }
00080 
00081 static int dictate_exec(struct ast_channel *chan, void *data)
00082 {
00083    char *mydata, *argv[2], *path = NULL, filein[256];
00084    char dftbase[256];
00085    char *base;
00086    struct ast_flags flags = {0};
00087    struct ast_filestream *fs;
00088    struct ast_frame *f = NULL;
00089    struct localuser *u;
00090    int ffactor = 320 * 80,
00091       res = 0,
00092       argc = 0,
00093       done = 0,
00094       oldr = 0,
00095       lastop = 0,
00096       samples = 0,
00097       speed = 1,
00098       digit = 0,
00099       len = 0,
00100       maxlen = 0,
00101       mode = 0;
00102       
00103    LOCAL_USER_ADD(u);
00104    
00105    snprintf(dftbase, sizeof(dftbase), "%s/dictate", ast_config_AST_SPOOL_DIR);
00106    if (!ast_strlen_zero(data) && (mydata = ast_strdupa(data))) {
00107       argc = ast_app_separate_args(mydata, '|', argv, sizeof(argv) / sizeof(argv[0]));
00108    }
00109    
00110    if (argc) {
00111       base = argv[0];
00112    } else {
00113       base = dftbase;
00114    }
00115 
00116    oldr = chan->readformat;
00117    if ((res = ast_set_read_format(chan, AST_FORMAT_SLINEAR)) < 0) {
00118       ast_log(LOG_WARNING, "Unable to set to linear mode.\n");
00119       LOCAL_USER_REMOVE(u);
00120       return -1;
00121    }
00122 
00123    ast_answer(chan);
00124    ast_safe_sleep(chan, 200);
00125    for(res = 0; !res;) {
00126       if (ast_app_getdata(chan, "dictate/enter_filename", filein, sizeof(filein), 0) || 
00127          ast_strlen_zero(filein)) {
00128          res = -1;
00129          break;
00130       }
00131       
00132       mkdir(base, 0755);
00133       len = strlen(base) + strlen(filein) + 2;
00134       if (!path || len > maxlen) {
00135          path = alloca(len);
00136          memset(path, 0, len);
00137          maxlen = len;
00138       } else {
00139          memset(path, 0, maxlen);
00140       }
00141 
00142       snprintf(path, len, "%s/%s", base, filein);
00143       fs = ast_writefile(path, "raw", NULL, O_CREAT|O_APPEND, 0, 0700);
00144       mode = DMODE_PLAY;
00145       memset(&flags, 0, sizeof(flags));
00146       ast_set_flag(&flags, DFLAG_PAUSE);
00147       digit = play_and_wait(chan, "dictate/forhelp", AST_DIGIT_ANY);
00148       done = 0;
00149       speed = 1;
00150       res = 0;
00151       lastop = 0;
00152       samples = 0;
00153       while (!done && ((res = ast_waitfor(chan, -1)) > -1) && fs && (f = ast_read(chan))) {
00154          if (digit) {
00155             struct ast_frame fr = {AST_FRAME_DTMF, digit};
00156             ast_queue_frame(chan, &fr);
00157             digit = 0;
00158          }
00159          if ((f->frametype == AST_FRAME_DTMF)) {
00160             int got = 1;
00161             switch(mode) {
00162             case DMODE_PLAY:
00163                switch(f->subclass) {
00164                case '1':
00165                   ast_set_flag(&flags, DFLAG_PAUSE);
00166                   mode = DMODE_RECORD;
00167                   break;
00168                case '2':
00169                   speed++;
00170                   if (speed > 4) {
00171                      speed = 1;
00172                   }
00173                   res = ast_say_number(chan, speed, AST_DIGIT_ANY, chan->language, (char *) NULL);
00174                   break;
00175                case '7':
00176                   samples -= ffactor;
00177                   if(samples < 0) {
00178                      samples = 0;
00179                   }
00180                   ast_seekstream(fs, samples, SEEK_SET);
00181                   break;
00182                case '8':
00183                   samples += ffactor;
00184                   ast_seekstream(fs, samples, SEEK_SET);
00185                   break;
00186                   
00187                default:
00188                   got = 0;
00189                }
00190                break;
00191             case DMODE_RECORD:
00192                switch(f->subclass) {
00193                case '1':
00194                   ast_set_flag(&flags, DFLAG_PAUSE);
00195                   mode = DMODE_PLAY;
00196                   break;
00197                case '8':
00198                   ast_toggle_flag(&flags, DFLAG_TRUNC);
00199                   lastop = 0;
00200                   break;
00201                default:
00202                   got = 0;
00203                }
00204                break;
00205             default:
00206                got = 0;
00207             }
00208             if (!got) {
00209                switch(f->subclass) {
00210                case '#':
00211                   done = 1;
00212                   continue;
00213                   break;
00214                case '*':
00215                   ast_toggle_flag(&flags, DFLAG_PAUSE);
00216                   if (ast_test_flag(&flags, DFLAG_PAUSE)) {
00217                      digit = play_and_wait(chan, "dictate/pause", AST_DIGIT_ANY);
00218                   } else {
00219                      digit = play_and_wait(chan, mode == DMODE_PLAY ? "dictate/playback" : "dictate/record", AST_DIGIT_ANY);
00220                   }
00221                   break;
00222                case '0':
00223                   ast_set_flag(&flags, DFLAG_PAUSE);
00224                   digit = play_and_wait(chan, "dictate/paused", AST_DIGIT_ANY);
00225                   switch(mode) {
00226                   case DMODE_PLAY:
00227                      digit = play_and_wait(chan, "dictate/play_help", AST_DIGIT_ANY);
00228                      break;
00229                   case DMODE_RECORD:
00230                      digit = play_and_wait(chan, "dictate/record_help", AST_DIGIT_ANY);
00231                      break;
00232                   }
00233                   if (digit == 0) {
00234                      digit = play_and_wait(chan, "dictate/both_help", AST_DIGIT_ANY);
00235                   } else if (digit < 0) {
00236                      done = 1;
00237                      break;
00238                   }
00239                   break;
00240                }
00241             }
00242             
00243          } else if (f->frametype == AST_FRAME_VOICE) {
00244             switch(mode) {
00245                struct ast_frame *fr;
00246                int x;
00247             case DMODE_PLAY:
00248                if (lastop != DMODE_PLAY) {
00249                   if (ast_test_flag(&flags, DFLAG_PAUSE)) {
00250                      digit = play_and_wait(chan, "dictate/playback_mode", AST_DIGIT_ANY);
00251                      if (digit == 0) {
00252                         digit = play_and_wait(chan, "dictate/paused", AST_DIGIT_ANY);
00253                      } else if (digit < 0) {
00254                         break;
00255                      }
00256                   }
00257                   if (lastop != DFLAG_PLAY) {
00258                      lastop = DFLAG_PLAY;
00259                      ast_closestream(fs);
00260                      fs = ast_openstream(chan, path, chan->language);
00261                      ast_seekstream(fs, samples, SEEK_SET);
00262                      chan->stream = NULL;
00263                   }
00264                   lastop = DMODE_PLAY;
00265                }
00266 
00267                if (!ast_test_flag(&flags, DFLAG_PAUSE)) {
00268                   for (x = 0; x < speed; x++) {
00269                      if ((fr = ast_readframe(fs))) {
00270                         ast_write(chan, fr);
00271                         samples += fr->samples;
00272                         ast_frfree(fr);
00273                         fr = NULL;
00274                      } else {
00275                         samples = 0;
00276                         ast_seekstream(fs, 0, SEEK_SET);
00277                      }
00278                   }
00279                }
00280                break;
00281             case DMODE_RECORD:
00282                if (lastop != DMODE_RECORD) {
00283                   int oflags = O_CREAT | O_WRONLY;
00284                   if (ast_test_flag(&flags, DFLAG_PAUSE)) {                
00285                      digit = play_and_wait(chan, "dictate/record_mode", AST_DIGIT_ANY);
00286                      if (digit == 0) {
00287                         digit = play_and_wait(chan, "dictate/paused", AST_DIGIT_ANY);
00288                      } else if (digit < 0) {
00289                         break;
00290                      }
00291                   }
00292                   lastop = DMODE_RECORD;
00293                   ast_closestream(fs);
00294                   if ( ast_test_flag(&flags, DFLAG_TRUNC)) {
00295                      oflags |= O_TRUNC;
00296                      digit = play_and_wait(chan, "dictate/truncating_audio", AST_DIGIT_ANY);
00297                   } else {
00298                      oflags |= O_APPEND;
00299                   }
00300                   fs = ast_writefile(path, "raw", NULL, oflags, 0, 0700);
00301                   if (ast_test_flag(&flags, DFLAG_TRUNC)) {
00302                      ast_seekstream(fs, 0, SEEK_SET);
00303                      ast_clear_flag(&flags, DFLAG_TRUNC);
00304                   } else {
00305                      ast_seekstream(fs, 0, SEEK_END);
00306                   }
00307                }
00308                if (!ast_test_flag(&flags, DFLAG_PAUSE)) {
00309                   res = ast_writestream(fs, f);
00310                }
00311                break;
00312             }
00313             
00314          }
00315 
00316          ast_frfree(f);
00317       }
00318    }
00319    if (oldr) {
00320       ast_set_read_format(chan, oldr);
00321    }
00322    LOCAL_USER_REMOVE(u);
00323    return res;
00324 }
00325 
00326 int unload_module(void)
00327 {
00328    int res;
00329 
00330    res = ast_unregister_application(app);
00331    
00332    STANDARD_HANGUP_LOCALUSERS;
00333    
00334    return res;
00335 }
00336 
00337 int load_module(void)
00338 {
00339    return ast_register_application(app, dictate_exec, synopsis, desc);
00340 }
00341 
00342 char *description(void)
00343 {
00344    return tdesc;
00345 }
00346 
00347 int usecount(void)
00348 {
00349    int res;
00350    STANDARD_USECOUNT(res);
00351    return res;
00352 }
00353 
00354 char *key()
00355 {
00356    return ASTERISK_GPL_KEY;
00357 }
00358 

Generated on Mon Mar 20 08:25:36 2006 for Asterisk - the Open Source PBX by  doxygen 1.3.9.1