Asterisk.org: Developer Documentation (28 Oct 2009)

Wed Oct 28 15:48:02 2009

## 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.

Referenced by dictate_exec().

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

    00344 {
    00345    return tdesc;
    00346 }

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_clear_flag, ast_closestream(), ast_config_AST_SPOOL_DIR, AST_DIGIT_ANY, AST_FORMAT_SLINEAR, AST_FRAME_DTMF, AST_FRAME_VOICE, ast_frfree(), ast_log(), 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_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, ast_frame::frametype, ast_channel::language, LOCAL_USER_ADD, LOCAL_USER_REMOVE, LOG_WARNING, play_and_wait(), ast_channel::readformat, ast_frame::samples, ast_channel::stream, and ast_frame::subclass.

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                      if (!(fs = ast_openstream(chan, path, chan->language)))
    00261                         break;
    00262                      ast_seekstream(fs, samples, SEEK_SET);
    00263                      chan->stream = NULL;
    00264                   }
    00265                   lastop = DMODE_PLAY;
    00266                }
    00267
    00268                if (!ast_test_flag(&flags, DFLAG_PAUSE)) {
    00269                   for (x = 0; x < speed; x++) {
    00270                      if ((fr = ast_readframe(fs))) {
    00271                         ast_write(chan, fr);
    00272                         samples += fr->samples;
    00273                         ast_frfree(fr);
    00274                         fr = NULL;
    00275                      } else {
    00276                         samples = 0;
    00277                         ast_seekstream(fs, 0, SEEK_SET);
    00278                      }
    00279                   }
    00280                }
    00281                break;
    00282             case DMODE_RECORD:
    00283                if (lastop != DMODE_RECORD) {
    00284                   int oflags = O_CREAT | O_WRONLY;
    00285                   if (ast_test_flag(&flags, DFLAG_PAUSE)) {
    00286                      digit = play_and_wait(chan, "dictate/record_mode", AST_DIGIT_ANY);
    00287                      if (digit == 0) {
    00288                         digit = play_and_wait(chan, "dictate/paused", AST_DIGIT_ANY);
    00289                      } else if (digit < 0) {
    00290                         break;
    00291                      }
    00292                   }
    00293                   lastop = DMODE_RECORD;
    00294                   ast_closestream(fs);
    00295                   if ( ast_test_flag(&flags, DFLAG_TRUNC)) {
    00296                      oflags |= O_TRUNC;
    00297                      digit = play_and_wait(chan, "dictate/truncating_audio", AST_DIGIT_ANY);
    00298                   } else {
    00299                      oflags |= O_APPEND;
    00300                   }
    00301                   fs = ast_writefile(path, "raw", NULL, oflags, 0, 0700);
    00302                   if (ast_test_flag(&flags, DFLAG_TRUNC)) {
    00303                      ast_seekstream(fs, 0, SEEK_SET);
    00304                      ast_clear_flag(&flags, DFLAG_TRUNC);
    00305                   } else {
    00306                      ast_seekstream(fs, 0, SEEK_END);
    00307                   }
    00308                }
    00309                if (!ast_test_flag(&flags, DFLAG_PAUSE)) {
    00310                   res = ast_writestream(fs, f);
    00311                }
    00312                break;
    00313             }
    00314
    00315          }
    00316
    00317          ast_frfree(f);
    00318       }
    00319    }
    00320    if (oldr) {
    00321       ast_set_read_format(chan, oldr);
    00322    }
    00323    LOCAL_USER_REMOVE(u);
    00324    return 0;
    00325 }

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

References ASTERISK_GPL_KEY.

    00356 {
    00357    return ASTERISK_GPL_KEY;
    00358 }

int load_module | ( | void |  | ) |

Initialize the module.

This function is called at module load time. Put all code in here that needs to set up your module's hardware, software, registrations, etc.

Returns:
  This function should return 0 on success and non-zero on failure. If the module is not loaded successfully, Asterisk will call its unload_module() function.

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.

TE STUFF END

Definition at line 338 of file app_dictate.c.

References ast_register_application(), and dictate_exec().

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

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.

Referenced by dictate_exec().

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

References ast_unregister_application(), and STANDARD_HANGUP_LOCALUSERS.

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

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

References STANDARD_USECOUNT.

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

## 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.