#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" |
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 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 |
Definition at line 64 of file app_dictate.c.
00064 { 00065 DMODE_INIT, 00066 DMODE_RECORD, 00067 DMODE_PLAY 00068 } dmodes;
| char* description | ( | void | ) |
Provides a description of the 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(), localuser::chan, DFLAG_PAUSE, DFLAG_PLAY, DFLAG_TRUNC, DMODE_PLAY, DMODE_RECORD, localuser::flags, ast_flags::flags, ast_frame::frametype, LOCAL_USER_ADD, LOCAL_USER_REMOVE, LOG_WARNING, play_and_wait(), ast_channel::readformat, ast_frame::samples, 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; }
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.
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).
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.
Definition at line 348 of file app_dictate.c.
References STANDARD_USECOUNT.
00349 { 00350 int res; 00351 STANDARD_USECOUNT(res); 00352 return res; 00353 }
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.
Definition at line 55 of file app_dictate.c.
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.
1.5.1