Thu Apr 28 2011 17:13:37

Asterisk developer's documentation


app_dictate.c File Reference

Virtual Dictation Machine Application For Asterisk. More...

#include "asterisk.h"
#include <sys/stat.h>
#include "asterisk/paths.h"
#include "asterisk/file.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/say.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

static void __reg_module (void)
static void __unreg_module (void)
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 struct ast_module_info
__MODULE_INFO_SECTION 
__mod_info = { __MODULE_INFO_GLOBALS .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Virtual Dictation Machine" , .key = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, }
static char * app = "Dictate"
static struct ast_module_infoast_module_info = &__mod_info

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

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

Definition at line 67 of file app_dictate.c.


Function Documentation

static void __reg_module ( void  ) [static]

Definition at line 351 of file app_dictate.c.

static void __unreg_module ( void  ) [static]

Definition at line 351 of file app_dictate.c.

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

Definition at line 84 of file app_dictate.c.

References ast_channel::_state, ast_answer(), AST_APP_ARG, ast_app_getdata(), ast_clear_flag, ast_closestream(), ast_config_AST_SPOOL_DIR, ast_copy_string(), AST_DECLARE_APP_ARGS, AST_DIGIT_ANY, AST_FILE_MODE, AST_FORMAT_SLINEAR, AST_FRAME_DTMF, AST_FRAME_VOICE, ast_frfree, ast_log(), ast_mkdir(), 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_STATE_UP, ast_strdupa, ast_strlen_zero(), ast_test_flag, ast_toggle_flag, ast_waitfor(), ast_write(), ast_writefile(), ast_writestream(), DFLAG_PAUSE, DFLAG_PLAY, DFLAG_TRUNC, DMODE_PLAY, DMODE_RECORD, f, ast_frame::frametype, ast_channel::language, len(), LOG_WARNING, parse(), play_and_wait(), ast_channel::readformat, ast_frame::samples, ast_channel::stream, and ast_frame::subclass.

Referenced by load_module().

{
   char *path = NULL, filein[256], *filename = "";
   char *parse;
   AST_DECLARE_APP_ARGS(args,
      AST_APP_ARG(base);
      AST_APP_ARG(filename);
   );
   char dftbase[256];
   char *base;
   struct ast_flags flags = {0};
   struct ast_filestream *fs;
   struct ast_frame *f = NULL;
   int ffactor = 320 * 80,
      res = 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 (!ast_strlen_zero(data)) {
      parse = ast_strdupa(data);
      AST_STANDARD_APP_ARGS(args, parse);
   } else
      args.argc = 0;

   if (args.argc && !ast_strlen_zero(args.base)) {
      base = args.base;
   } else {
      base = dftbase;
   }
   if (args.argc > 1 && args.filename) {
      filename = args.filename;
   }
   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;
   }

   if (chan->_state != AST_STATE_UP) {
      ast_answer(chan);
   }
   ast_safe_sleep(chan, 200);
   for (res = 0; !res;) {
      if (ast_strlen_zero(filename)) {
         if (ast_app_getdata(chan, "dictate/enter_filename", filein, sizeof(filein), 0) ||
            ast_strlen_zero(filein)) {
            res = -1;
            break;
         }
      } else {
         ast_copy_string(filein, filename, sizeof(filein));
         filename = "";
      }
      ast_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, AST_FILE_MODE);
      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, 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);
                     if (!(fs = ast_openstream(chan, path, chan->language)))
                        break;
                     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, AST_FILE_MODE);
                  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);
   }
   return 0;
}
static int load_module ( void  ) [static]
static int play_and_wait ( struct ast_channel chan,
char *  file,
char *  digits 
) [static]

Definition at line 75 of file app_dictate.c.

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

Referenced by dictate_exec().

{
   int res = -1;
   if (!ast_streamfile(chan, file, chan->language)) {
      res = ast_waitstream(chan, digits);
   }
   return res;
}
static int unload_module ( void  ) [static]

Definition at line 339 of file app_dictate.c.

References ast_unregister_application().

{
   int res;
   res = ast_unregister_application(app);
   return res;
}

Variable Documentation

struct ast_module_info __MODULE_INFO_SECTION __mod_info = { __MODULE_INFO_GLOBALS .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Virtual Dictation Machine" , .key = ASTERISK_GPL_KEY , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, } [static]

Definition at line 351 of file app_dictate.c.

char* app = "Dictate" [static]

Definition at line 58 of file app_dictate.c.

Definition at line 351 of file app_dictate.c.