Asterisk - The Open Source Telephony Project  GIT-master-a24979a
Macros | Enumerations | Functions | Variables
app_record.c File Reference

Trivial application to record a sound file. More...

#include "asterisk.h"
#include "asterisk/file.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/app.h"
#include "asterisk/channel.h"
#include "asterisk/dsp.h"
#include "asterisk/format_cache.h"
#include "asterisk/paths.h"
Include dependency graph for app_record.c:

Go to the source code of this file.

Macros

#define OPERATOR_KEY   '0'
 

Enumerations

enum  {
  OPTION_APPEND = (1 << 0) , OPTION_NOANSWER = (1 << 1) , OPTION_QUIET = (1 << 2) , OPTION_SKIP = (1 << 3) ,
  OPTION_STAR_TERMINATE = (1 << 4) , OPTION_IGNORE_TERMINATE = (1 << 5) , OPTION_KEEP = (1 << 6) , OPTION_ANY_TERMINATE = (1 << 7) ,
  OPTION_OPERATOR_EXIT = (1 << 8) , OPTION_NO_TRUNCATE = (1 << 9)
}
 
enum  dtmf_response { RESPONSE_NO_MATCH = 0 , RESPONSE_OPERATOR , RESPONSE_DTMF }
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
static int create_destination_directory (const char *path)
 
static int load_module (void)
 
static enum dtmf_response record_dtmf_response (struct ast_channel *chan, struct ast_flags *flags, int dtmf_integer, int terminator)
 
static int record_exec (struct ast_channel *chan, const char *data)
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Trivial Record Application" , .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 = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, .support_level = AST_MODULE_SUPPORT_CORE, }
 
static char * app = "Record"
 
static const struct ast_app_option app_opts [128] = { [ 'a' ] = { .flag = OPTION_APPEND }, [ 'k' ] = { .flag = OPTION_KEEP }, [ 'n' ] = { .flag = OPTION_NOANSWER }, [ 'o' ] = { .flag = OPTION_OPERATOR_EXIT }, [ 'q' ] = { .flag = OPTION_QUIET }, [ 's' ] = { .flag = OPTION_SKIP }, [ 't' ] = { .flag = OPTION_STAR_TERMINATE }, [ 'u' ] = { .flag = OPTION_NO_TRUNCATE }, [ 'y' ] = { .flag = OPTION_ANY_TERMINATE }, [ 'x' ] = { .flag = OPTION_IGNORE_TERMINATE }, }
 
static const struct ast_module_infoast_module_info = &__mod_info
 

Detailed Description

Trivial application to record a sound file.

Author
Matthew Fredrickson cresl.nosp@m.in@d.nosp@m.igium.nosp@m..com

Definition in file app_record.c.

Macro Definition Documentation

◆ OPERATOR_KEY

#define OPERATOR_KEY   '0'

Definition at line 123 of file app_record.c.

Enumeration Type Documentation

◆ anonymous enum

anonymous enum
Enumerator
OPTION_APPEND 
OPTION_NOANSWER 
OPTION_QUIET 
OPTION_SKIP 
OPTION_STAR_TERMINATE 
OPTION_IGNORE_TERMINATE 
OPTION_KEEP 
OPTION_ANY_TERMINATE 
OPTION_OPERATOR_EXIT 
OPTION_NO_TRUNCATE 

Definition at line 127 of file app_record.c.

127  {
128  OPTION_APPEND = (1 << 0),
129  OPTION_NOANSWER = (1 << 1),
130  OPTION_QUIET = (1 << 2),
131  OPTION_SKIP = (1 << 3),
132  OPTION_STAR_TERMINATE = (1 << 4),
133  OPTION_IGNORE_TERMINATE = (1 << 5),
134  OPTION_KEEP = (1 << 6),
135  OPTION_ANY_TERMINATE = (1 << 7),
136  OPTION_OPERATOR_EXIT = (1 << 8),
137  OPTION_NO_TRUNCATE = (1 << 9),
138 };
@ OPTION_NOANSWER
Definition: app_record.c:129
@ OPTION_STAR_TERMINATE
Definition: app_record.c:132
@ OPTION_KEEP
Definition: app_record.c:134
@ OPTION_NO_TRUNCATE
Definition: app_record.c:137
@ OPTION_QUIET
Definition: app_record.c:130
@ OPTION_OPERATOR_EXIT
Definition: app_record.c:136
@ OPTION_IGNORE_TERMINATE
Definition: app_record.c:133
@ OPTION_ANY_TERMINATE
Definition: app_record.c:135
@ OPTION_SKIP
Definition: app_record.c:131
@ OPTION_APPEND
Definition: app_record.c:128

