2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 2005, Anthony Minessale II
6 * Anthony Minessale II <anthmct@yahoo.com>
8 * Donated by Sangoma Technologies <http://www.samgoma.com>
10 * See http://www.asterisk.org for more information about
11 * the Asterisk project. Please do not directly contact
12 * any of the maintainers of this project for assistance;
13 * the project provides a web site, mailing lists and IRC
14 * channels for your use.
16 * This program is free software, distributed under the terms of
17 * the GNU General Public License Version 2. See the LICENSE file
18 * at the top of the source tree.
23 * \brief Virtual Dictation Machine Application For Asterisk
25 * \author Anthony Minessale II <anthmct@yahoo.com>
27 * \ingroup applications
32 ASTERISK_FILE_VERSION(__FILE__
, "$Revision$")
36 #include "asterisk/paths.h" /* use ast_config_AST_SPOOL_DIR */
37 #include "asterisk/file.h"
38 #include "asterisk/pbx.h"
39 #include "asterisk/module.h"
40 #include "asterisk/say.h"
41 #include "asterisk/app.h"
43 static char *app
= "Dictate";
44 static char *synopsis
= "Virtual Dictation Machine";
45 static char *desc
= " Dictate([<base_dir>[,<filename>]])\n"
46 "Start dictation machine using optional base dir for files.\n";
50 DFLAG_RECORD
= (1 << 0),
51 DFLAG_PLAY
= (1 << 1),
52 DFLAG_TRUNC
= (1 << 2),
53 DFLAG_PAUSE
= (1 << 3),
62 #define ast_toggle_flag(it,flag) if(ast_test_flag(it, flag)) ast_clear_flag(it, flag); else ast_set_flag(it, flag)
64 static int play_and_wait(struct ast_channel
*chan
, char *file
, char *digits
)
67 if (!ast_streamfile(chan
, file
, chan
->language
)) {
68 res
= ast_waitstream(chan
, digits
);
73 static int dictate_exec(struct ast_channel
*chan
, void *data
)
75 char *path
= NULL
, filein
[256], *filename
= "";
77 AST_DECLARE_APP_ARGS(args
,
79 AST_APP_ARG(filename
);
83 struct ast_flags flags
= {0};
84 struct ast_filestream
*fs
;
85 struct ast_frame
*f
= NULL
;
86 int ffactor
= 320 * 80,
98 snprintf(dftbase
, sizeof(dftbase
), "%s/dictate", ast_config_AST_SPOOL_DIR
);
99 if (!ast_strlen_zero(data
)) {
100 parse
= ast_strdupa(data
);
101 AST_STANDARD_APP_ARGS(args
, parse
);
105 if (args
.argc
&& !ast_strlen_zero(args
.base
)) {
110 if (args
.argc
> 1 && args
.filename
) {
111 filename
= args
.filename
;
113 oldr
= chan
->readformat
;
114 if ((res
= ast_set_read_format(chan
, AST_FORMAT_SLINEAR
)) < 0) {
115 ast_log(LOG_WARNING
, "Unable to set to linear mode.\n");
120 ast_safe_sleep(chan
, 200);
121 for (res
= 0; !res
;) {
122 if (ast_strlen_zero(filename
)) {
123 if (ast_app_getdata(chan
, "dictate/enter_filename", filein
, sizeof(filein
), 0) ||
124 ast_strlen_zero(filein
)) {
129 ast_copy_string(filein
, filename
, sizeof(filein
));
132 ast_mkdir(base
, 0755);
133 len
= strlen(base
) + strlen(filein
) + 2;
134 if (!path
|| len
> maxlen
) {
136 memset(path
, 0, len
);
139 memset(path
, 0, maxlen
);
142 snprintf(path
, len
, "%s/%s", base
, filein
);
143 fs
= ast_writefile(path
, "raw", NULL
, O_CREAT
|O_APPEND
, 0, AST_FILE_MODE
);
145 memset(&flags
, 0, sizeof(flags
));
146 ast_set_flag(&flags
, DFLAG_PAUSE
);
147 digit
= play_and_wait(chan
, "dictate/forhelp", AST_DIGIT_ANY
);
153 while (!done
&& ((res
= ast_waitfor(chan
, -1)) > -1) && fs
&& (f
= ast_read(chan
))) {
155 struct ast_frame fr
= {AST_FRAME_DTMF
, digit
};
156 ast_queue_frame(chan
, &fr
);
159 if ((f
->frametype
== AST_FRAME_DTMF
)) {
163 switch(f
->subclass
) {
165 ast_set_flag(&flags
, DFLAG_PAUSE
);
173 res
= ast_say_number(chan
, speed
, AST_DIGIT_ANY
, chan
->language
, NULL
);
180 ast_seekstream(fs
, samples
, SEEK_SET
);
184 ast_seekstream(fs
, samples
, SEEK_SET
);
192 switch(f
->subclass
) {
194 ast_set_flag(&flags
, DFLAG_PAUSE
);
198 ast_toggle_flag(&flags
, DFLAG_TRUNC
);
209 switch(f
->subclass
) {
215 ast_toggle_flag(&flags
, DFLAG_PAUSE
);
216 if (ast_test_flag(&flags
, DFLAG_PAUSE
)) {
217 digit
= play_and_wait(chan
, "dictate/pause", AST_DIGIT_ANY
);
219 digit
= play_and_wait(chan
, mode
== DMODE_PLAY
? "dictate/playback" : "dictate/record", AST_DIGIT_ANY
);
223 ast_set_flag(&flags
, DFLAG_PAUSE
);
224 digit
= play_and_wait(chan
, "dictate/paused", AST_DIGIT_ANY
);
227 digit
= play_and_wait(chan
, "dictate/play_help", AST_DIGIT_ANY
);
230 digit
= play_and_wait(chan
, "dictate/record_help", AST_DIGIT_ANY
);
234 digit
= play_and_wait(chan
, "dictate/both_help", AST_DIGIT_ANY
);
235 } else if (digit
< 0) {
243 } else if (f
->frametype
== AST_FRAME_VOICE
) {
245 struct ast_frame
*fr
;
248 if (lastop
!= DMODE_PLAY
) {
249 if (ast_test_flag(&flags
, DFLAG_PAUSE
)) {
250 digit
= play_and_wait(chan
, "dictate/playback_mode", AST_DIGIT_ANY
);
252 digit
= play_and_wait(chan
, "dictate/paused", AST_DIGIT_ANY
);
253 } else if (digit
< 0) {
257 if (lastop
!= DFLAG_PLAY
) {
260 if (!(fs
= ast_openstream(chan
, path
, chan
->language
)))
262 ast_seekstream(fs
, samples
, SEEK_SET
);
268 if (!ast_test_flag(&flags
, DFLAG_PAUSE
)) {
269 for (x
= 0; x
< speed
; x
++) {
270 if ((fr
= ast_readframe(fs
))) {
272 samples
+= fr
->samples
;
277 ast_seekstream(fs
, 0, SEEK_SET
);
283 if (lastop
!= DMODE_RECORD
) {
284 int oflags
= O_CREAT
| O_WRONLY
;
285 if (ast_test_flag(&flags
, DFLAG_PAUSE
)) {
286 digit
= play_and_wait(chan
, "dictate/record_mode", AST_DIGIT_ANY
);
288 digit
= play_and_wait(chan
, "dictate/paused", AST_DIGIT_ANY
);
289 } else if (digit
< 0) {
293 lastop
= DMODE_RECORD
;
295 if ( ast_test_flag(&flags
, DFLAG_TRUNC
)) {
297 digit
= play_and_wait(chan
, "dictate/truncating_audio", AST_DIGIT_ANY
);
301 fs
= ast_writefile(path
, "raw", NULL
, oflags
, 0, AST_FILE_MODE
);
302 if (ast_test_flag(&flags
, DFLAG_TRUNC
)) {
303 ast_seekstream(fs
, 0, SEEK_SET
);
304 ast_clear_flag(&flags
, DFLAG_TRUNC
);
306 ast_seekstream(fs
, 0, SEEK_END
);
309 if (!ast_test_flag(&flags
, DFLAG_PAUSE
)) {
310 res
= ast_writestream(fs
, f
);
321 ast_set_read_format(chan
, oldr
);
326 static int unload_module(void)
329 res
= ast_unregister_application(app
);
333 static int load_module(void)
335 return ast_register_application(app
, dictate_exec
, synopsis
, desc
);
338 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY
, "Virtual Dictation Machine");