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 "asterisk/format_cache.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_EXTENDED (ASTERISK_GPL_KEY,"Virtual Dictation Machine")
static int dictate_exec (struct ast_channel *chan, const char *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 const char app [] = "Dictate"


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

00065              {
00066    DFLAG_RECORD = (1 << 0),
00067    DFLAG_PLAY = (1 << 1),
00068    DFLAG_TRUNC = (1 << 2),
00069    DFLAG_PAUSE = (1 << 3),
00070 } dflags;

enum dmodes

Enumerator:
DMODE_INIT 
DMODE_RECORD 
DMODE_PLAY 

Definition at line 72 of file app_dictate.c.

00072              {
00073    DMODE_INIT,
00074    DMODE_RECORD,
00075    DMODE_PLAY
00076 } dmodes;


Function Documentation

AST_MODULE_INFO_STANDARD_EXTENDED ( ASTERISK_GPL_KEY  ,
"Virtual Dictation Machine"   
)

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

Definition at line 89 of file app_dictate.c.

References ao2_bump, ao2_cleanup, ao2_ref, args, ast_alloca, ast_answer(), AST_APP_ARG, ast_app_getdata(), ast_channel_language(), ast_channel_readformat(), ast_channel_stream_set(), 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_slin, 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, digit, DMODE_PLAY, DMODE_RECORD, f, ast_frame::frametype, ast_frame_subclass::integer, len(), LOG_WARNING, NULL, parse(), play_and_wait(), ast_frame::samples, and ast_frame::subclass.

Referenced by load_module().

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

static int load_module ( void   )  [static]

Definition at line 353 of file app_dictate.c.

References ast_register_application_xml, and dictate_exec().

00354 {
00355    return ast_register_application_xml(app, dictate_exec);
00356 }

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

Definition at line 80 of file app_dictate.c.

References ast_channel_language(), ast_streamfile(), and ast_waitstream().

Referenced by dictate_exec().

00081 {
00082    int res = -1;
00083    if (!ast_streamfile(chan, file, ast_channel_language(chan))) {
00084       res = ast_waitstream(chan, digits);
00085    }
00086    return res;
00087 }

static int unload_module ( void   )  [static]

Definition at line 346 of file app_dictate.c.

References ast_unregister_application().

00347 {
00348    int res;
00349    res = ast_unregister_application(app);
00350    return res;
00351 }


Variable Documentation

const char app[] = "Dictate" [static]

Definition at line 63 of file app_dictate.c.


Generated on Thu Apr 16 06:28:24 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6