Asterisk - The Open Source Telephony Project GIT-master-d856a3e
app_mf.c
Go to the documentation of this file.
1/*
2 * Asterisk -- An open source telephony toolkit.
3 *
4 * Copyright (C) 2021, Naveen Albert
5 *
6 * Naveen Albert <asterisk@phreaknet.org>
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 MF sender and receiver applications
22 *
23 * \author Naveen Albert <asterisk@phreaknet.org>
24 *
25 * \ingroup applications
26 */
27
28/*** MODULEINFO
29 <support_level>extended</support_level>
30 ***/
31
32#include "asterisk.h"
33
34#include "asterisk/file.h"
35#include "asterisk/pbx.h"
36#include "asterisk/channel.h"
37#include "asterisk/dsp.h"
38#include "asterisk/app.h"
39#include "asterisk/module.h"
42
43/*** DOCUMENTATION
44 <application name="ReceiveMF" language="en_US">
45 <since>
46 <version>16.21.0</version>
47 <version>18.7.0</version>
48 <version>19.0.0</version>
49 </since>
50 <synopsis>
51 Detects MF digits on a channel and saves them to a variable.
52 </synopsis>
53 <syntax>
54 <parameter name="variable" required="true">
55 <para>The input digits will be stored in the given
56 <replaceable>variable</replaceable> name.</para>
57 </parameter>
58 <parameter name="timeout">
59 <para>The number of seconds to wait for all digits, if greater
60 than <literal>0</literal>. Can be floating point. Default
61 is no timeout.</para>
62 </parameter>
63 <parameter name="options">
64 <optionlist>
65 <option name="d">
66 <para>Delay audio by a frame to try to extra quelch.</para>
67 </option>
68 <option name="l">
69 <para>Receive digits even if a key pulse (KP) has not yet
70 been received. By default, this application will ignore
71 all other digits until a KP has been received.</para>
72 </option>
73 <option name="k">
74 <para>Do not return a character for the KP digit.</para>
75 </option>
76 <option name="m">
77 <para>Mute conference.</para>
78 </option>
79 <option name="n">
80 <para>Maximum number of digits, regardless of the sequence.</para>
81 </option>
82 <option name="o">
83 <para>Enable override. Repeated KPs will clear all previous digits.</para>
84 </option>
85 <option name="q">
86 <para>Quelch MF from in-band.</para>
87 </option>
88 <option name="r">
89 <para>"Radio" mode (relaxed MF).</para>
90 </option>
91 <option name="s">
92 <para>Do not return a character for ST digits.</para>
93 </option>
94 </optionlist>
95 </parameter>
96 </syntax>
97 <description>
98 <para>Reads a ST, STP, ST2P, or ST3P-terminated string of MF digits from
99 the user in to the given <replaceable>variable</replaceable>.</para>
100 <para>This application does not automatically answer the channel and
101 should be preceded with <literal>Answer</literal> or
102 <literal>Progress</literal> as needed.</para>
103 <variablelist>
104 <variable name="RECEIVEMFSTATUS">
105 <para>This is the status of the read operation.</para>
106 <value name="START" />
107 <value name="ERROR" />
108 <value name="HANGUP" />
109 <value name="MAXDIGITS" />
110 <value name="TIMEOUT" />
111 </variable>
112 </variablelist>
113 </description>
114 <see-also>
115 <ref type="application">Read</ref>
116 <ref type="application">SendMF</ref>
117 <ref type="application">ReceiveSF</ref>
118 </see-also>
119 </application>
120 <application name="SendMF" language="en_US">
121 <since>
122 <version>16.21.0</version>
123 <version>18.7.0</version>
124 <version>19.0.0</version>
125 </since>
126 <synopsis>
127 Sends arbitrary MF digits on the current or specified channel.
128 </synopsis>
129 <syntax>
130 <parameter name="digits" required="true">
131 <para>List of digits 0-9,*#ABC to send; w for a half-second pause,
132 also f or F for a flash-hook if the channel supports flash-hook,
133 h or H for 250 ms of 2600 Hz,
134 and W for a wink if the channel supports wink.</para>
135 <para>Key pulse and start digits are not included automatically.
136 * is used for KP, # for ST, A for STP, B for ST2P, and C for ST3P.</para>
137 </parameter>
138 <parameter name="timeout_ms" required="false">
139 <para>Amount of time to wait in ms between tones. (defaults to 50ms).</para>
140 </parameter>
141 <parameter name="duration_ms" required="false">
142 <para>Duration of each numeric digit (defaults to 55ms).</para>
143 </parameter>
144 <parameter name="duration_ms_kp" required="false">
145 <para>Duration of KP digits (defaults to 120ms).</para>
146 </parameter>
147 <parameter name="duration_ms_st" required="false">
148 <para>Duration of ST, STP, ST2P, and ST3P digits (defaults to 65ms).</para>
149 </parameter>
150 <parameter name="channel" required="false">
151 <para>Channel where digits will be played</para>
152 </parameter>
153 </syntax>
154 <description>
155 <para>It will send all digits or terminate if it encounters an error.</para>
156 </description>
157 <see-also>
158 <ref type="application">ReceiveMF</ref>
159 <ref type="application">SendSF</ref>
160 <ref type="application">SendDTMF</ref>
161 </see-also>
162 </application>
163 <manager name="PlayMF" language="en_US">
164 <since>
165 <version>16.21.0</version>
166 <version>18.7.0</version>
167 <version>19.0.0</version>
168 </since>
169 <synopsis>
170 Play MF digit on a specific channel.
171 </synopsis>
172 <syntax>
173 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
174 <parameter name="Channel" required="true">
175 <para>Channel name to send digit to.</para>
176 </parameter>
177 <parameter name="Digit" required="true">
178 <para>The MF digit to play.</para>
179 </parameter>
180 <parameter name="Duration" required="false">
181 <para>The duration, in milliseconds, of the digit to be played.</para>
182 </parameter>
183 </syntax>
184 <description>
185 <para>Plays an MF digit on the specified channel.</para>
186 </description>
187 </manager>
188 ***/
189
191 OPT_DELAY = (1 << 0),
192 OPT_MUTE = (1 << 1),
193 OPT_QUELCH = (1 << 2),
194 OPT_RELAXED = (1 << 3),
195 OPT_LAX_KP = (1 << 4),
196 OPT_PROCESS = (1 << 5),
197 OPT_NO_KP = (1 << 6),
198 OPT_NO_ST = (1 << 7),
199 OPT_KP_OVERRIDE = (1 << 8),
200 OPT_MAXDIGITS = (1 << 9),
201};
202
203enum {
205 /* Must be the last element */
207};
208
220});
221
222static const char *readmf_name = "ReceiveMF";
223static const char sendmf_name[] = "SendMF";
224
225#define MF_BETWEEN_MS 50
226#define MF_DURATION 55
227#define MF_KP_DURATION 120
228#define MF_ST_DURATION 65
229
230/*!
231 * \brief Detects MF digits on channel using DSP, terminated by ST, STP, ST2P, or ST3P
232 *
233 * \param chan channel on which to read digits
234 * \param buf Buffer in which to store digits
235 * \param buflen Size of buffer
236 * \param timeout ms to wait for all digits before giving up
237 * \param features Any additional DSP features to use
238 * \param laxkp Receive digits even if KP not received
239 * \param override Start over if we receive additional KPs
240 * \param no_kp Don't include KP in the output
241 * \param no_st Don't include start digits in the output
242 * \param maxdigits If greater than 0, only read this many digits no matter what
243 *
244 * \retval 0 if successful
245 * \retval -1 if unsuccessful (including hangup).
246 */
247static int read_mf_digits(struct ast_channel *chan, char *buf, int buflen, int timeout, int features, int laxkp, int override, int no_kp, int no_st, int maxdigits) {
248 struct ast_dsp *dsp;
249 struct ast_frame *frame = NULL;
250 struct timeval start;
251 int remaining_time = timeout;
252 int digits_read = 0;
253 int is_start_digit = 0;
254 char *str = buf;
255 int res = 0;
256
257 if (!(dsp = ast_dsp_new())) {
258 ast_log(LOG_WARNING, "Unable to allocate DSP!\n");
259 pbx_builtin_setvar_helper(chan, "RECEIVEMFSTATUS", "ERROR");
260 return -1;
261 }
264
265 start = ast_tvnow();
266 *str = 0; /* start with empty output buffer */
267
268 /* based on app_read and generic_fax_exec from res_fax */
269 while (timeout == 0 || remaining_time > 0) {
270 if (timeout > 0) {
271 remaining_time = ast_remaining_ms(start, timeout);
272 if (remaining_time <= 0) {
273 pbx_builtin_setvar_helper(chan, "RECEIVEMFSTATUS", "TIMEOUT");
274 break;
275 }
276 }
277 if ((maxdigits && digits_read >= maxdigits) || digits_read >= (buflen - 1)) { /* we don't have room to store any more digits (very unlikely to happen for a legitimate reason) */
278 /* This result will probably not be usable, so status should not be START */
279 pbx_builtin_setvar_helper(chan, "RECEIVEMFSTATUS", "MAXDIGITS");
280 break;
281 }
282 /* ast_waitfordigit only waits for DTMF frames, we need to do DSP on voice frames */
283 if (ast_waitfor(chan, 1000) > 0) {
284 frame = ast_read(chan);
285 if (!frame) {
286 ast_debug(1, "Channel '%s' did not return a frame; probably hung up.\n", ast_channel_name(chan));
287 pbx_builtin_setvar_helper(chan, "RECEIVEMFSTATUS", "HANGUP");
288 break;
289 } else if (frame->frametype == AST_FRAME_VOICE) {
290 frame = ast_dsp_process(chan, dsp, frame);
291 /* AST_FRAME_DTMF is used all over the DSP code for DTMF, MF, fax, etc.
292 It's used because we can use the frame to store the digit detected.
293 All this means is that we received something we care about. */
294 if (frame->frametype == AST_FRAME_DTMF) {
295 char result = frame->subclass.integer;
296 if (digits_read == 0 && !laxkp && result != '*') {
297 ast_debug(1, "Received MF digit, but no KP yet, ignoring: %c\n", result);
298 ast_frfree(frame);
299 continue;
300 }
301 ast_debug(1, "Received MF digit: %c\n", result);
302 if (result == '*') {
303 /* We received an additional KP, start over? */
304 if (override && digits_read > 0) {
305 ast_debug(1, "Received another KP, starting over\n");
306 str = buf;
307 *str = 0;
308 digits_read = 1; /* we just detected a KP */
309 } else {
310 digits_read++;
311 }
312 /* if we were told not to include the KP digit in the output string, then skip it */
313 if (no_kp) {
314 ast_frfree(frame);
315 continue;
316 }
317 } else {
318 digits_read++;
319 }
320 is_start_digit = (strchr("#", result) || strchr("A", result) || strchr("B", result) || strchr("C", result));
321 /* if we were told not to include the ST digit in the output string, then skip it */
322 if (!no_st || !is_start_digit) {
323 *str++ = result; /* won't write past allotted memory, because of buffer check at top of loop */
324 *str = 0;
325 }
326 /* we received a ST digit (ST, STP, ST2P, or ST3P), so we're done */
327 if (is_start_digit) {
328 pbx_builtin_setvar_helper(chan, "RECEIVEMFSTATUS", "START");
329 ast_frfree(frame);
330 break;
331 }
332 /* only free frame if it was a DSP match. The MF itself should not be muted. */
333 ast_frfree(frame);
334 }
335 }
336 } else {
337 pbx_builtin_setvar_helper(chan, "RECEIVEMFSTATUS", "HANGUP");
338 res = -1;
339 }
340 }
341 ast_dsp_free(dsp);
342 ast_debug(3, "channel '%s' - event loop stopped { timeout: %d, remaining_time: %d }\n", ast_channel_name(chan), timeout, remaining_time);
343 return res;
344}
345
346static int read_mf_exec(struct ast_channel *chan, const char *data)
347{
348#define BUFFER_SIZE 256
349 char tmp[BUFFER_SIZE] = "";
350 int to = 0;
351 double tosec;
352 struct ast_flags flags = {0};
353 char *optargs[OPT_ARG_ARRAY_SIZE];
354 char *argcopy = NULL;
355 int res, features = 0, maxdigits = 0;
356
357 AST_DECLARE_APP_ARGS(arglist,
358 AST_APP_ARG(variable);
359 AST_APP_ARG(timeout);
361 );
362
363 if (ast_strlen_zero(data)) {
364 ast_log(LOG_WARNING, "ReceiveMF requires an argument (variable)\n");
365 return -1;
366 }
367
368 argcopy = ast_strdupa(data);
369
370 AST_STANDARD_APP_ARGS(arglist, argcopy);
371
372 if (!ast_strlen_zero(arglist.options)) {
373 ast_app_parse_options(read_app_options, &flags, optargs, arglist.options);
374 }
375
376 if (!ast_strlen_zero(arglist.timeout)) {
377 tosec = atof(arglist.timeout);
378 if (tosec <= 0) {
379 to = 0;
380 } else {
381 to = tosec * 1000.0;
382 }
383 }
384
385 if (ast_strlen_zero(arglist.variable)) {
386 ast_log(LOG_WARNING, "Invalid! Usage: ReceiveMF(variable[,timeout][,option])\n");
387 return -1;
388 }
390 maxdigits = atoi(optargs[OPT_ARG_MAXDIGITS]);
391 if (maxdigits <= 0) {
392 ast_log(LOG_WARNING, "Invalid maximum number of digits, ignoring: '%s'\n", optargs[OPT_ARG_MAXDIGITS]);
393 maxdigits = 0;
394 }
395 }
396
398 features |= DSP_DIGITMODE_MUTEMAX;
399 }
400
402 features |= DSP_DIGITMODE_MUTECONF;
403 }
404
406 features |= DSP_DIGITMODE_NOQUELCH;
407 }
408
410 features |= DSP_DIGITMODE_RELAXDTMF;
411 }
412
413 res = read_mf_digits(chan, tmp, BUFFER_SIZE, to, features, (ast_test_flag(&flags, OPT_LAX_KP)),
415 pbx_builtin_setvar_helper(chan, arglist.variable, tmp);
416 if (!ast_strlen_zero(tmp)) {
417 ast_verb(3, "MF digits received: '%s'\n", tmp);
418 } else if (!res) { /* if channel hung up, don't print anything out */
419 ast_verb(3, "No MF digits received.\n");
420 }
421 return res;
422}
423
424static int sendmf_exec(struct ast_channel *chan, const char *vdata)
425{
426 int res;
427 char *data;
428 int dinterval = 0, duration = 0, durationkp = 0, durationst = 0;
429 struct ast_channel *chan_found = NULL;
430 struct ast_channel *chan_dest = chan;
431 struct ast_channel *chan_autoservice = NULL;
433 AST_APP_ARG(digits);
434 AST_APP_ARG(dinterval);
435 AST_APP_ARG(duration);
436 AST_APP_ARG(durationkp);
437 AST_APP_ARG(durationst);
438 AST_APP_ARG(channel);
439 );
440
441 if (ast_strlen_zero(vdata)) {
442 ast_log(LOG_WARNING, "SendMF requires an argument\n");
443 return 0;
444 }
445
446 data = ast_strdupa(vdata);
448
449 if (ast_strlen_zero(args.digits)) {
450 ast_log(LOG_WARNING, "The digits argument is required (0-9,*#ABC,wf)\n");
451 return 0;
452 }
453 if (!ast_strlen_zero(args.dinterval)) {
454 ast_app_parse_timelen(args.dinterval, &dinterval, TIMELEN_MILLISECONDS);
455 }
456 if (!ast_strlen_zero(args.duration)) {
457 ast_app_parse_timelen(args.duration, &duration, TIMELEN_MILLISECONDS);
458 }
459 if (!ast_strlen_zero(args.durationkp)) {
460 ast_app_parse_timelen(args.durationkp, &durationkp, TIMELEN_MILLISECONDS);
461 }
462 if (!ast_strlen_zero(args.durationst)) {
463 ast_app_parse_timelen(args.durationst, &durationst, TIMELEN_MILLISECONDS);
464 }
465 if (!ast_strlen_zero(args.channel)) {
466 chan_found = ast_channel_get_by_name(args.channel);
467 if (!chan_found) {
468 ast_log(LOG_WARNING, "No such channel: %s\n", args.channel);
469 return 0;
470 }
471 chan_dest = chan_found;
472 if (chan_found != chan) {
473 chan_autoservice = chan;
474 }
475 }
476 res = ast_mf_stream(chan_dest, chan_autoservice, NULL, args.digits, dinterval <= 0 ? MF_BETWEEN_MS : dinterval,
477 duration <= 0 ? MF_DURATION : duration, durationkp <= 0 ? MF_KP_DURATION : durationkp,
478 durationst <= 0 ? MF_ST_DURATION : durationst, 0);
479 ast_channel_cleanup(chan_found);
480
481 return chan_autoservice ? 0 : res;
482}
483
484static int manager_play_mf(struct mansession *s, const struct message *m)
485{
486 const char *channel = astman_get_header(m, "Channel");
487 const char *digit = astman_get_header(m, "Digit");
488 const char *duration = astman_get_header(m, "Duration");
489 struct ast_channel *chan;
490 unsigned int duration_ms = MF_DURATION;
491
492 if (!(chan = ast_channel_get_by_name(channel))) {
493 astman_send_error(s, m, "Channel not found");
494 return 0;
495 }
496
497 if (ast_strlen_zero(digit)) {
498 astman_send_error(s, m, "No digit specified");
499 chan = ast_channel_unref(chan);
500 return 0;
501 }
502
503 /* Override default duration with KP or ST-specific default durations */
504 if (!strcmp(digit, "*"))
505 duration_ms = MF_KP_DURATION;
506
507 if (!strcmp(digit, "#") || !strcmp(digit, "A") || !strcmp(digit, "B") || !strcmp(digit, "C"))
508 duration_ms = MF_ST_DURATION;
509
510 if (!ast_strlen_zero(duration) && (sscanf(duration, "%30u", &duration_ms) != 1)) {
511 astman_send_error(s, m, "Could not convert Duration parameter");
512 chan = ast_channel_unref(chan);
513 return 0;
514 }
515
516 ast_mf_stream(chan, NULL, NULL, digit, 0, duration_ms, duration_ms, duration_ms, 1);
517
518 chan = ast_channel_unref(chan);
519
520 astman_send_ack(s, m, "MF successfully queued");
521
522 return 0;
523}
524
525static int unload_module(void)
526{
527 int res;
528
531 res |= ast_manager_unregister("PlayMF");
532
533 return res;
534}
535
536static int load_module(void)
537{
538 int res;
539
543
544 return res;
545}
546
547AST_MODULE_INFO_STANDARD_EXTENDED(ASTERISK_GPL_KEY, "MF Sender and Receiver Applications");
char digit
const char * str
Definition: app_jack.c:147
@ OPT_ARG_MAXDIGITS
Definition: app_mf.c:204
@ OPT_ARG_ARRAY_SIZE
Definition: app_mf.c:206
static int sendmf_exec(struct ast_channel *chan, const char *vdata)
Definition: app_mf.c:424
static const char * readmf_name
Definition: app_mf.c:222
#define MF_DURATION
Definition: app_mf.c:226
#define BUFFER_SIZE
static const char sendmf_name[]
Definition: app_mf.c:223
static int read_mf_digits(struct ast_channel *chan, char *buf, int buflen, int timeout, int features, int laxkp, int override, int no_kp, int no_st, int maxdigits)
Detects MF digits on channel using DSP, terminated by ST, STP, ST2P, or ST3P.
Definition: app_mf.c:247
static int manager_play_mf(struct mansession *s, const struct message *m)
Definition: app_mf.c:484
#define MF_ST_DURATION
Definition: app_mf.c:228
static int load_module(void)
Definition: app_mf.c:536
static int unload_module(void)
Definition: app_mf.c:525
read_option_flags
Definition: app_mf.c:190
@ OPT_PROCESS
Definition: app_mf.c:196
@ OPT_MUTE
Definition: app_mf.c:192
@ OPT_NO_KP
Definition: app_mf.c:197
@ OPT_LAX_KP
Definition: app_mf.c:195
@ OPT_RELAXED
Definition: app_mf.c:194
@ OPT_MAXDIGITS
Definition: app_mf.c:200
@ OPT_QUELCH
Definition: app_mf.c:193
@ OPT_DELAY
Definition: app_mf.c:191
@ OPT_KP_OVERRIDE
Definition: app_mf.c:199
@ OPT_NO_ST
Definition: app_mf.c:198
AST_MODULE_INFO_STANDARD_EXTENDED(ASTERISK_GPL_KEY, "MF Sender and Receiver Applications")
#define MF_KP_DURATION
Definition: app_mf.c:227
static int read_mf_exec(struct ast_channel *chan, const char *data)
Definition: app_mf.c:346
static const struct ast_app_option read_app_options[128]
Definition: app_mf.c:220
#define MF_BETWEEN_MS
Definition: app_mf.c:225
Asterisk main include file. File version handling, generic pbx functions.
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
#define ast_log
Definition: astobj2.c:42
static int tmp()
Definition: bt_open.c:389
static PGresult * result
Definition: cel_pgsql.c:84
General Asterisk PBX channel definitions.
const char * ast_channel_name(const struct ast_channel *chan)
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition: channel.c:3181
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4276
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:3004
#define ast_channel_cleanup(c)
Cleanup a channel reference.
Definition: channel.h:3015
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
Definition: channel.c:1473
Conversion utility functions.
Convenient Signal Processing routines.
void ast_dsp_free(struct ast_dsp *dsp)
Definition: dsp.c:1783
#define DSP_DIGITMODE_NOQUELCH
Definition: dsp.h:34
#define DSP_DIGITMODE_MF
Definition: dsp.h:32
#define DSP_DIGITMODE_MUTEMAX
Definition: dsp.h:36
struct ast_frame * ast_dsp_process(struct ast_channel *chan, struct ast_dsp *dsp, struct ast_frame *inf)
Return AST_FRAME_NULL frames when there is silence, AST_FRAME_BUSY on busies, and call progress,...
Definition: dsp.c:1499
#define DSP_FEATURE_DIGIT_DETECT
Definition: dsp.h:28
int ast_dsp_set_digitmode(struct ast_dsp *dsp, int digitmode)
Set digit mode.
Definition: dsp.c:1857
#define DSP_DIGITMODE_MUTECONF
Definition: dsp.h:35
void ast_dsp_set_features(struct ast_dsp *dsp, int features)
Select feature set.
Definition: dsp.c:1768
struct ast_dsp * ast_dsp_new(void)
Allocates a new dsp, assumes 8khz for internal sample rate.
Definition: dsp.c:1758
#define DSP_DIGITMODE_RELAXDTMF
Definition: dsp.h:37
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
Generic File Format Support. Should be included by clients of the file handling routines....
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:1969
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:2001
const char * astman_get_header(const struct message *m, char *var)
Get header from manager transaction.
Definition: manager.c:1630
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
Definition: manager.c:7511
Application convenience functions, designed to give consistent look and feel to Asterisk apps.
#define AST_APP_ARG(name)
Define an application argument.
int ast_app_parse_timelen(const char *timestr, int *result, enum ast_timelen defunit)
Common routine to parse time lengths, with optional time unit specifier.
Definition: main/app.c:3273
#define AST_APP_OPTIONS(holder, options...)
Declares an array of options for an application.
#define AST_APP_OPTION_ARG(option, flagno, argno)
Declares an application option that accepts an 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.
@ TIMELEN_MILLISECONDS
#define AST_APP_OPTION(option, flagno)
Declares an application option that does not accept an argument.
int ast_mf_stream(struct ast_channel *chan, struct ast_channel *peer, struct ast_channel *chan2, const char *digits, int between, unsigned int duration, unsigned int durationkp, unsigned int durationst, int is_external)
Send a string of MF digits to a channel.
Definition: main/app.c:1113
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_VOICE
#define ast_debug(level,...)
Log a DEBUG message.
#define ast_verb(level,...)
#define LOG_WARNING
Tone Indication Support.
#define ast_manager_register_xml(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
Definition: manager.h:191
#define EVENT_FLAG_CALL
Definition: manager.h:76
Asterisk module definitions.
#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
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 NULL
Definition: resample.c:96
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
Main Channel structure associated with a channel.
const char * data
Definition: dsp.c:407
Structure used to handle boolean flags.
Definition: utils.h:199
unsigned int flags
Definition: utils.h:200
Data structure associated with a single frame of data.
struct ast_frame_subclass subclass
enum ast_frame_type frametype
In case you didn't read that giant block of text above the mansession_session struct,...
Definition: manager.c:326
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
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159
#define ast_test_flag(p, flag)
Definition: utils.h:63