Wed Jan 8 2020 09:49:53

Asterisk developer's documentation


app_dictate.c File Reference

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.

Macros

#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

static void __reg_module (void)
 
static void __unreg_module (void)
 
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 struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Virtual Dictation Machine" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, }
 
static const char app [] = "Dictate"
 
static struct ast_module_infoast_module_info = &__mod_info
 

Detailed Description

Virtual Dictation Machine Application For Asterisk.

Author
Anthony Minessale II anthm.nosp@m.ct@y.nosp@m.ahoo..nosp@m.com

Definition in file app_dictate.c.

Macro Definition Documentation

#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().

Enumeration Type Documentation

enum dflags
Enumerator
DFLAG_RECORD 
DFLAG_PLAY 
DFLAG_TRUNC 
DFLAG_PAUSE 

Definition at line 64 of file app_dictate.c.

64  {
65  DFLAG_RECORD = (1 << 0),
66  DFLAG_PLAY = (1 << 1),
67  DFLAG_TRUNC = (1 << 2),
68  DFLAG_PAUSE = (1 << 3),
69 } dflags;
dflags
Definition: app_dictate.c:64
enum dmodes
Enumerator
DMODE_INIT 
DMODE_RECORD 
DMODE_PLAY 

Definition at line 71 of file app_dictate.c.

71  {
72  DMODE_INIT,
75 } dmodes;
dmodes
Definition: app_dictate.c:71

Function Documentation

static void __reg_module ( void  )
static

Definition at line 355 of file app_dictate.c.

static void __unreg_module ( void  )
static

Definition at line 355 of file app_dictate.c.

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, ast_channel::language, len(), LOG_WARNING, parse(), play_and_wait(), ast_channel::readformat, ast_frame::samples, ast_channel::stream, and ast_frame::subclass.

Referenced by load_module().