◆ dtmf_response

Enumerator
RESPONSE_NO_MATCH 
RESPONSE_OPERATOR 
RESPONSE_DTMF 

Definition at line 140 of file app_record.c.

140  {
141  RESPONSE_NO_MATCH = 0,
144 };
@ RESPONSE_OPERATOR
Definition: app_record.c:142
@ RESPONSE_DTMF
Definition: app_record.c:143
@ RESPONSE_NO_MATCH
Definition: app_record.c:141

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 543 of file app_record.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 543 of file app_record.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module* AST_MODULE_SELF_SYM ( void  )

Definition at line 543 of file app_record.c.

◆ create_destination_directory()

static int create_destination_directory ( const char *  path)
static

Definition at line 187 of file app_record.c.

188 {
189  int res;
190  char directory[PATH_MAX], *file_sep;
191 
192  if (!(file_sep = strrchr(path, '/'))) {
193  /* No directory to create */
194  return 0;
195  }
196 
197  /* Overwrite temporarily */
198  *file_sep = '\0';
199 
200  /* Absolute path? */
201  if (path[0] == '/') {
202  res = ast_mkdir(path, 0777);
203  *file_sep = '/';
204  return res;
205  }
206 
207  /* Relative path */
208  res = snprintf(directory, sizeof(directory), "%s/sounds/%s",
210 
211  *file_sep = '/';
212 
213  if (res >= sizeof(directory)) {
214  /* We truncated, so we fail */
215  return -1;
216  }
217 
218  return ast_mkdir(directory, 0777);
219 }
#define PATH_MAX
Definition: asterisk.h:40
const char * ast_config_AST_DATA_DIR
Definition: options.c:158
int ast_mkdir(const char *path, int mode)
Recursively create directory path.
Definition: main/utils.c:2377

References ast_config_AST_DATA_DIR, ast_mkdir(), and PATH_MAX.

Referenced by record_exec().

◆ load_module()

static int load_module ( void  )
static

Definition at line 538 of file app_record.c.

539 {
541 }
static int record_exec(struct ast_channel *chan, const char *data)
Definition: app_record.c:221
static char * app
Definition: app_record.c:125
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:626

◆ record_dtmf_response()

static enum dtmf_response record_dtmf_response ( struct ast_channel chan,
struct ast_flags flags,
int  dtmf_integer,
int  terminator 
)
static

Definition at line 125 of file app_record.c.

173 {
174  if ((dtmf_integer == OPERATOR_KEY) &&
176  return RESPONSE_OPERATOR;
177  }
178 
179  if ((dtmf_integer == terminator) ||
181  return RESPONSE_DTMF;
182  }
183 
184  return RESPONSE_NO_MATCH;
185 }
#define OPERATOR_KEY
Definition: app_record.c:123
#define ast_test_flag(p, flag)
Definition: utils.h:63

Referenced by record_exec().

◆ record_exec()

static int record_exec ( struct ast_channel chan,
const char *  data 
)
static

Definition at line 221 of file app_record.c.

222 {
223  int res = 0;
224  char *ext = NULL, *opts[0];
225  char *parse;
226  int i = 0;
227  char tmp[PATH_MAX];
228 
229  struct ast_filestream *s = NULL;
230  struct ast_frame *f = NULL;
231 
232  struct ast_dsp *sildet = NULL; /* silence detector dsp */
233  int totalsilence = 0;
234  int dspsilence = 0;
235  int silence = 0; /* amount of silence to allow */
236  int gotsilence = 0; /* did we timeout for silence? */
237  int truncate_silence = 1; /* truncate on complete silence recording */
238  int maxduration = 0; /* max duration of recording in milliseconds */
239  int gottimeout = 0; /* did we timeout for maxduration exceeded? */
240  int terminator = '#';
241  RAII_VAR(struct ast_format *, rfmt, NULL, ao2_cleanup);
242  int ioflags;
243  struct ast_silence_generator *silgen = NULL;
244  struct ast_flags flags = { 0, };
246  AST_APP_ARG(filename);
247  AST_APP_ARG(silence);
248  AST_APP_ARG(maxduration);
250  );
251  int ms;
252  struct timeval start;
253  const char *status_response = "ERROR";
254 
255  /* The next few lines of code parse out the filename and header from the input string */
256  if (ast_strlen_zero(data)) { /* no data implies no filename or anything is present */
257  ast_log(LOG_WARNING, "Record requires an argument (filename)\n");
258  pbx_builtin_setvar_helper(chan, "RECORD_STATUS", "ERROR");
259  return -1;
260  }
261 
262  parse = ast_strdupa(data);
264  if (args.argc == 4)
265  ast_app_parse_options(app_opts, &flags, opts, args.options);
266 
267  if (!ast_strlen_zero(args.filename)) {
268  ext = strrchr(args.filename, '.'); /* to support filename with a . in the filename, not format */
269  if (!ext)
270  ext = strchr(args.filename, ':');
271  if (ext) {
272  *ext = '\0';
273  ext++;
274  }
275  }
276  if (!ext) {
277  ast_log(LOG_WARNING, "No extension specified to filename!\n");
278  pbx_builtin_setvar_helper(chan, "RECORD_STATUS", "ERROR");
279  return -1;
280  }
281  if (args.silence) {
282  if ((sscanf(args.silence, "%30d", &i) == 1) && (i > -1)) {
283  silence = i * 1000;
284  } else if (!ast_strlen_zero(args.silence)) {
285  ast_log(LOG_WARNING, "'%s' is not a valid silence duration\n", args.silence);
286  }
287  }
288 
289  if (ast_test_flag(&flags, OPTION_NO_TRUNCATE))
290  truncate_silence = 0;
291 
292  if (args.maxduration) {
293  if ((sscanf(args.maxduration, "%30d", &i) == 1) && (i > -1))
294  /* Convert duration to milliseconds */
295  maxduration = i * 1000;
296  else if (!ast_strlen_zero(args.maxduration))
297  ast_log(LOG_WARNING, "'%s' is not a valid maximum duration\n", args.maxduration);
298  }
299 
301  terminator = '*';
303  terminator = '\0';
304 
305  /*
306  If a '%d' is specified as part of the filename, we replace that token with
307  sequentially incrementing numbers until we find a unique filename.
308  */
309  if (strchr(args.filename, '%')) {
310  size_t src, dst, count = 0;
311  size_t src_len = strlen(args.filename);
312  size_t dst_len = sizeof(tmp) - 1;
313 
314  do {
315  for (src = 0, dst = 0; src < src_len && dst < dst_len; src++) {
316  if (!strncmp(&args.filename[src], "%d", 2)) {
317  int s = snprintf(&tmp[dst], PATH_MAX - dst, "%zu", count);
318  if (s >= PATH_MAX - dst) {
319  /* We truncated, so we need to bail */
320  ast_log(LOG_WARNING, "Failed to create unique filename from template: %s\n", args.filename);
321  pbx_builtin_setvar_helper(chan, "RECORD_STATUS", "ERROR");
322  return -1;
323  }
324  dst += s;
325  src++;
326  } else {
327  tmp[dst] = args.filename[src];
328  tmp[++dst] = '\0';
329  }
330  }
331  count++;
332  } while (ast_fileexists(tmp, ext, ast_channel_language(chan)) > 0);
333  } else
334  ast_copy_string(tmp, args.filename, sizeof(tmp));
335 
336  pbx_builtin_setvar_helper(chan, "RECORDED_FILE", tmp);
337 
338  if (ast_channel_state(chan) != AST_STATE_UP) {
339  if (ast_test_flag(&flags, OPTION_SKIP)) {
340  /* At the user's option, skip if the line is not up */
341  pbx_builtin_setvar_helper(chan, "RECORD_STATUS", "SKIP");
342  return 0;
343  } else if (!ast_test_flag(&flags, OPTION_NOANSWER)) {
344  /* Otherwise answer unless we're supposed to record while on-hook */
345  res = ast_answer(chan);
346  }
347  }
348 
349  if (res) {
350  ast_log(LOG_WARNING, "Could not answer channel '%s'\n", ast_channel_name(chan));
351  status_response = "ERROR";
352  goto out;
353  }
354 
355  if (!ast_test_flag(&flags, OPTION_QUIET)) {
356  /* Some code to play a nice little beep to signify the start of the record operation */
357  res = ast_streamfile(chan, "beep", ast_channel_language(chan));
358  if (!res) {
359  res = ast_waitstream(chan, "");
360  } else {
361  ast_log(LOG_WARNING, "ast_streamfile(beep) failed on %s\n", ast_channel_name(chan));
362  res = 0;
363  }
364  ast_stopstream(chan);
365  }
366 
367  /* The end of beep code. Now the recording starts */
368 
369  if (silence > 0) {
370  rfmt = ao2_bump(ast_channel_readformat(chan));
372  if (res < 0) {
373  ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n");
374  pbx_builtin_setvar_helper(chan, "RECORD_STATUS", "ERROR");
375  return -1;
376  }
377  sildet = ast_dsp_new();
378  if (!sildet) {
379  ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
380  pbx_builtin_setvar_helper(chan, "RECORD_STATUS", "ERROR");
381  return -1;
382  }
384  }
385 
387  ast_log(LOG_WARNING, "Could not create directory for file %s\n", args.filename);
388  status_response = "ERROR";
389  goto out;
390  }
391 
392  ioflags = ast_test_flag(&flags, OPTION_APPEND) ? O_CREAT|O_APPEND|O_WRONLY : O_CREAT|O_TRUNC|O_WRONLY;
393  s = ast_writefile(tmp, ext, NULL, ioflags, 0, AST_FILE_MODE);
394 
395  if (!s) {
396  ast_log(LOG_WARNING, "Could not create file %s\n", args.filename);
397  status_response = "ERROR";
398  goto out;
399  }
400 
403 
404  /* Request a video update */
406 
407  if (maxduration <= 0)
408  maxduration = -1;
409 
410  start = ast_tvnow();
411  while ((ms = ast_remaining_ms(start, maxduration))) {
412  ms = ast_waitfor(chan, ms);
413  if (ms < 0) {
414  break;
415  }
416 
417  if (maxduration > 0 && ms == 0) {
418  break;
419  }
420 
421  f = ast_read(chan);
422  if (!f) {
423  res = -1;
424  break;
425  }
426  if (f->frametype == AST_FRAME_VOICE) {
427  res = ast_writestream(s, f);
428 
429  if (res) {
430  ast_log(LOG_WARNING, "Problem writing frame\n");
431  ast_frfree(f);
432  status_response = "ERROR";
433  break;
434  }
435 
436  if (silence > 0) {
437  dspsilence = 0;
438  ast_dsp_silence(sildet, f, &dspsilence);
439  if (dspsilence) {
440  totalsilence = dspsilence;
441  } else {
442  totalsilence = 0;
443  }
444  if (totalsilence > silence) {
445  /* Ended happily with silence */
446  ast_frfree(f);
447  gotsilence = 1;
448  status_response = "SILENCE";
449  break;
450  }
451  }
452  } else if (f->frametype == AST_FRAME_VIDEO) {
453  res = ast_writestream(s, f);
454 
455  if (res) {
456  ast_log(LOG_WARNING, "Problem writing frame\n");
457  status_response = "ERROR";
458  ast_frfree(f);
459  break;
460  }
461  } else if (f->frametype == AST_FRAME_DTMF) {
462  enum dtmf_response rc =
463  record_dtmf_response(chan, &flags, f->subclass.integer, terminator);
464  switch(rc) {
465  case RESPONSE_NO_MATCH:
466  break;
467  case RESPONSE_OPERATOR:
468  status_response = "OPERATOR";
469  ast_debug(1, "Got OPERATOR\n");
470  break;
471  case RESPONSE_DTMF:
472  status_response = "DTMF";
473  ast_debug(1, "Got DTMF\n");
474  break;
475  }
476  if (rc != RESPONSE_NO_MATCH) {
477  ast_frfree(f);
478  break;
479  }
480  }
481  ast_frfree(f);
482  }
483 
484  if (maxduration > 0 && !ms) {
485  gottimeout = 1;
486  status_response = "TIMEOUT";
487  }
488 
489  if (!f) {
490  ast_debug(1, "Got hangup\n");
491  res = -1;
492  status_response = "HANGUP";
493  if (!ast_test_flag(&flags, OPTION_KEEP)) {
494  ast_filedelete(args.filename, NULL);
495  }
496  }
497 
498  if (gotsilence && truncate_silence) {
499  ast_stream_rewind(s, silence - 1000);
500  ast_truncstream(s);
501  } else if (!gottimeout && f) {
502  /*
503  * Strip off the last 1/4 second of it, if we didn't end because of a timeout,
504  * or a hangup. This must mean we ended because of a DTMF tone and while this
505  * 1/4 second stripping is very old code the most likely explanation is that it
506  * relates to stripping a partial DTMF tone.
507  */
508  ast_stream_rewind(s, 250);
509  ast_truncstream(s);
510  }
511  ast_closestream(s);
512 
513  if (silgen)
515 
516 out:
517  if ((silence > 0) && rfmt) {
518  res = ast_set_read_format(chan, rfmt);
519  if (res) {
520  ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", ast_channel_name(chan));
521  }
522  }
523 
524  if (sildet) {
525  ast_dsp_free(sildet);
526  }
527 
528  pbx_builtin_setvar_helper(chan, "RECORD_STATUS", status_response);
529 
530  return res;
531 }
static enum dtmf_response record_dtmf_response(struct ast_channel *chan, struct ast_flags *flags, int dtmf_integer, int terminator)
Definition: app_record.c:171
static int create_destination_directory(const char *path)
Definition: app_record.c:187
static const struct ast_app_option app_opts[128]
Definition: app_record.c:157
dtmf_response
Definition: app_record.c:140
#define AST_FILE_MODE
Definition: asterisk.h:32
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
#define ast_log
Definition: astobj2.c:42
#define ao2_cleanup(obj)
Definition: astobj2.h:1934
#define ao2_bump(obj)
Bump refcount on an AO2 object by one, returning the object.
Definition: astobj2.h:480
static int tmp()
Definition: bt_open.c:389
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1844
struct ast_silence_generator * ast_channel_start_silence_generator(struct ast_channel *chan)
Starts a silence generator on the given channel.
Definition: channel.c:8247
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition: channel.c:3163
void ast_channel_stop_silence_generator(struct ast_channel *chan, struct ast_silence_generator *state)
Stops a previously-started silence generator on the given channel.
Definition: channel.c:8293
const char * ast_channel_name(const struct ast_channel *chan)
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4292
int ast_set_read_format(struct ast_channel *chan, struct ast_format *format)
Sets read format on channel chan.
Definition: channel.c:5839
const char * ast_channel_language(const struct ast_channel *chan)
struct ast_format * ast_channel_readformat(struct ast_channel *chan)
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:2806
int ast_indicate(struct ast_channel *chan, int condition)
Indicates condition of channel.
Definition: channel.c:4312
ast_channel_state
ast_channel states
Definition: channelstate.h:35
@ AST_STATE_UP
Definition: channelstate.h:42
void ast_dsp_set_threshold(struct ast_dsp *dsp, int threshold)
Set the minimum average magnitude threshold to determine talking by the DSP.
Definition: dsp.c:1778
void ast_dsp_free(struct ast_dsp *dsp)
Definition: dsp.c:1773
struct ast_dsp * ast_dsp_new(void)
Allocates a new dsp, assumes 8khz for internal sample rate.
Definition: dsp.c:1748
@ THRESHOLD_SILENCE
Definition: dsp.h:73
int ast_dsp_silence(struct ast_dsp *dsp, struct ast_frame *f, int *totalsilence)
Process the audio frame for silence.
Definition: dsp.c:1486
int ast_dsp_get_threshold_from_settings(enum threshold which)
Get silence threshold from dsp.conf.
Definition: dsp.c:1999
int ast_stopstream(struct ast_channel *c)
Stops a stream.
Definition: file.c:222
int ast_writestream(struct ast_filestream *fs, struct ast_frame *f)
Writes a frame to a stream.
Definition: file.c:244
int ast_stream_rewind(struct ast_filestream *fs, off_t ms)
Rewind stream ms.
Definition: file.c:1098
int ast_streamfile(struct ast_channel *c, const char *filename, const char *preflang)
Streams a file.
Definition: file.c:1291
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:1402
int ast_truncstream(struct ast_filestream *fs)
Trunc stream at current location.
Definition: file.c:1078
int ast_closestream(struct ast_filestream *f)
Closes a stream.
Definition: file.c:1109
int ast_fileexists(const char *filename, const char *fmt, const char *preflang)
Checks for the existence of a given file.
Definition: file.c:1127
int ast_filedelete(const char *filename, const char *fmt)
Deletes a file.
Definition: file.c:1139
int ast_waitstream(struct ast_channel *c, const char *breakon)
Waits for a stream to stop or digit to be pressed.
Definition: file.c:1817
struct ast_format * ast_format_slin
Built-in cached signed linear 8kHz format.
Definition: format_cache.c:41
const char * ext
Definition: http.c:150
#define AST_APP_ARG(name)
Define an application argument.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the 'standard' argument separation process for an application.
int ast_app_parse_options(const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr)
Parses a string containing application options and sets flags/arguments.
Definition: main/app.c:3126
#define AST_FRAME_DTMF
#define ast_frfree(fr)
@ AST_FRAME_VIDEO
@ AST_FRAME_VOICE
@ AST_CONTROL_VIDUPDATE
#define ast_debug(level,...)
Log a DEBUG message.
#define LOG_WARNING
#define ast_opt_transmit_silence
Definition: options.h:124
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name.
#define NULL
Definition: resample.c:96
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:406
Definition: dsp.c:407
int totalsilence
Definition: dsp.c:411
This structure is allocated by file.c in one chunk, together with buf_size and desc_size bytes of mem...
Definition: mod_format.h:101
Structure used to handle boolean flags.
Definition: utils.h:199
unsigned int flags
Definition: utils.h:200
Definition of a media format.
Definition: format.c:43
Data structure associated with a single frame of data.
struct ast_frame_subclass subclass
enum ast_frame_type frametype
const char * args
static struct test_options options
int ast_remaining_ms(struct timeval start, int max_ms)
Calculate remaining milliseconds given a starting timestamp and upper bound.
Definition: main/utils.c:2179
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:157
FILE * out
Definition: utils/frame.c:33
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:936

