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"
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 (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" |
Virtual Dictation Machine Application For Asterisk.
Definition in file app_dictate.c.
#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().
enum dflags |
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 |
Definition at line 71 of file app_dictate.c.
00071 { 00072 DMODE_INIT, 00073 DMODE_RECORD, 00074 DMODE_PLAY 00075 } dmodes;
AST_MODULE_INFO_STANDARD | ( | ASTERISK_GPL_KEY | , | |
"Virtual Dictation Machine" | ||||
) |
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_alloca, 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_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 oldr = 0, 00105 lastop = 0, 00106 samples = 0, 00107 speed = 1, 00108 digit = 0, 00109 len = 0, 00110 maxlen = 0, 00111 mode = 0; 00112 00113 snprintf(dftbase, sizeof(dftbase), "%s/dictate", ast_config_AST_SPOOL_DIR); 00114 if (!ast_strlen_zero(data)) { 00115 parse = ast_strdupa(data); 00116 AST_STANDARD_APP_ARGS(args, parse); 00117 } else 00118 args.argc = 0; 00119 00120 if (args.argc && !ast_strlen_zero(args.base)) { 00121 base = args.base; 00122 } else { 00123 base = dftbase; 00124 } 00125 if (args.argc > 1 && args.filename) { 00126 filename = args.filename; 00127 } 00128 oldr = chan->readformat; 00129 if ((res = ast_set_read_format(chan, AST_FORMAT_SLINEAR)) < 0) { 00130 ast_log(LOG_WARNING, "Unable to set to linear mode.\n"); 00131 return -1; 00132 } 00133 00134 if (chan->_state != AST_STATE_UP) { 00135 ast_answer(chan); 00136 } 00137 ast_safe_sleep(chan, 200); 00138 for (res = 0; !res;) { 00139 if (ast_strlen_zero(filename)) { 00140 if (ast_app_getdata(chan, "dictate/enter_filename", filein, sizeof(filein), 0) || 00141 ast_strlen_zero(filein)) { 00142 res = -1; 00143 break; 00144 } 00145 } else { 00146 ast_copy_string(filein, filename, sizeof(filein)); 00147 filename = ""; 00148 } 00149 ast_mkdir(base, 0755); 00150 len = strlen(base) + strlen(filein) + 2; 00151 if (!path || len > maxlen) { 00152 path = ast_alloca(len); 00153 memset(path, 0, len); 00154 maxlen = len; 00155 } else { 00156 memset(path, 0, maxlen); 00157 } 00158 00159 snprintf(path, len, "%s/%s", base, filein); 00160 fs = ast_writefile(path, "raw", NULL, O_CREAT|O_APPEND, 0, AST_FILE_MODE); 00161 mode = DMODE_PLAY; 00162 memset(&flags, 0, sizeof(flags)); 00163 ast_set_flag(&flags, DFLAG_PAUSE); 00164 digit = play_and_wait(chan, "dictate/forhelp", AST_DIGIT_ANY); 00165 done = 0; 00166 speed = 1; 00167 res = 0; 00168 lastop = 0; 00169 samples = 0; 00170 while (!done && ((res = ast_waitfor(chan, -1)) > -1) && fs && (f = ast_read(chan))) { 00171 if (digit) { 00172 struct ast_frame fr = {AST_FRAME_DTMF, { .integer = digit } }; 00173 ast_queue_frame(chan, &fr); 00174 digit = 0; 00175 } 00176 if ((f->frametype == AST_FRAME_DTMF)) { 00177 int got = 1; 00178 switch(mode) { 00179 case DMODE_PLAY: 00180 switch (f->subclass.integer) { 00181 case '1': 00182 ast_set_flag(&flags, DFLAG_PAUSE); 00183 mode = DMODE_RECORD; 00184 break; 00185 case '2': 00186 speed++; 00187 if (speed > 4) { 00188 speed = 1; 00189 } 00190 res = ast_say_number(chan, speed, AST_DIGIT_ANY, chan->language, NULL); 00191 break; 00192 case '7': 00193 samples -= ffactor; 00194 if(samples < 0) { 00195 samples = 0; 00196 } 00197 ast_seekstream(fs, samples, SEEK_SET); 00198 break; 00199 case '8': 00200 samples += ffactor; 00201 ast_seekstream(fs, samples, SEEK_SET); 00202 break; 00203 00204 default: 00205 got = 0; 00206 } 00207 break; 00208 case DMODE_RECORD: 00209 switch (f->subclass.integer) { 00210 case '1': 00211 ast_set_flag(&flags, DFLAG_PAUSE); 00212 mode = DMODE_PLAY; 00213 break; 00214 case '8': 00215 ast_toggle_flag(&flags, DFLAG_TRUNC); 00216 lastop = 0; 00217 break; 00218 default: 00219 got = 0; 00220 } 00221 break; 00222 default: 00223 got = 0; 00224 } 00225 if (!got) { 00226 switch (f->subclass.integer) { 00227 case '#': 00228 done = 1; 00229 continue; 00230 break; 00231 case '*': 00232 ast_toggle_flag(&flags, DFLAG_PAUSE); 00233 if (ast_test_flag(&flags, DFLAG_PAUSE)) { 00234 digit = play_and_wait(chan, "dictate/pause", AST_DIGIT_ANY); 00235 } else { 00236 digit = play_and_wait(chan, mode == DMODE_PLAY ? "dictate/playback" : "dictate/record", AST_DIGIT_ANY); 00237 } 00238 break; 00239 case '0': 00240 ast_set_flag(&flags, DFLAG_PAUSE); 00241 digit = play_and_wait(chan, "dictate/paused", AST_DIGIT_ANY); 00242 switch(mode) { 00243 case DMODE_PLAY: 00244 digit = play_and_wait(chan, "dictate/play_help", AST_DIGIT_ANY); 00245 break; 00246 case DMODE_RECORD: 00247 digit = play_and_wait(chan, "dictate/record_help", AST_DIGIT_ANY); 00248 break; 00249 } 00250 if (digit == 0) { 00251 digit = play_and_wait(chan, "dictate/both_help", AST_DIGIT_ANY); 00252 } else if (digit < 0) { 00253 done = 1; 00254 break; 00255 } 00256 break; 00257 } 00258 } 00259 00260 } else if (f->frametype == AST_FRAME_VOICE) { 00261 switch(mode) { 00262 struct ast_frame *fr; 00263 int x; 00264 case DMODE_PLAY: 00265 if (lastop != DMODE_PLAY) { 00266 if (ast_test_flag(&flags, DFLAG_PAUSE)) { 00267 digit = play_and_wait(chan, "dictate/playback_mode", AST_DIGIT_ANY); 00268 if (digit == 0) { 00269 digit = play_and_wait(chan, "dictate/paused", AST_DIGIT_ANY); 00270 } else if (digit < 0) { 00271 break; 00272 } 00273 } 00274 if (lastop != DFLAG_PLAY) { 00275 lastop = DFLAG_PLAY; 00276 ast_closestream(fs); 00277 if (!(fs = ast_openstream(chan, path, chan->language))) 00278 break; 00279 ast_seekstream(fs, samples, SEEK_SET); 00280 chan->stream = NULL; 00281 } 00282 lastop = DMODE_PLAY; 00283 } 00284 00285 if (!ast_test_flag(&flags, DFLAG_PAUSE)) { 00286 for (x = 0; x < speed; x++) { 00287 if ((fr = ast_readframe(fs))) { 00288 ast_write(chan, fr); 00289 samples += fr->samples; 00290 ast_frfree(fr); 00291 fr = NULL; 00292 } else { 00293 samples = 0; 00294 ast_seekstream(fs, 0, SEEK_SET); 00295 } 00296 } 00297 } 00298 break; 00299 case DMODE_RECORD: 00300 if (lastop != DMODE_RECORD) { 00301 int oflags = O_CREAT | O_WRONLY; 00302 if (ast_test_flag(&flags, DFLAG_PAUSE)) { 00303 digit = play_and_wait(chan, "dictate/record_mode", AST_DIGIT_ANY); 00304 if (digit == 0) { 00305 digit = play_and_wait(chan, "dictate/paused", AST_DIGIT_ANY); 00306 } else if (digit < 0) { 00307 break; 00308 } 00309 } 00310 lastop = DMODE_RECORD; 00311 ast_closestream(fs); 00312 if ( ast_test_flag(&flags, DFLAG_TRUNC)) { 00313 oflags |= O_TRUNC; 00314 digit = play_and_wait(chan, "dictate/truncating_audio", AST_DIGIT_ANY); 00315 } else { 00316 oflags |= O_APPEND; 00317 } 00318 fs = ast_writefile(path, "raw", NULL, oflags, 0, AST_FILE_MODE); 00319 if (ast_test_flag(&flags, DFLAG_TRUNC)) { 00320 ast_seekstream(fs, 0, SEEK_SET); 00321 ast_clear_flag(&flags, DFLAG_TRUNC); 00322 } else { 00323 ast_seekstream(fs, 0, SEEK_END); 00324 } 00325 } 00326 if (!ast_test_flag(&flags, DFLAG_PAUSE)) { 00327 res = ast_writestream(fs, f); 00328 } 00329 break; 00330 } 00331 00332 } 00333 00334 ast_frfree(f); 00335 } 00336 } 00337 if (oldr) { 00338 ast_set_read_format(chan, oldr); 00339 } 00340 return 0; 00341 }
static int load_module | ( | void | ) | [static] |
Definition at line 350 of file app_dictate.c.
References ast_register_application_xml, and dictate_exec().
00351 { 00352 return ast_register_application_xml(app, dictate_exec); 00353 }
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_streamfile(), and ast_waitstream().
Referenced by dictate_exec().
00080 { 00081 int res = -1; 00082 if (!ast_streamfile(chan, file, chan->language)) { 00083 res = ast_waitstream(chan, digits); 00084 } 00085 return res; 00086 }
static int unload_module | ( | void | ) | [static] |
Definition at line 343 of file app_dictate.c.
References ast_unregister_application().
00344 { 00345 int res; 00346 res = ast_unregister_application(app); 00347 return res; 00348 }
const char app[] = "Dictate" [static] |
Definition at line 62 of file app_dictate.c.