Mon May 14 04:43:24 2007

Asterisk developer's documentation


app_dictate.c File Reference

Virtual Dictation Machine Application For Asterisk. More...

#include "asterisk.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.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 dependency graph for app_dictate.c:

Go to the source code of this file.

Defines

#define ast_toggle_flag(it, flag)   if(ast_test_flag(it, flag)) ast_clear_flag(it, flag); else ast_set_flag(it, flag)

Enumerations

enum  dflags { DFLAG_RECORD = (1 << 0), DFLAG_PLAY = (1 << 1), DFLAG_TRUNC = (1 << 2), DFLAG_PAUSE = (1 << 3) }
enum  dmodes { DMODE_INIT, DMODE_RECORD, DMODE_PLAY }

Functions

 AST_MODULE_INFO_STANDARD (ASTERISK_GPL_KEY,"Virtual Dictation Machine")
static int dictate_exec (struct ast_channel *chan, void *data)
static int load_module (void)
static int play_and_wait (struct ast_channel *chan, char *file, char *digits)
static int unload_module (void)

Variables

static char * app = "Dictate"
static char * desc
static char * synopsis = "Virtual Dictation Machine"


Detailed Description

Virtual Dictation Machine Application For Asterisk.

Author:
Anthony Minessale II <anthmct@yahoo.com>

Definition in file app_dictate.c.


Define Documentation

#define ast_toggle_flag ( it,
flag   )     if(ast_test_flag(it, flag)) ast_clear_flag(it, flag); else ast_set_flag(it, flag)

Definition at line 68 of file app_dictate.c.

Referenced by dictate_exec().


Enumeration Type Documentation

enum dflags

Enumerator:
DFLAG_RECORD 
DFLAG_PLAY 
DFLAG_TRUNC 
DFLAG_PAUSE 

Definition at line 55 of file app_dictate.c.

00055              {
00056    DFLAG_RECORD = (1 << 0),
00057    DFLAG_PLAY = (1 << 1),
00058    DFLAG_TRUNC = (1 << 2),
00059    DFLAG_PAUSE = (1 << 3),
00060 } dflags;

enum dmodes

Enumerator:
DMODE_INIT 
DMODE_RECORD 
DMODE_PLAY 

Definition at line 62 of file app_dictate.c.

00062              {
00063    DMODE_INIT,
00064    DMODE_RECORD,
00065    DMODE_PLAY
00066 } dmodes;


Function Documentation

AST_MODULE_INFO_STANDARD ( ASTERISK_GPL_KEY  ,
"Virtual Dictation Machine"   
)

static int dictate_exec ( struct ast_channel chan,
void *  data 
) [static]

Definition at line 79 of file app_dictate.c.

References ast_answer(), AST_APP_ARG, ast_app_getdata(), ast_clear_flag, ast_closestream(), ast_config_AST_SPOOL_DIR, AST_DECLARE_APP_ARGS, AST_DIGIT_ANY, AST_FORMAT_SLINEAR, AST_FRAME_DTMF, AST_FRAME_VOICE, ast_frfree(), ast_log(), ast_module_user_add, ast_module_user_remove, ast_openstream(), ast_queue_frame(), ast_read(), ast_readframe(), ast_safe_sleep(), ast_say_number(), ast_seekstream(), ast_set_flag, ast_set_read_format(), AST_STANDARD_APP_ARGS, ast_strdupa, ast_strlen_zero(), ast_test_flag, ast_toggle_flag, ast_waitfor(), ast_write(), ast_writefile(), ast_writestream(), ast_module_user::chan, DFLAG_PAUSE, DFLAG_PLAY, DFLAG_TRUNC, DMODE_PLAY, DMODE_RECORD, f, ast_flags::flags, len, LOG_WARNING, parse(), play_and_wait(), ast_channel::readformat, ast_frame::samples, and ast_channel::stream.

Referenced by load_module().

