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