References ao2_bump, ao2_cleanup, app_opts, args, ast_answer(), AST_APP_ARG, ast_app_parse_options(), ast_channel_language(), ast_channel_name(), ast_channel_readformat(), ast_channel_start_silence_generator(), ast_channel_stop_silence_generator(), ast_closestream(), AST_CONTROL_VIDUPDATE, ast_copy_string(), ast_debug, AST_DECLARE_APP_ARGS, ast_dsp_free(), ast_dsp_get_threshold_from_settings(), ast_dsp_new(), ast_dsp_set_threshold(), ast_dsp_silence(), AST_FILE_MODE, ast_filedelete(), ast_fileexists(), ast_format_slin, AST_FRAME_DTMF, AST_FRAME_VIDEO, AST_FRAME_VOICE, ast_frfree, ast_indicate(), ast_log, ast_opt_transmit_silence, ast_read(), ast_remaining_ms(), ast_set_read_format(), AST_STANDARD_APP_ARGS, AST_STATE_UP, ast_stopstream(), ast_strdupa, ast_stream_rewind(), ast_streamfile(), ast_strlen_zero(), ast_test_flag, ast_truncstream(), ast_tvnow(), ast_waitfor(), ast_waitstream(), ast_writefile(), ast_writestream(), create_destination_directory(), ext, ast_flags::flags, ast_frame::frametype, ast_frame_subclass::integer, LOG_WARNING, NULL, OPTION_APPEND, OPTION_IGNORE_TERMINATE, OPTION_KEEP, OPTION_NO_TRUNCATE, OPTION_NOANSWER, OPTION_QUIET, OPTION_SKIP, OPTION_STAR_TERMINATE, options, out, parse(), PATH_MAX, pbx_builtin_setvar_helper(), RAII_VAR, record_dtmf_response(), RESPONSE_DTMF, RESPONSE_NO_MATCH, RESPONSE_OPERATOR, ast_frame::subclass, THRESHOLD_SILENCE, tmp(), and ast_dsp::totalsilence.

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 533 of file app_record.c.

534 {
536 }
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx_app.c:392

References app, and ast_unregister_application().

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Trivial Record Application" , .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 = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, .support_level = AST_MODULE_SUPPORT_CORE, }
static

Definition at line 538 of file app_record.c.

◆ app

char* app = "Record"
static

Definition at line 125 of file app_record.c.

Referenced by unload_module().

◆ app_opts

const struct ast_app_option app_opts[128] = { [ 'a' ] = { .flag = OPTION_APPEND }, [ 'k' ] = { .flag = OPTION_KEEP }, [ 'n' ] = { .flag = OPTION_NOANSWER }, [ 'o' ] = { .flag = OPTION_OPERATOR_EXIT }, [ 'q' ] = { .flag = OPTION_QUIET }, [ 's' ] = { .flag = OPTION_SKIP }, [ 't' ] = { .flag = OPTION_STAR_TERMINATE }, [ 'u' ] = { .flag = OPTION_NO_TRUNCATE }, [ 'y' ] = { .flag = OPTION_ANY_TERMINATE }, [ 'x' ] = { .flag = OPTION_IGNORE_TERMINATE }, }
static

Definition at line 125 of file app_record.c.

Referenced by record_exec().

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 543 of file app_record.c.