00080 {
00081    char *path = NULL, filein[256], *filename = "";
00082    char *parse;
00083    AST_DECLARE_APP_ARGS(args,
00084       AST_APP_ARG(base);
00085       AST_APP_ARG(filename);
00086    );
00087    char dftbase[256];
00088    char *base;
00089    struct ast_flags flags = {0};
00090    struct ast_filestream *fs;
00091    struct ast_frame *f = NULL;
00092    struct ast_module_user *u;
00093    int ffactor = 320 * 80,
00094       res = 0,
00095       done = 0,
00096       oldr = 0,
00097       lastop = 0,
00098       samples = 0,
00099       speed = 1,
00100       digit = 0,
00101       len = 0,
00102       maxlen = 0,
00103       mode = 0;
00104       
00105    u = ast_module_user_add(chan);
00106    
00107    snprintf(dftbase, sizeof(dftbase), "%s/dictate", ast_config_AST_SPOOL_DIR);
00108    if (!ast_strlen_zero(data)) {
00109       parse = ast_strdupa(data);
00110       AST_STANDARD_APP_ARGS(args, parse);
00111    } else
00112       args.argc = 0;
00113    
00114    if (args.argc && !ast_strlen_zero(args.base)) {
00115       base = args.base;
00116    } else {
00117       base = dftbase;
00118    }
00119    if (args.argc > 1 && args.filename) {
00120       filename = args.filename;
00121    } 
00122    oldr = chan->readformat;
00123    if ((res = ast_set_read_format(chan, AST_FORMAT_SLINEAR)) < 0) {
00124       ast_log(LOG_WARNING, "Unable to set to linear mode.\n");
00125       ast_module_user_remove(u);
00126       return -1;
00127    }
00128 
00129    ast_answer(chan);
00130    ast_safe_sleep(chan, 200);
00131    for (res = 0; !res;) {
00132       if (ast_strlen_zero(filename)) {
00133          if (ast_app_getdata(chan, "dictate/enter_filename", filein, sizeof(filein), 0) || 
00134             ast_strlen_zero(filein)) {
00135             res = -1;
00136             break;
00137          }
00138       } else {
00139          ast_copy_string(filein, filename, sizeof(filein));
00140          filename = "";
00141       }
00142       mkdir(base, 0755);
00143       len = strlen(base) + strlen(filein) + 2;
00144       if (!path || len > maxlen) {
00145          path = alloca(len);
00146          memset(path, 0, len);
00147          maxlen = len;
00148       } else {
00149          memset(path, 0, maxlen);
00150       }
00151 
00152       snprintf(path, len, "%s/%s", base, filein);
00153       fs = ast_writefile(path, "raw", NULL, O_CREAT|O_APPEND, 0, 0700);
00154       mode = DMODE_PLAY;
00155       memset(&flags, 0, sizeof(flags));
00156       ast_set_flag(&flags, DFLAG_PAUSE);
00157       digit = play_and_wait(chan, "dictate/forhelp", AST_DIGIT_ANY);
00158       done = 0;
00159       speed = 1;
00160       res = 0;
00161       lastop = 0;
00162       samples = 0;
00163       while (!done && ((res = ast_waitfor(chan, -1)) > -1) && fs && (f = ast_read(chan))) {
00164          if (digit) {
00165             struct ast_frame fr = {AST_FRAME_DTMF, digit};
00166             ast_queue_frame(chan, &fr);
00167             digit = 0;
00168          }
00169          if ((f->frametype == AST_FRAME_DTMF)) {
00170             int got = 1;
00171             switch(mode) {
00172             case DMODE_PLAY:
00173                switch(f->subclass) {
00174                case '1':
00175                   ast_set_flag(&flags, DFLAG_PAUSE);
00176                   mode = DMODE_RECORD;
00177                   break;
00178                case '2':
00179                   speed++;
00180                   if (speed > 4) {
00181                      speed = 1;
00182                   }
00183                   res = ast_say_number(chan, speed, AST_DIGIT_ANY, chan->language, (char *) NULL);
00184                   break;
00185                case '7':
00186                   samples -= ffactor;
00187                   if(samples < 0) {
00188                      samples = 0;
00189                   }
00190                   ast_seekstream(fs, samples, SEEK_SET);
00191                   break;
00192                case '8':
00193                   samples += ffactor;
00194                   ast_seekstream(fs, samples, SEEK_SET);
00195                   break;
00196                   
00197                default:
00198                   got = 0;
00199                }
00200                break;
00201             case DMODE_RECORD:
00202                switch(f->subclass) {
00203                case '1':
00204                   ast_set_flag(&flags, DFLAG_PAUSE);
00205                   mode = DMODE_PLAY;
00206                   break;
00207                case '8':
00208                   ast_toggle_flag(&flags, DFLAG_TRUNC);
00209                   lastop = 0;
00210                   break;
00211                default:
00212                   got = 0;
00213                }
00214                break;
00215             default:
00216                got = 0;
00217             }
00218             if (!got) {
00219                switch(f->subclass) {
00220                case '#':
00221                   done = 1;
00222                   continue;
00223                   break;
00224                case '*':
00225                   ast_toggle_flag(&flags, DFLAG_PAUSE);
00226                   if (ast_test_flag(&flags, DFLAG_PAUSE)) {
00227                      digit = play_and_wait(chan, "dictate/pause", AST_DIGIT_ANY);
00228                   } else {
00229                      digit = play_and_wait(chan, mode == DMODE_PLAY ? "dictate/playback" : "dictate/record", AST_DIGIT_ANY);
00230                   }
00231                   break;
00232                case '0':
00233                   ast_set_flag(&flags, DFLAG_PAUSE);
00234                   digit = play_and_wait(chan, "dictate/paused", AST_DIGIT_ANY);
00235                   switch(mode) {
00236                   case DMODE_PLAY:
00237                      digit = play_and_wait(chan, "dictate/play_help", AST_DIGIT_ANY);
00238                      break;
00239                   case DMODE_RECORD:
00240                      digit = play_and_wait(chan, "dictate/record_help", AST_DIGIT_ANY);
00241                      break;
00242                   }
00243                   if (digit == 0) {
00244                      digit = play_and_wait(chan, "dictate/both_help", AST_DIGIT_ANY);
00245                   } else if (digit < 0) {
00246                      done = 1;
00247                      break;
00248                   }
00249                   break;
00250                }
00251             }
00252             
00253          } else if (f->frametype == AST_FRAME_VOICE) {
00254             switch(mode) {
00255                struct ast_frame *fr;
00256                int x;
00257             case DMODE_PLAY:
00258                if (lastop != DMODE_PLAY) {
00259                   if (ast_test_flag(&flags, DFLAG_PAUSE)) {
00260                      digit = play_and_wait(chan, "dictate/playback_mode", AST_DIGIT_ANY);
00261                      if (digit == 0) {
00262                         digit = play_and_wait(chan, "dictate/paused", AST_DIGIT_ANY);
00263                      } else if (digit < 0) {
00264                         break;
00265                      }
00266                   }
00267                   if (lastop != DFLAG_PLAY) {
00268                      lastop = DFLAG_PLAY;
00269                      ast_closestream(fs);
00270                      if (!(fs = ast_openstream(chan, path, chan->language)))
00271                         break;
00272                      ast_seekstream(fs, samples, SEEK_SET);
00273                      chan->stream = NULL;
00274                   }
00275                   lastop = DMODE_PLAY;
00276                }
00277 
00278                if (!ast_test_flag(&flags, DFLAG_PAUSE)) {
00279                   for (x = 0; x < speed; x++) {
00280                      if ((fr = ast_readframe(fs))) {
00281                         ast_write(chan, fr);
00282                         samples += fr->samples;
00283                         ast_frfree(fr);
00284                         fr = NULL;
00285                      } else {
00286                         samples = 0;
00287                         ast_seekstream(fs, 0, SEEK_SET);
00288                      }
00289                   }
00290                }
00291                break;
00292             case DMODE_RECORD:
00293                if (lastop != DMODE_RECORD) {
00294                   int oflags = O_CREAT | O_WRONLY;
00295                   if (ast_test_flag(&flags, DFLAG_PAUSE)) {                
00296                      digit = play_and_wait(chan, "dictate/record_mode", AST_DIGIT_ANY);
00297                      if (digit == 0) {
00298                         digit = play_and_wait(chan, "dictate/paused", AST_DIGIT_ANY);
00299                      } else if (digit < 0) {
00300                         break;
00301                      }
00302                   }
00303                   lastop = DMODE_RECORD;
00304                   ast_closestream(fs);
00305                   if ( ast_test_flag(&flags, DFLAG_TRUNC)) {
00306                      oflags |= O_TRUNC;
00307                      digit = play_and_wait(chan, "dictate/truncating_audio", AST_DIGIT_ANY);
00308                   } else {
00309                      oflags |= O_APPEND;
00310                   }
00311                   fs = ast_writefile(path, "raw", NULL, oflags, 0, 0700);
00312                   if (ast_test_flag(&flags, DFLAG_TRUNC)) {
00313                      ast_seekstream(fs, 0, SEEK_SET);
00314                      ast_clear_flag(&flags, DFLAG_TRUNC);
00315                   } else {
00316                      ast_seekstream(fs, 0, SEEK_END);
00317                   }
00318                }
00319                if (!ast_test_flag(&flags, DFLAG_PAUSE)) {
00320                   res = ast_writestream(fs, f);
00321                }
00322                break;
00323             }
00324             
00325          }
00326 
00327          ast_frfree(f);
00328       }
00329    }
00330    if (oldr) {
00331       ast_set_read_format(chan, oldr);
00332    }
00333    ast_module_user_remove(u);
00334    return res;
00335 }