89 {
90  char *path = NULL, filein[256], *filename = "";
91  char *parse;
93  AST_APP_ARG(base);
94  AST_APP_ARG(filename);
95  );
96  char dftbase[256];
97  char *base;
98  struct ast_flags flags = {0};
99  struct ast_filestream *fs;
100  struct ast_frame *f = NULL;
101  int ffactor = 320 * 80,
102  res = 0,
103  done = 0,
104  oldr = 0,
105  lastop = 0,
106  samples = 0,
107  speed = 1,
108  digit = 0,
109  len = 0,
110  maxlen = 0,
111  mode = 0;
112 
113  snprintf(dftbase, sizeof(dftbase), "%s/dictate", ast_config_AST_SPOOL_DIR);
114  if (!ast_strlen_zero(data)) {
115  parse = ast_strdupa(data);
116  AST_STANDARD_APP_ARGS(args, parse);
117  } else
118  args.argc = 0;
119 
120  if (args.argc && !ast_strlen_zero(args.base)) {
121  base = args.base;
122  } else {
123  base = dftbase;
124  }
125  if (args.argc > 1 && args.filename) {
126  filename = args.filename;
127  }
128  oldr = chan->readformat;
129  if ((res = ast_set_read_format(chan, AST_FORMAT_SLINEAR)) < 0) {
130  ast_log(LOG_WARNING, "Unable to set to linear mode.\n");
131  return -1;
132  }
133 
134  if (chan->_state != AST_STATE_UP) {
135  ast_answer(chan);
136  }
137  ast_safe_sleep(chan, 200);
138  for (res = 0; !res;) {
139  if (ast_strlen_zero(filename)) {
140  if (ast_app_getdata(chan, "dictate/enter_filename", filein, sizeof(filein), 0) ||
141  ast_strlen_zero(filein)) {
142  res = -1;
143  break;
144  }
145  } else {
146  ast_copy_string(filein, filename, sizeof(filein));
147  filename = "";
148  }
149  ast_mkdir(base, 0755);
150  len = strlen(base) + strlen(filein) + 2;
151  if (!path || len > maxlen) {
152  path = ast_alloca(len);
153  memset(path, 0, len);
154  maxlen = len;
155  } else {
156  memset(path, 0, maxlen);
157  }
158 
159  snprintf(path, len, "%s/%s", base, filein);
160  fs = ast_writefile(path, "raw", NULL, O_CREAT|O_APPEND, 0, AST_FILE_MODE);
161  mode = DMODE_PLAY;
162  memset(&flags, 0, sizeof(flags));
163  ast_set_flag(&flags, DFLAG_PAUSE);
164  digit = play_and_wait(chan, "dictate/forhelp", AST_DIGIT_ANY);
165  done = 0;
166  speed = 1;
167  res = 0;
168  lastop = 0;
169  samples = 0;
170  while (!done && ((res = ast_waitfor(chan, -1)) > -1) && fs && (f = ast_read(chan))) {
171  if (digit) {
172  struct ast_frame fr = {AST_FRAME_DTMF, { .integer = digit } };
173  ast_queue_frame(chan, &fr);
174  digit = 0;
175  }
176  if ((f->frametype == AST_FRAME_DTMF)) {
177  int got = 1;
178  switch(mode) {
179  case DMODE_PLAY:
180  switch (f->subclass.integer) {
181  case '1':
182  ast_set_flag(&flags, DFLAG_PAUSE);
183  mode = DMODE_RECORD;
184  break;
185  case '2':
186  speed++;
187  if (speed > 4) {
188  speed = 1;
189  }
190  res = ast_say_number(chan, speed, AST_DIGIT_ANY, chan->language, NULL);
191  break;
192  case '7':
193  samples -= ffactor;
194  if(samples < 0) {
195  samples = 0;
196  }
197  ast_seekstream(fs, samples, SEEK_SET);
198  break;
199  case '8':
200  samples += ffactor;
201  ast_seekstream(fs, samples, SEEK_SET);
202  break;
203 
204  default:
205  got = 0;
206  }
207  break;
208  case DMODE_RECORD:
209  switch (f->subclass.integer) {
210  case '1':
211  ast_set_flag(&flags, DFLAG_PAUSE);
212  mode = DMODE_PLAY;
213  break;
214  case '8':
215  ast_toggle_flag(&flags, DFLAG_TRUNC);
216  lastop = 0;
217  break;
218  default:
219  got = 0;
220  }
221  break;
222  default:
223  got = 0;
224  }
225  if (!got) {
226  switch (f->subclass.integer) {
227  case '#':
228  done = 1;
229  continue;
230  break;
231  case '*':
232  ast_toggle_flag(&flags, DFLAG_PAUSE);
233  if (ast_test_flag(&flags, DFLAG_PAUSE)) {
234  digit = play_and_wait(chan, "dictate/pause", AST_DIGIT_ANY);
235  } else {
236  digit = play_and_wait(chan, mode == DMODE_PLAY ? "dictate/playback" : "dictate/record", AST_DIGIT_ANY);
237  }
238  break;
239  case '0':
240  ast_set_flag(&flags, DFLAG_PAUSE);
241  digit = play_and_wait(chan, "dictate/paused", AST_DIGIT_ANY);
242  switch(mode) {
243  case DMODE_PLAY:
244  digit = play_and_wait(chan, "dictate/play_help", AST_DIGIT_ANY);
245  break;
246  case DMODE_RECORD:
247  digit = play_and_wait(chan, "dictate/record_help", AST_DIGIT_ANY);
248  break;
249  }
250  if (digit == 0) {
251  digit = play_and_wait(chan, "dictate/both_help", AST_DIGIT_ANY);
252  } else if (digit < 0) {
253  done = 1;
254  break;
255  }
256  break;
257  }
258  }
259 
260  } else if (f->frametype == AST_FRAME_VOICE) {
261  switch(mode) {
262  struct ast_frame *fr;
263  int x;
264  case DMODE_PLAY:
265  if (lastop != DMODE_PLAY) {
266  if (ast_test_flag(&flags, DFLAG_PAUSE)) {
267  digit = play_and_wait(chan, "dictate/playback_mode", AST_DIGIT_ANY);
268  if (digit == 0) {
269  digit = play_and_wait(chan, "dictate/paused", AST_DIGIT_ANY);
270  } else if (digit < 0) {
271  break;
272  }
273  }
274  if (lastop != DFLAG_PLAY) {
275  lastop = DFLAG_PLAY;
276  ast_closestream(fs);
277  if (!(fs = ast_openstream(chan, path, chan->language)))
278  break;
279  ast_seekstream(fs, samples, SEEK_SET);
280  chan->stream = NULL;
281  }
282  lastop = DMODE_PLAY;
283  }
284 
285  if (!ast_test_flag(&flags, DFLAG_PAUSE)) {
286  for (x = 0; x < speed; x++) {
287  if ((fr = ast_readframe(fs))) {
288  ast_write(chan, fr);
289  samples += fr->samples;
290  ast_frfree(fr);
291  fr = NULL;
292  } else {
293  samples = 0;
294  ast_seekstream(fs, 0, SEEK_SET);
295  }
296  }
297  }
298  break;
299  case DMODE_RECORD:
300  if (lastop != DMODE_RECORD) {
301  int oflags = O_CREAT | O_WRONLY;
302  if (ast_test_flag(&flags, DFLAG_PAUSE)) {
303  digit = play_and_wait(chan, "dictate/record_mode", AST_DIGIT_ANY);
304  if (digit == 0) {
305  digit = play_and_wait(chan, "dictate/paused", AST_DIGIT_ANY);
306  } else if (digit < 0) {
307  break;
308  }
309  }
310  lastop = DMODE_RECORD;
311  ast_closestream(fs);
312  if ( ast_test_flag(&flags, DFLAG_TRUNC)) {
313  oflags |= O_TRUNC;
314  digit = play_and_wait(chan, "dictate/truncating_audio", AST_DIGIT_ANY);
315  } else {
316  oflags |= O_APPEND;
317  }
318  fs = ast_writefile(path, "raw", NULL, oflags, 0, AST_FILE_MODE);
319  if (ast_test_flag(&flags, DFLAG_TRUNC)) {
320  ast_seekstream(fs, 0, SEEK_SET);
321  ast_clear_flag(&flags, DFLAG_TRUNC);
322  } else {
323  ast_seekstream(fs, 0, SEEK_END);
324  }
325  }
326  if (!ast_test_flag(&flags, DFLAG_PAUSE)) {
327  res = ast_writestream(fs, f);
328  }
329  break;
330  }
331 
332  }
333 
334  ast_frfree(f);
335  }
336  }
337  if (oldr) {
338  ast_set_read_format(chan, oldr);
339  }
340  return 0;
341 }
int ast_safe_sleep(struct ast_channel *chan, int ms)
Wait for a specified amount of time, looking for hangups.
Definition: channel.c:1916
union ast_frame_subclass subclass
Definition: frame.h:146
int ast_app_getdata(struct ast_channel *c, const char *prompt, char *s, int maxlen, int timeout)
Plays a stream and gets DTMF data from a channel.
Definition: app.c:178
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: utils.h:653
#define AST_DIGIT_ANY
Definition: file.h:47
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define ast_toggle_flag(it, flag)
Definition: app_dictate.c:77
#define ast_set_flag(p, flag)
Definition: utils.h:70
#define LOG_WARNING
Definition: logger.h:144
#define AST_FRAME_DTMF
Definition: frame.h:128
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
Definition: app.h:572
unsigned int flags
Definition: utils.h:201
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4383
#define AST_FILE_MODE
Definition: asterisk.h:36
int ast_set_read_format(struct ast_channel *chan, format_t format)
Sets read format on channel chan Set read format for channel to whichever component of &quot;format&quot; is be...
Definition: channel.c:5301
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
int ast_queue_frame(struct ast_channel *chan, struct ast_frame *f)
Queue one or more frames to a channel&#39;s frame queue.
Definition: channel.c:1558
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
static int play_and_wait(struct ast_channel *chan, char *file, char *digits)
Definition: app_dictate.c:79
static struct @350 args
struct ast_frame * ast_readframe(struct ast_filestream *s)
Read a frame from a filestream.
Definition: file.c:737
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
enum ast_channel_state _state
Definition: channel.h:839
struct ast_filestream * ast_writefile(const char *filename, const char *type, const char *comment, int flags, int check, mode_t mode)
Starts writing a file.
Definition: file.c:1049
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
int ast_seekstream(struct ast_filestream *fs, off_t sample_offset, int whence)
Seeks into stream.
Definition: file.c:879
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1858
int ast_closestream(struct ast_filestream *f)
Closes a stream.
Definition: file.c:904
static struct ast_format f[]
Definition: format_g726.c:181
int ast_write(struct ast_channel *chan, struct ast_frame *frame)
Write a frame to a channel This function writes the given frame to the indicated channel.
Definition: channel.c:4916
const char * ast_config_AST_SPOOL_DIR
Definition: asterisk.c:259
Structure used to handle boolean flags.
Definition: utils.h:200
#define ast_clear_flag(p, flag)
Definition: utils.h:77
This structure is allocated by file.c in one chunk, together with buf_size and desc_size bytes of mem...
Definition: mod_format.h:100
#define AST_FORMAT_SLINEAR
Definition: frame.h:254
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition: channel.c:3539
int ast_say_number(struct ast_channel *chan, int num, const char *ints, const char *lang, const char *options)
says a number
Definition: channel.c:8397
format_t readformat
Definition: channel.h:853
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
int ast_writestream(struct ast_filestream *fs, struct ast_frame *f)
Writes a frame to a stream.
Definition: file.c:150
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:3086
Data structure associated with a single frame of data.
Definition: frame.h:142
#define AST_APP_ARG(name)
Define an application argument.
Definition: app.h:555
enum ast_frame_type frametype
Definition: frame.h:144
#define ast_frfree(fr)
Definition: frame.h:583
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
Definition: app.h:604
struct ast_filestream * stream
Definition: channel.h:757
union ast_frame::@172 data
const ast_string_field language
Definition: channel.h:787
struct ast_filestream * ast_openstream(struct ast_channel *chan, const char *filename, const char *preflang)
Opens stream for use in seeking, playing.
Definition: file.c:636
int samples
Definition: frame.h:150
int ast_mkdir(const char *path, int mode)
Recursively create directory path.
Definition: utils.c:2151
static int load_module ( void  )
static

