Fri May 26 01:45:48 2006

Asterisk developer's documentation


app_dictate.c File Reference

Virtual Dictation Machine Application For Asterisk. More...

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include "asterisk.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

char * description (void)
 Provides a description of the module.
static int dictate_exec (struct ast_channel *chan, void *data)
char * key ()
 Returns the ASTERISK_GPL_KEY.
int load_module (void)
 Initialize the module.
static int play_and_wait (struct ast_channel *chan, char *file, char *digits)
int unload_module (void)
 Cleanup all module structures, sockets, etc.
int usecount (void)
 Provides a usecount.

Variables

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


Detailed Description

Virtual Dictation Machine Application For Asterisk.

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 70 of file app_dictate.c.


Enumeration Type Documentation

enum dflags
 

Enumerator:
DFLAG_RECORD 
DFLAG_PLAY 
DFLAG_TRUNC 
DFLAG_PAUSE 

Definition at line 57 of file app_dictate.c.

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

enum dmodes
 

Enumerator:
DMODE_INIT 
DMODE_RECORD 
DMODE_PLAY 

Definition at line 64 of file app_dictate.c.

00064              {
00065    DMODE_INIT,
00066    DMODE_RECORD,
00067    DMODE_PLAY
00068 } dmodes;


Function Documentation

char* description void   ) 
 

Provides a description of the module.

Returns:
a short description of your module

Definition at line 342 of file app_dictate.c.

00343 {
00344    return tdesc;
00345 }

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

Definition at line 81 of file app_dictate.c.

References ast_answer(), ast_app_getdata(), ast_app_separate_args(), ast_config_AST_SPOOL_DIR, AST_FORMAT_SLINEAR, ast_log(), ast_safe_sleep(), ast_set_read_format(), ast_strdupa, ast_strlen_zero(), localuser::chan, ast_flags::flags, LOCAL_USER_ADD, LOCAL_USER_REMOVE, LOG_WARNING, and ast_channel::readformat.

Referenced by load_module().

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 }

char* key void   ) 
 

Returns the ASTERISK_GPL_KEY.

This returns the ASTERISK_GPL_KEY, signifiying that you agree to the terms of the GPL stated in the ASTERISK_GPL_KEY. Your module will not load if it does not return the EXACT message:

 char *key(void) {
         return ASTERISK_GPL_KEY;
 }

Returns:
ASTERISK_GPL_KEY

Definition at line 354 of file app_dictate.c.

References ASTERISK_GPL_KEY.

00355 {
00356    return ASTERISK_GPL_KEY;
00357 }

int load_module void   ) 
 

Initialize the module.

Initialize the Agents module. This function is being called by Asterisk when loading the module. Among other thing it registers applications, cli commands and reads the cofiguration file.

Returns:
int Always 0.

Definition at line 337 of file app_dictate.c.

References ast_register_application(), and dictate_exec().

00338 {
00339    return ast_register_application(app, dictate_exec, synopsis, desc);
00340 }

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

Definition at line 72 of file app_dictate.c.

References ast_streamfile(), ast_waitstream(), and ast_channel::language.

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

int unload_module void   ) 
 

Cleanup all module structures, sockets, etc.

This is called at exit. Any registrations and memory allocations need to be unregistered and free'd here. Nothing else will do these for you (until exit).

Returns:
Zero on success, or non-zero on error.

Definition at line 326 of file app_dictate.c.

References ast_unregister_application(), and STANDARD_HANGUP_LOCALUSERS.

00327 {
00328    int res;
00329 
00330    res = ast_unregister_application(app);
00331    
00332    STANDARD_HANGUP_LOCALUSERS;
00333    
00334    return res;
00335 }

int usecount void   ) 
 

Provides a usecount.

This function will be called by various parts of asterisk. Basically, all it has to do is to return a usecount when called. You will need to maintain your usecount within the module somewhere. The usecount should be how many channels provided by this module are in use.

Returns:
The module's usecount.

Definition at line 347 of file app_dictate.c.

References STANDARD_USECOUNT.

00348 {
00349    int res;
00350    STANDARD_USECOUNT(res);
00351    return res;
00352 }


Variable Documentation

char* app = "Dictate" [static]
 

Definition at line 48 of file app_dictate.c.

char* desc [static]
 

Initial value:

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

Definition at line 50 of file app_dictate.c.

LOCAL_USER_DECL
 

Definition at line 55 of file app_dictate.c.

STANDARD_LOCAL_USER
 

Definition at line 54 of file app_dictate.c.

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

Definition at line 49 of file app_dictate.c.

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

Definition at line 47 of file app_dictate.c.


Generated on Fri May 26 01:45:48 2006 for Asterisk - the Open Source PBX by  doxygen 1.4.6