static int load_module ( void   )  [static]

Definition at line 344 of file app_dictate.c.

References ast_register_application(), and dictate_exec().

00345 {
00346    return ast_register_application(app, dictate_exec, synopsis, desc);
00347 }

static int play_and_wait ( struct ast_channel chan,
char *  file,
char *  digits 
) [static]

Definition at line 70 of file app_dictate.c.

References ast_streamfile(), and ast_waitstream().

Referenced by dictate_exec().

00071 {
00072    int res = -1;
00073    if (!ast_streamfile(chan, file, chan->language)) {
00074       res = ast_waitstream(chan, digits);
00075    }
00076    return res;
00077 }

static int unload_module ( void   )  [static]

Definition at line 337 of file app_dictate.c.

References ast_unregister_application().

00338 {
00339    int res;
00340    res = ast_unregister_application(app);
00341    return res;
00342 }


Variable Documentation

char* app = "Dictate" [static]

Definition at line 49 of file app_dictate.c.

char* desc [static]

Initial value:

 "  Dictate([<base_dir>[|<filename>]])\n"
"Start dictation machine using optional base dir for files.\n"

Definition at line 51 of file app_dictate.c.

char* synopsis = "Virtual Dictation Machine" [static]

Definition at line 50 of file app_dictate.c.


Generated on Mon May 14 04:43:25 2007 for Asterisk - the Open Source PBX by  doxygen 1.5.1