Definition at line 350 of file app_dictate.c.

References ast_register_application_xml, and dictate_exec().

351 {
353 }
static const char app[]
Definition: app_dictate.c:62
static int dictate_exec(struct ast_channel *chan, const char *data)
Definition: app_dictate.c:88
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:437
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(), ast_waitstream(), and ast_channel::language.

Referenced by dictate_exec().

80 {
81  int res = -1;
82  if (!ast_streamfile(chan, file, chan->language)) {
83  res = ast_waitstream(chan, digits);
84  }
85  return res;
86 }
int ast_streamfile(struct ast_channel *c, const char *filename, const char *preflang)
Streams a file.
Definition: file.c:946
int ast_waitstream(struct ast_channel *c, const char *breakon)
Waits for a stream to stop or digit to be pressed.
Definition: file.c:1343
const ast_string_field language
Definition: channel.h:787
static int unload_module ( void  )
static

Definition at line 343 of file app_dictate.c.

References ast_unregister_application().

344 {
345  int res;
347  return res;
348 }
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx.c:7705
static const char app[]
Definition: app_dictate.c:62

Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Virtual Dictation Machine" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, }
static

Definition at line 355 of file app_dictate.c.

const char app[] = "Dictate"
static

Definition at line 62 of file app_dictate.c.

Definition at line 355 of file app_dictate.c.