Asterisk - The Open Source Telephony Project GIT-master-4522eb1
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros Modules Pages
app_record.c
Go to the documentation of this file.
1/*
2 * Asterisk -- An open source telephony toolkit.
3 *
4 * Copyright (C) 1999 - 2005, Digium, Inc.
5 *
6 * Matthew Fredrickson <creslin@digium.com>
7 *
8 * See http://www.asterisk.org for more information about
9 * the Asterisk project. Please do not directly contact
10 * any of the maintainers of this project for assistance;
11 * the project provides a web site, mailing lists and IRC
12 * channels for your use.
13 *
14 * This program is free software, distributed under the terms of
15 * the GNU General Public License Version 2. See the LICENSE file
16 * at the top of the source tree.
17 */
18
19/*! \file
20 *
21 * \brief Trivial application to record a sound file
22 *
23 * \author Matthew Fredrickson <creslin@digium.com>
24 *
25 * \ingroup applications
26 */
27
28/*** MODULEINFO
29 <support_level>core</support_level>
30 ***/
31
32#include "asterisk.h"
33
34#include "asterisk/file.h"
35#include "asterisk/pbx.h"
36#include "asterisk/module.h"
37#include "asterisk/app.h"
38#include "asterisk/channel.h"
39#include "asterisk/dsp.h" /* use dsp routines for silence detection */
41#include "asterisk/paths.h"
42
43/*** DOCUMENTATION
44 <application name="Record" language="en_US">
45 <since>
46 <version>0.1.8</version>
47 </since>
48 <synopsis>
49 Record to a file.
50 </synopsis>
51 <syntax>
52 <parameter name="filename" required="true" argsep=".">
53 <argument name="filename" required="true" />
54 <argument name="format" required="true">
55 <para>Is the format of the file type to be recorded (wav, gsm, etc).</para>
56 </argument>
57 </parameter>
58 <parameter name="silence">
59 <para>Is the number of seconds of silence to allow before returning.</para>
60 </parameter>
61 <parameter name="maxduration">
62 <para>Is the maximum recording duration in seconds. If missing
63 or 0 there is no maximum.</para>
64 </parameter>
65 <parameter name="options">
66 <optionlist>
67 <option name="a">
68 <para>Append to existing recording rather than replacing.</para>
69 </option>
70 <option name="n">
71 <para>Do not answer, but record anyway if line not yet answered.</para>
72 </option>
73 <option name="o">
74 <para>Exit when 0 is pressed, setting the variable <variable>RECORD_STATUS</variable>
75 to <literal>OPERATOR</literal> instead of <literal>DTMF</literal></para>
76 </option>
77 <option name="q">
78 <para>quiet (do not play a beep tone).</para>
79 </option>
80 <option name="s">
81 <para>skip recording if the line is not yet answered.</para>
82 </option>
83 <option name="t">
84 <para>use alternate '*' terminator key (DTMF) instead of default '#'</para>
85 </option>
86 <option name="u">
87 <para>Don't truncate recorded silence.</para>
88 </option>
89 <option name="x">
90 <para>Ignore all terminator keys (DTMF) and keep recording until hangup.</para>
91 </option>
92 <option name="k">
93 <para>Keep recorded file upon hangup.</para>
94 </option>
95 <option name="y">
96 <para>Terminate recording if *any* DTMF digit is received.</para>
97 </option>
98 </optionlist>
99 </parameter>
100 </syntax>
101 <description>
102 <para>If filename contains <literal>%d</literal>, these characters will be replaced with a number
103 incremented by one each time the file is recorded.
104 Use <astcli>core show file formats</astcli> to see the available formats on your system
105 User can press <literal>#</literal> to terminate the recording and continue to the next priority.
106 If the user hangs up during a recording, all data will be lost and the application will terminate.</para>
107 <variablelist>
108 <variable name="RECORDED_FILE">
109 <para>Will be set to the final filename of the recording, without an extension.</para>
110 </variable>
111 <variable name="RECORD_STATUS">
112 <para>This is the final status of the command</para>
113 <value name="DTMF">A terminating DTMF was received ('#' or '*', depending upon option 't')</value>
114 <value name="SILENCE">The maximum silence occurred in the recording.</value>
115 <value name="SKIP">The line was not yet answered and the 's' option was specified.</value>
116 <value name="TIMEOUT">The maximum length was reached.</value>
117 <value name="HANGUP">The channel was hung up.</value>
118 <value name="ERROR">An unrecoverable error occurred, which resulted in a WARNING to the logs.</value>
119 </variable>
120 </variablelist>
121 </description>
122 <see-also>
123 <ref type="function">RECORDING_INFO</ref>
124 </see-also>
125 </application>
126 <function name="RECORDING_INFO" language="en_US">
127 <synopsis>
128 Retrieve information about a recording previously created using the Record application
129 </synopsis>
130 <syntax>
131 <parameter name="property" required="true">
132 <para>The property about the recording to retrieve.</para>
133 <enumlist>
134 <enum name="duration">
135 <para>The duration, in milliseconds, of the recording.</para>
136 </enum>
137 </enumlist>
138 </parameter>
139 </syntax>
140 <description>
141 <para>Returns information about the previous recording created by <literal>Record</literal>.
142 This function cannot be used if no recordings have yet been completed.</para>
143 </description>
144 <see-also>
145 <ref type="application">Record</ref>
146 </see-also>
147 </function>
148 ***/
149
150#define OPERATOR_KEY '0'
151
152static char *app = "Record";
153
154enum {
155 OPTION_APPEND = (1 << 0),
156 OPTION_NOANSWER = (1 << 1),
157 OPTION_QUIET = (1 << 2),
158 OPTION_SKIP = (1 << 3),
161 OPTION_KEEP = (1 << 6),
165};
166
171};
172
184});
185
186/*!
187 * \internal
188 * \brief Used to determine what action to take when DTMF is received while recording
189 * \since 13.0.0
190 *
191 * \param chan channel being recorded
192 * \param flags option flags in use by the record application
193 * \param dtmf_integer the integer value of the DTMF key received
194 * \param terminator key currently set to be pressed for normal termination
195 *
196 * \returns One of enum dtmf_response
197 */
199 struct ast_flags *flags, int dtmf_integer, int terminator)
200{
201 if ((dtmf_integer == OPERATOR_KEY) &&
203 return RESPONSE_OPERATOR;
204 }
205
206 if ((dtmf_integer == terminator) ||
208 return RESPONSE_DTMF;
209 }
210
211 return RESPONSE_NO_MATCH;
212}
213
214static int create_destination_directory(const char *path)
215{
216 int res;
217 char directory[PATH_MAX], *file_sep;
218
219 if (!(file_sep = strrchr(path, '/'))) {
220 /* No directory to create */
221 return 0;
222 }
223
224 /* Overwrite temporarily */
225 *file_sep = '\0';
226
227 /* Absolute path? */
228 if (path[0] == '/') {
229 res = ast_mkdir(path, 0777);
230 *file_sep = '/';
231 return res;
232 }
233
234 /* Relative path */
235 res = snprintf(directory, sizeof(directory), "%s/sounds/%s",
237
238 *file_sep = '/';
239
240 if (res >= sizeof(directory)) {
241 /* We truncated, so we fail */
242 return -1;
243 }
244
245 return ast_mkdir(directory, 0777);
246}
247
249 unsigned long duration; /* Duration, in ms */
250};
251
252static void recording_data_free(void *data)
253{
254 ast_free(data);
255}
256
258 .type = "RECORDING_INFO",
259 .destroy = recording_data_free,
260};
261
262static int recording_info_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
263{
264 struct ast_datastore *ds;
265 struct recording_data *recdata;
266
267 *buf = '\0';
268
269 if (!chan) {
270 ast_log(LOG_ERROR, "%s() can only be executed on a channel\n", cmd);
271 return -1;
272 } else if (ast_strlen_zero(data)) {
273 ast_log(LOG_ERROR, "%s() requires an argument\n", cmd);
274 return -1;
275 }
276
277 ast_channel_lock(chan);
279 ast_channel_unlock(chan);
280
281 if (!ds) {
282 ast_log(LOG_ERROR, "No recordings have completed on channel %s\n", ast_channel_name(chan));
283 return -1;
284 }
285
286 recdata = ds->data;
287
288 if (!strcasecmp(data, "duration")) {
289 snprintf(buf, len, "%ld", recdata->duration);
290 } else {
291 ast_log(LOG_ERROR, "Invalid property type: %s\n", data);
292 return -1;
293 }
294
295 return 0;
296}
297
298static int record_exec(struct ast_channel *chan, const char *data)
299{
300 struct ast_datastore *ds;
301 int res = 0;
302 char *ext = NULL, *opts[0];
303 char *parse;
304 int i = 0;
305 char tmp[PATH_MAX];
306 struct recording_data *recdata;
307
308 struct ast_filestream *s = NULL;
309 struct ast_frame *f = NULL;
310
311 struct ast_dsp *sildet = NULL; /* silence detector dsp */
312 int totalsilence = 0;
313 int dspsilence = 0;
314 int silence = 0; /* amount of silence to allow */
315 int gotsilence = 0; /* did we timeout for silence? */
316 int truncate_silence = 1; /* truncate on complete silence recording */
317 int maxduration = 0; /* max duration of recording in milliseconds */
318 int gottimeout = 0; /* did we timeout for maxduration exceeded? */
319 int terminator = '#';
320 RAII_VAR(struct ast_format *, rfmt, NULL, ao2_cleanup);
321 int ioflags;
322 struct ast_silence_generator *silgen = NULL;
323 struct ast_flags flags = { 0, };
325 AST_APP_ARG(filename);
326 AST_APP_ARG(silence);
327 AST_APP_ARG(maxduration);
329 );
330 int ms;
331 struct timeval start;
332 const char *status_response = "ERROR";
333
334 /* Retrieve or create the datastore */
335 ast_channel_lock(chan);
338 ast_log(LOG_ERROR, "Unable to allocate new datastore.\n");
339 ast_channel_unlock(chan);
340 return -1;
341 }
342
343 if (!(recdata = ast_calloc(1, sizeof(*recdata)))) {
345 ast_channel_unlock(chan);
346 return -1;
347 }
348
349 ds->data = recdata;
351 } else {
352 recdata = ds->data;
353 }
354 ast_channel_unlock(chan);
355
356 /* Reset, in case already set */
357 recdata->duration = 0;
358
359 /* The next few lines of code parse out the filename and header from the input string */
360 if (ast_strlen_zero(data)) { /* no data implies no filename or anything is present */
361 ast_log(LOG_WARNING, "Record requires an argument (filename)\n");
362 pbx_builtin_setvar_helper(chan, "RECORD_STATUS", "ERROR");
363 return -1;
364 }
365
366 parse = ast_strdupa(data);
368 if (args.argc == 4)
369 ast_app_parse_options(app_opts, &flags, opts, args.options);
370
371 if (!ast_strlen_zero(args.filename)) {
372 ext = strrchr(args.filename, '.'); /* to support filename with a . in the filename, not format */
373 if (!ext)
374 ext = strchr(args.filename, ':');
375 if (ext) {
376 *ext = '\0';
377 ext++;
378 }
379 }
380 if (!ext) {
381 ast_log(LOG_WARNING, "No extension specified to filename!\n");
382 pbx_builtin_setvar_helper(chan, "RECORD_STATUS", "ERROR");
383 return -1;
384 }
385 if (args.silence) {
386 if ((sscanf(args.silence, "%30d", &i) == 1) && (i > -1)) {
387 silence = i * 1000;
388 } else if (!ast_strlen_zero(args.silence)) {
389 ast_log(LOG_WARNING, "'%s' is not a valid silence duration\n", args.silence);
390 }
391 }
392
394 truncate_silence = 0;
395
396 if (args.maxduration) {
397 if ((sscanf(args.maxduration, "%30d", &i) == 1) && (i > -1))
398 /* Convert duration to milliseconds */
399 maxduration = i * 1000;
400 else if (!ast_strlen_zero(args.maxduration))
401 ast_log(LOG_WARNING, "'%s' is not a valid maximum duration\n", args.maxduration);
402 }
403
405 terminator = '*';
407 terminator = '\0';
408
409 /*
410 If a '%d' is specified as part of the filename, we replace that token with
411 sequentially incrementing numbers until we find a unique filename.
412 */
413 if (strchr(args.filename, '%')) {
414 size_t src, dst, count = 0;
415 size_t src_len = strlen(args.filename);
416 size_t dst_len = sizeof(tmp) - 1;
417
418 do {
419 for (src = 0, dst = 0; src < src_len && dst < dst_len; src++) {
420 if (!strncmp(&args.filename[src], "%d", 2)) {
421 int s = snprintf(&tmp[dst], PATH_MAX - dst, "%zu", count);
422 if (s >= PATH_MAX - dst) {
423 /* We truncated, so we need to bail */
424 ast_log(LOG_WARNING, "Failed to create unique filename from template: %s\n", args.filename);
425 pbx_builtin_setvar_helper(chan, "RECORD_STATUS", "ERROR");
426 return -1;
427 }
428 dst += s;
429 src++;
430 } else {
431 tmp[dst] = args.filename[src];
432 tmp[++dst] = '\0';
433 }
434 }
435 count++;
436 } while (ast_fileexists(tmp, ext, ast_channel_language(chan)) > 0);
437 } else
438 ast_copy_string(tmp, args.filename, sizeof(tmp));
439
440 pbx_builtin_setvar_helper(chan, "RECORDED_FILE", tmp);
441
442 if (ast_channel_state(chan) != AST_STATE_UP) {
443 if (ast_test_flag(&flags, OPTION_SKIP)) {
444 /* At the user's option, skip if the line is not up */
445 pbx_builtin_setvar_helper(chan, "RECORD_STATUS", "SKIP");
446 return 0;
447 } else if (!ast_test_flag(&flags, OPTION_NOANSWER)) {
448 /* Otherwise answer unless we're supposed to record while on-hook */
449 res = ast_answer(chan);
450 }
451 }
452
453 if (res) {
454 ast_log(LOG_WARNING, "Could not answer channel '%s'\n", ast_channel_name(chan));
455 status_response = "ERROR";
456 goto out;
457 }
458
459 if (!ast_test_flag(&flags, OPTION_QUIET)) {
460 /* Some code to play a nice little beep to signify the start of the record operation */
461 res = ast_streamfile(chan, "beep", ast_channel_language(chan));
462 if (!res) {
463 res = ast_waitstream(chan, "");
464 } else {
465 ast_log(LOG_WARNING, "ast_streamfile(beep) failed on %s\n", ast_channel_name(chan));
466 res = 0;
467 }
468 ast_stopstream(chan);
469 }
470
471 /* The end of beep code. Now the recording starts */
472
473 if (silence > 0) {
474 rfmt = ao2_bump(ast_channel_readformat(chan));
476 if (res < 0) {
477 ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n");
478 pbx_builtin_setvar_helper(chan, "RECORD_STATUS", "ERROR");
479 return -1;
480 }
481 sildet = ast_dsp_new();
482 if (!sildet) {
483 ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
484 pbx_builtin_setvar_helper(chan, "RECORD_STATUS", "ERROR");
485 return -1;
486 }
488 }
489
491 ast_log(LOG_WARNING, "Could not create directory for file %s\n", args.filename);
492 status_response = "ERROR";
493 goto out;
494 }
495
496 ioflags = ast_test_flag(&flags, OPTION_APPEND) ? O_CREAT|O_APPEND|O_WRONLY : O_CREAT|O_TRUNC|O_WRONLY;
497 s = ast_writefile(tmp, ext, NULL, ioflags, 0, AST_FILE_MODE);
498
499 if (!s) {
500 ast_log(LOG_WARNING, "Could not create file %s\n", args.filename);
501 status_response = "ERROR";
502 goto out;
503 }
504
507
508 /* Request a video update */
510
511 if (maxduration <= 0)
512 maxduration = -1;
513
514 start = ast_tvnow();
515 while ((ms = ast_remaining_ms(start, maxduration))) {
516 ms = ast_waitfor(chan, ms);
517 if (ms < 0) {
518 break;
519 }
520
521 if (maxduration > 0 && ms == 0) {
522 break;
523 }
524
525 f = ast_read(chan);
526 if (!f) {
527 res = -1;
528 break;
529 }
530 if (f->frametype == AST_FRAME_VOICE) {
531 res = ast_writestream(s, f);
532
533 if (res) {
534 ast_log(LOG_WARNING, "Problem writing frame\n");
535 ast_frfree(f);
536 status_response = "ERROR";
537 break;
538 }
539
540 if (silence > 0) {
541 dspsilence = 0;
542 ast_dsp_silence(sildet, f, &dspsilence);
543 if (dspsilence) {
544 totalsilence = dspsilence;
545 } else {
546 totalsilence = 0;
547 }
548 if (totalsilence > silence) {
549 /* Ended happily with silence */
550 ast_frfree(f);
551 gotsilence = 1;
552 status_response = "SILENCE";
553 break;
554 }
555 }
556 } else if (f->frametype == AST_FRAME_VIDEO) {
557 res = ast_writestream(s, f);
558
559 if (res) {
560 ast_log(LOG_WARNING, "Problem writing frame\n");
561 status_response = "ERROR";
562 ast_frfree(f);
563 break;
564 }
565 } else if (f->frametype == AST_FRAME_DTMF) {
566 enum dtmf_response rc =
567 record_dtmf_response(chan, &flags, f->subclass.integer, terminator);
568 switch(rc) {
570 break;
572 status_response = "OPERATOR";
573 ast_debug(1, "Got OPERATOR\n");
574 break;
575 case RESPONSE_DTMF:
576 status_response = "DTMF";
577 ast_debug(1, "Got DTMF\n");
578 break;
579 }
580 if (rc != RESPONSE_NO_MATCH) {
581 ast_frfree(f);
582 break;
583 }
584 }
585 ast_frfree(f);
586 }
587
588 if (maxduration > 0 && !ms) {
589 gottimeout = 1;
590 status_response = "TIMEOUT";
591 }
592
593 if (!f) {
594 ast_debug(1, "Got hangup\n");
595 res = -1;
596 status_response = "HANGUP";
597 if (!ast_test_flag(&flags, OPTION_KEEP)) {
598 ast_filedelete(args.filename, NULL);
599 }
600 }
601
602 if (gotsilence && truncate_silence) {
603 ast_stream_rewind(s, silence - 1000);
605 } else if (!gottimeout && f) {
606 /*
607 * Strip off the last 1/4 second of it, if we didn't end because of a timeout,
608 * or a hangup. This must mean we ended because of a DTMF tone and while this
609 * 1/4 second stripping is very old code the most likely explanation is that it
610 * relates to stripping a partial DTMF tone.
611 */
612 ast_stream_rewind(s, 250);
614 }
616
617 if (silgen)
619
620out:
621 recdata->duration = ast_tvdiff_ms(ast_tvnow(), start);
622
623 if ((silence > 0) && rfmt) {
624 res = ast_set_read_format(chan, rfmt);
625 if (res) {
626 ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", ast_channel_name(chan));
627 }
628 }
629
630 if (sildet) {
631 ast_dsp_free(sildet);
632 }
633
634 pbx_builtin_setvar_helper(chan, "RECORD_STATUS", status_response);
635
636 return res;
637}
638
640 .name = "RECORDING_INFO",
641 .read = recording_info_read,
642};
643
644static int unload_module(void)
645{
646 int res;
649 return res;
650}
651
652static int load_module(void)
653{
654 int res;
657 return res;
658}
659
660AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Trivial Record Application");
static int record_exec(struct ast_channel *chan, const char *data)
Definition: app_record.c:298
#define OPERATOR_KEY
Definition: app_record.c:150
static enum dtmf_response record_dtmf_response(struct ast_channel *chan, struct ast_flags *flags, int dtmf_integer, int terminator)
Definition: app_record.c:198
static struct ast_custom_function acf_recording_info
Definition: app_record.c:639
static int create_destination_directory(const char *path)
Definition: app_record.c:214
static int recording_info_read(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)
Definition: app_record.c:262
static const struct ast_app_option app_opts[128]
Definition: app_record.c:184
static char * app
Definition: app_record.c:152
static const struct ast_datastore_info recording_data_info
Definition: app_record.c:257
static int load_module(void)
Definition: app_record.c:652
static int unload_module(void)
Definition: app_record.c:644
@ OPTION_NOANSWER
Definition: app_record.c:156
@ OPTION_STAR_TERMINATE
Definition: app_record.c:159
@ OPTION_KEEP
Definition: app_record.c:161
@ OPTION_NO_TRUNCATE
Definition: app_record.c:164
@ OPTION_QUIET
Definition: app_record.c:157
@ OPTION_OPERATOR_EXIT
Definition: app_record.c:163
@ OPTION_IGNORE_TERMINATE
Definition: app_record.c:160
@ OPTION_ANY_TERMINATE
Definition: app_record.c:162
@ OPTION_SKIP
Definition: app_record.c:158
@ OPTION_APPEND
Definition: app_record.c:155
static void recording_data_free(void *data)
Definition: app_record.c:252
dtmf_response
Definition: app_record.c:167
@ RESPONSE_OPERATOR
Definition: app_record.c:169
@ RESPONSE_DTMF
Definition: app_record.c:170
@ RESPONSE_NO_MATCH
Definition: app_record.c:168
Asterisk main include file. File version handling, generic pbx functions.
#define AST_FILE_MODE
Definition: asterisk.h:32
#define PATH_MAX
Definition: asterisk.h:40
#define ast_free(a)
Definition: astmm.h:180
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
#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
General Asterisk PBX channel definitions.
const char * ast_channel_name(const struct ast_channel *chan)
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2354
#define ast_channel_lock(chan)
Definition: channel.h:2972
struct ast_silence_generator * ast_channel_start_silence_generator(struct ast_channel *chan)
Starts a silence generator on the given channel.
Definition: channel.c:8169
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition: channel.c:3130
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:8215
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4214
int ast_set_read_format(struct ast_channel *chan, struct ast_format *format)
Sets read format on channel chan.
Definition: channel.c:5721
const char * ast_channel_language(const struct ast_channel *chan)
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:2774
int ast_indicate(struct ast_channel *chan, int condition)
Indicates condition of channel.
Definition: channel.c:4234
#define ast_channel_unlock(chan)
Definition: channel.h:2973
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2368
struct ast_format * ast_channel_readformat(struct ast_channel *chan)
ast_channel_state
ast_channel states
Definition: channelstate.h:35
@ AST_STATE_UP
Definition: channelstate.h:42
#define ast_datastore_alloc(info, uid)
Definition: datastore.h:85
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition: datastore.c:68
Convenient Signal Processing routines.
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:1788
void ast_dsp_free(struct ast_dsp *dsp)
Definition: dsp.c:1783
@ 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:1488
int ast_dsp_get_threshold_from_settings(enum threshold which)
Get silence threshold from dsp.conf.
Definition: dsp.c:2009
struct ast_dsp * ast_dsp_new(void)
Allocates a new dsp, assumes 8khz for internal sample rate.
Definition: dsp.c:1758
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
Generic File Format Support. Should be included by clients of the file handling routines....
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:1108
int ast_streamfile(struct ast_channel *c, const char *filename, const char *preflang)
Streams a file.
Definition: file.c:1301
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:1431
int ast_truncstream(struct ast_filestream *fs)
Trunc stream at current location.
Definition: file.c:1088
int ast_closestream(struct ast_filestream *f)
Closes a stream.
Definition: file.c:1119
int ast_fileexists(const char *filename, const char *fmt, const char *preflang)
Checks for the existence of a given file.
Definition: file.c:1137
int ast_filedelete(const char *filename, const char *fmt)
Deletes a file.
Definition: file.c:1149
int ast_waitstream(struct ast_channel *c, const char *breakon)
Waits for a stream to stop or digit to be pressed.
Definition: file.c:1848
Media Format Cache API.
struct ast_format * ast_format_slin
Built-in cached signed linear 8kHz format.
Definition: format_cache.c:41
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
const char * ext
Definition: http.c:150
Application convenience functions, designed to give consistent look and feel to Asterisk apps.
#define AST_APP_ARG(name)
Define an application argument.
#define AST_APP_OPTIONS(holder, options...)
Declares an array of options for an application.
#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.
#define AST_APP_OPTION(option, flagno)
Declares an application option that does not accept an argument.
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:3066
#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_ERROR
#define LOG_WARNING
Asterisk module definitions.
#define AST_MODULE_INFO_STANDARD(keystr, desc)
Definition: module.h:581
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx_app.c:392
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:640
#define ast_opt_transmit_silence
Definition: options.h:125
Asterisk file paths, configured in asterisk.conf.
const char * ast_config_AST_DATA_DIR
Definition: options.c:159
Core PBX routines and definitions.
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 ast_custom_function_register(acf)
Register a custom function.
Definition: pbx.h:1562
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
#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:425
Main Channel structure associated with a channel.
Data structure associated with a custom dialplan function.
Definition: pbx.h:118
const char * name
Definition: pbx.h:119
Structure for a data store type.
Definition: datastore.h:31
const char * type
Definition: datastore.h:32
Structure for a data store object.
Definition: datastore.h:64
void * data
Definition: datastore.h:66
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
unsigned long duration
Definition: app_record.c:249
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: utils.c:2281
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:107
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159
FILE * out
Definition: utils/frame.c:33
#define ast_test_flag(p, flag)
Definition: utils.h:63
#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:947
int ast_mkdir(const char *path, int mode)
Recursively create directory path.
Definition: utils.c:2479