Sat Feb 11 06:33:38 2012

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, 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 struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Virtual Dictation Machine" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, }
static const 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 77 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 64 of file app_dictate.c.

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

enum dmodes

Enumerator:
DMODE_INIT 
DMODE_RECORD 
DMODE_PLAY 

Definition at line 71 of file app_dictate.c.

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


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 356 of file app_dictate.c.

static void __unreg_module ( void   )  [static]

Definition at line 356 of file app_dictate.c.

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

Definition at line 88 of file app_dictate.c.

References ast_channel::_state, args, ast_answer(), AST_APP_ARG, ast_app_getdata(), ast_channel_language(), 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_clear(), ast_format_copy(), 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_set_read_format_by_id(), 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_format::id, ast_frame_subclass::integer, len(), LOG_WARNING, parse(), play_and_wait(), ast_channel::readformat, ast_frame::samples, ast_channel::stream, and ast_frame::subclass.

Referenced by load_module().

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

static int load_module ( void   )  [static]

Definition at line 351 of file app_dictate.c.

References ast_register_application_xml, and dictate_exec().

00352 {
00353    return ast_register_application_xml(app, dictate_exec);
00354 }

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

Definition at line 79 of file app_dictate.c.

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

Referenced by dictate_exec().

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

static int unload_module ( void   )  [static]

Definition at line 344 of file app_dictate.c.

References ast_unregister_application().

00345 {
00346    int res;
00347    res = ast_unregister_application(app);
00348    return res;
00349 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Virtual Dictation Machine" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, } [static]

Definition at line 356 of file app_dictate.c.

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

Definition at line 62 of file app_dictate.c.

Definition at line 356 of file app_dictate.c.


Generated on Sat Feb 11 06:33:39 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6