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$")
40 #include "asterisk/file.h"
41 #include "asterisk/logger.h"
42 #include "asterisk/channel.h"
43 #include "asterisk/pbx.h"
44 #include "asterisk/module.h"
45 #include "asterisk/say.h"
46 #include "asterisk/lock.h"
47 #include "asterisk/app.h"
49 static char *app
= "Dictate";
50 static char *synopsis
= "Virtual Dictation Machine";
51 static char *desc
= " Dictate([<base_dir>[|<filename>]])\n"
52 "Start dictation machine using optional base dir for files.\n";
56 DFLAG_RECORD
= (1 << 0),
57 DFLAG_PLAY
= (1 << 1),
58 DFLAG_TRUNC
= (1 << 2),
59 DFLAG_PAUSE
= (1 << 3),
68 #define ast_toggle_flag(it,flag) if(ast_test_flag(it, flag)) ast_clear_flag(it, flag); else ast_set_flag(it, flag)
70 static int play_and_wait(struct ast_channel
*chan
, char *file
, char *digits
)
73 if (!ast_streamfile(chan
, file
, chan
->language
)) {
74 res
= ast_waitstream(chan
, digits
);
79 static int dictate_exec(struct ast_channel
*chan
, void *data
)
81 char *path
= NULL
, filein
[256], *filename
= "";
83 AST_DECLARE_APP_ARGS(args
,
85 AST_APP_ARG(filename
);
89 struct ast_flags flags
= {0};
90 struct ast_filestream
*fs
;
91 struct ast_frame
*f
= NULL
;
92 struct ast_module_user
*u
;
93 int ffactor
= 320 * 80,
105 u
= ast_module_user_add(chan
);
107 snprintf(dftbase
, sizeof(dftbase
), "%s/dictate", ast_config_AST_SPOOL_DIR
);
108 if (!ast_strlen_zero(data
)) {
109 parse
= ast_strdupa(data
);
110 AST_STANDARD_APP_ARGS(args
, parse
);
114 if (args
.argc
&& !ast_strlen_zero(args
.base
)) {
119 if (args
.argc
> 1 && args
.filename
) {
120 filename
= args
.filename
;
122 oldr
= chan
->readformat
;
123 if ((res
= ast_set_read_format(chan
, AST_FORMAT_SLINEAR
)) < 0) {
124 ast_log(LOG_WARNING
, "Unable to set to linear mode.\n");
125 ast_module_user_remove(u
);
130 ast_safe_sleep(chan
, 200);
131 for (res
= 0; !res
;) {
132 if (ast_strlen_zero(filename
)) {
133 if (ast_app_getdata(chan
, "dictate/enter_filename", filein
, sizeof(filein
), 0) ||
134 ast_strlen_zero(filein
)) {
139 ast_copy_string(filein
, filename
, sizeof(filein
));
143 len
= strlen(base
) + strlen(filein
) + 2;
144 if (!path
|| len
> maxlen
) {
146 memset(path
, 0, len
);
149 memset(path
, 0, maxlen
);
152 snprintf(path
, len
, "%s/%s", base
, filein
);
153 fs
= ast_writefile(path
, "raw", NULL
, O_CREAT
|O_APPEND
, 0, 0700);
155 memset(&flags
, 0, sizeof(flags
));
156 ast_set_flag(&flags
, DFLAG_PAUSE
);
157 digit
= play_and_wait(chan
, "dictate/forhelp", AST_DIGIT_ANY
);
163 while (!done
&& ((res
= ast_waitfor(chan
, -1)) > -1) && fs
&& (f
= ast_read(chan
))) {
165 struct ast_frame fr
= {AST_FRAME_DTMF
, digit
};
166 ast_queue_frame(chan
, &fr
);
169 if ((f
->frametype
== AST_FRAME_DTMF
)) {
173 switch(f
->subclass
) {
175 ast_set_flag(&flags
, DFLAG_PAUSE
);
183 res
= ast_say_number(chan
, speed
, AST_DIGIT_ANY
, chan
->language
, (char *) NULL
);
190 ast_seekstream(fs
, samples
, SEEK_SET
);
194 ast_seekstream(fs
, samples
, SEEK_SET
);
202 switch(f
->subclass
) {
204 ast_set_flag(&flags
, DFLAG_PAUSE
);
208 ast_toggle_flag(&flags
, DFLAG_TRUNC
);
219 switch(f
->subclass
) {
225 ast_toggle_flag(&flags
, DFLAG_PAUSE
);
226 if (ast_test_flag(&flags
, DFLAG_PAUSE
)) {
227 digit
= play_and_wait(chan
, "dictate/pause", AST_DIGIT_ANY
);
229 digit
= play_and_wait(chan
, mode
== DMODE_PLAY
? "dictate/playback" : "dictate/record", AST_DIGIT_ANY
);
233 ast_set_flag(&flags
, DFLAG_PAUSE
);
234 digit
= play_and_wait(chan
, "dictate/paused", AST_DIGIT_ANY
);
237 digit
= play_and_wait(chan
, "dictate/play_help", AST_DIGIT_ANY
);
240 digit
= play_and_wait(chan
, "dictate/record_help", AST_DIGIT_ANY
);
244 digit
= play_and_wait(chan
, "dictate/both_help", AST_DIGIT_ANY
);
245 } else if (digit
< 0) {
253 } else if (f
->frametype
== AST_FRAME_VOICE
) {
255 struct ast_frame
*fr
;
258 if (lastop
!= DMODE_PLAY
) {
259 if (ast_test_flag(&flags
, DFLAG_PAUSE
)) {
260 digit
= play_and_wait(chan
, "dictate/playback_mode", AST_DIGIT_ANY
);
262 digit
= play_and_wait(chan
, "dictate/paused", AST_DIGIT_ANY
);
263 } else if (digit
< 0) {
267 if (lastop
!= DFLAG_PLAY
) {
270 if (!(fs
= ast_openstream(chan
, path
, chan
->language
)))
272 ast_seekstream(fs
, samples
, SEEK_SET
);
278 if (!ast_test_flag(&flags
, DFLAG_PAUSE
)) {
279 for (x
= 0; x
< speed
; x
++) {
280 if ((fr
= ast_readframe(fs
))) {
282 samples
+= fr
->samples
;
287 ast_seekstream(fs
, 0, SEEK_SET
);
293 if (lastop
!= DMODE_RECORD
) {
294 int oflags
= O_CREAT
| O_WRONLY
;
295 if (ast_test_flag(&flags
, DFLAG_PAUSE
)) {
296 digit
= play_and_wait(chan
, "dictate/record_mode", AST_DIGIT_ANY
);
298 digit
= play_and_wait(chan
, "dictate/paused", AST_DIGIT_ANY
);
299 } else if (digit
< 0) {
303 lastop
= DMODE_RECORD
;
305 if ( ast_test_flag(&flags
, DFLAG_TRUNC
)) {
307 digit
= play_and_wait(chan
, "dictate/truncating_audio", AST_DIGIT_ANY
);
311 fs
= ast_writefile(path
, "raw", NULL
, oflags
, 0, 0700);
312 if (ast_test_flag(&flags
, DFLAG_TRUNC
)) {
313 ast_seekstream(fs
, 0, SEEK_SET
);
314 ast_clear_flag(&flags
, DFLAG_TRUNC
);
316 ast_seekstream(fs
, 0, SEEK_END
);
319 if (!ast_test_flag(&flags
, DFLAG_PAUSE
)) {
320 res
= ast_writestream(fs
, f
);
331 ast_set_read_format(chan
, oldr
);
333 ast_module_user_remove(u
);
337 static int unload_module(void)
340 res
= ast_unregister_application(app
);
344 static int load_module(void)
346 return ast_register_application(app
, dictate_exec
, synopsis
, desc
);
349 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY
, "Virtual Dictation Machine");