Asterisk - The Open Source Telephony Project GIT-master-8924258
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros Modules Pages
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.24.0</version>
47 <version>18.10.0</version>
48 </since>
49 <synopsis>
50 Detects MF digits on a channel and saves them to a variable.
51 </synopsis>
52 <syntax>
53 <parameter name="variable" required="true">
54 <para>The input digits will be stored in the given
55 <replaceable>variable</replaceable> name.</para>
56 </parameter>
57 <parameter name="timeout">
58 <para>The number of seconds to wait for all digits, if greater
59 than <literal>0</literal>. Can be floating point. Default
60 is no timeout.</para>
61 </parameter>
62 <parameter name="options">
63 <optionlist>
64 <option name="d">
65 <para>Delay audio by a frame to try to extra quelch.</para>
66 </option>
67 <option name="l">
68 <para>Receive digits even if a key pulse (KP) has not yet
69 been received. By default, this application will ignore
70 all other digits until a KP has been received.</para>
71 </option>
72 <option name="k">
73 <para>Do not return a character for the KP digit.</para>
74 </option>
75 <option name="m">
76 <para>Mute conference.</para>
77 </option>
78 <option name="n">
79 <para>Maximum number of digits, regardless of the sequence.</para>
80 </option>
81 <option name="o">
82 <para>Enable override. Repeated KPs will clear all previous digits.</para>
83 </option>
84 <option name="q">
85 <para>Quelch MF from in-band.</para>
86 </option>
87 <option name="r">
88 <para>"Radio" mode (relaxed MF).</para>
89 </option>
90 <option name="s">
91 <para>Do not return a character for ST digits.</para>
92 </option>
93 </optionlist>
94 </parameter>
95 </syntax>
96 <description>
97 <para>Reads a ST, STP, ST2P, or ST3P-terminated string of MF digits from
98 the user in to the given <replaceable>variable</replaceable>.</para>
99 <para>This application does not automatically answer the channel and
100 should be preceded with <literal>Answer</literal> or
101 <literal>Progress</literal> as needed.</para>
102 <variablelist>
103 <variable name="RECEIVEMFSTATUS">
104 <para>This is the status of the read operation.</para>
105 <value name="START" />
106 <value name="ERROR" />
107 <value name="HANGUP" />
108 <value name="MAXDIGITS" />
109 <value name="TIMEOUT" />
110 </variable>
111 </variablelist>
112 </description>
113 <see-also>
114 <ref type="application">Read</ref>
115 <ref type="application">SendMF</ref>
116 <ref type="application">ReceiveSF</ref>
117 </see-also>
118 </application>
119 <application name="SendMF" language="en_US">
120 <since>
121 <version>16.21.0</version>
122 <version>18.7.0</version>
123 </since>
124 <synopsis>
125 Sends arbitrary MF digits on the current or specified channel.
126 </synopsis>
127 <syntax>
128 <parameter name="digits" required="true">
129 <para>List of digits 0-9,*#ABC to send; w for a half-second pause,
130 also f or F for a flash-hook if the channel supports flash-hook,
131 h or H for 250 ms of 2600 Hz,
132 and W for a wink if the channel supports wink.</para>
133 <para>Key pulse and start digits are not included automatically.
134 * is used for KP, # for ST, A for STP, B for ST2P, and C for ST3P.</para>
135 </parameter>
136 <parameter name="timeout_ms" required="false">
137 <para>Amount of time to wait in ms between tones. (defaults to 50ms).</para>
138 </parameter>
139 <parameter name="duration_ms" required="false">
140 <para>Duration of each numeric digit (defaults to 55ms).</para>
141 </parameter>
142 <parameter name="duration_ms_kp" required="false">
143 <para>Duration of KP digits (defaults to 120ms).</para>
144 </parameter>
145 <parameter name="duration_ms_st" required="false">
146 <para>Duration of ST, STP, ST2P, and ST3P digits (defaults to 65ms).</para>
147 </parameter>
148 <parameter name="channel" required="false">
149 <para>Channel where digits will be played</para>
150 </parameter>
151 </syntax>
152 <description>
153 <para>It will send all digits or terminate if it encounters an error.</para>
154 </description>
155 <see-also>
156 <ref type="application">ReceiveMF</ref>
157 <ref type="application">SendSF</ref>
158 <ref type="application">SendDTMF</ref>
159 </see-also>
160 </application>
161 <manager name="PlayMF" language="en_US">
162 <since>
163 <version>16.21.0</version>
164 <version>18.7.0</version>
165 <version>19.0.0</version>
166 </since>
167 <synopsis>
168 Play MF digit on a specific channel.
169 </synopsis>
170 <syntax>
171 <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
172 <parameter name="Channel" required="true">
173 <para>Channel name to send digit to.</para>
174 </parameter>
175 <parameter name="Digit" required="true">
176 <para>The MF digit to play.</para>
177 </parameter>
178 <parameter name="Duration" required="false">
179 <para>The duration, in milliseconds, of the digit to be played.</para>
180 </parameter>
181 </syntax>
182 <description>
183 <para>Plays an MF digit on the specified channel.</para>
184 </description>
185 </manager>
186 ***/
187
189 OPT_DELAY = (1 << 0),
190 OPT_MUTE = (1 << 1),
191 OPT_QUELCH = (1 << 2),
192 OPT_RELAXED = (1 << 3),
193 OPT_LAX_KP = (1 << 4),
194 OPT_PROCESS = (1 << 5),
195 OPT_NO_KP = (1 << 6),
196 OPT_NO_ST = (1 << 7),
197 OPT_KP_OVERRIDE = (1 << 8),
198 OPT_MAXDIGITS = (1 << 9),
199};
200
201enum {
203 /* Must be the last element */
205};
206
218});
219
220static const char *readmf_name = "ReceiveMF";
221static const char sendmf_name[] = "SendMF";
222
223#define MF_BETWEEN_MS 50
224#define MF_DURATION 55
225#define MF_KP_DURATION 120
226#define MF_ST_DURATION 65
227
228/*!
229 * \brief Detects MF digits on channel using DSP, terminated by ST, STP, ST2P, or ST3P
230 *
231 * \param chan channel on which to read digits
232 * \param buf Buffer in which to store digits
233 * \param buflen Size of buffer
234 * \param timeout ms to wait for all digits before giving up
235 * \param features Any additional DSP features to use
236 * \param laxkp Receive digits even if KP not received
237 * \param override Start over if we receive additional KPs
238 * \param no_kp Don't include KP in the output
239 * \param no_st Don't include start digits in the output
240 * \param maxdigits If greater than 0, only read this many digits no matter what
241 *
242 * \retval 0 if successful
243 * \retval -1 if unsuccessful (including hangup).
244 */
245static 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) {
246 struct ast_dsp *dsp;
247 struct ast_frame *frame = NULL;
248 struct timeval start;
249 int remaining_time = timeout;
250 int digits_read = 0;
251 int is_start_digit = 0;
252 char *str = buf;
253 int res = 0;
254
255 if (!(dsp = ast_dsp_new())) {
256 ast_log(LOG_WARNING, "Unable to allocate DSP!\n");
257 pbx_builtin_setvar_helper(chan, "RECEIVEMFSTATUS", "ERROR");
258 return -1;
259 }
262
263 start = ast_tvnow();
264 *str = 0; /* start with empty output buffer */
265
266 /* based on app_read and generic_fax_exec from res_fax */
267 while (timeout == 0 || remaining_time > 0) {
268 if (timeout > 0) {
269 remaining_time = ast_remaining_ms(start, timeout);
270 if (remaining_time <= 0) {
271 pbx_builtin_setvar_helper(chan, "RECEIVEMFSTATUS", "TIMEOUT");
272 break;
273 }
274 }
275 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) */
276 /* This result will probably not be usable, so status should not be START */
277 pbx_builtin_setvar_helper(chan, "RECEIVEMFSTATUS", "MAXDIGITS");
278 break;
279 }
280 /* ast_waitfordigit only waits for DTMF frames, we need to do DSP on voice frames */
281 if (ast_waitfor(chan, 1000) > 0) {
282 frame = ast_read(chan);
283 if (!frame) {
284 ast_debug(1, "Channel '%s' did not return a frame; probably hung up.\n", ast_channel_name(chan));
285 pbx_builtin_setvar_helper(chan, "RECEIVEMFSTATUS", "HANGUP");
286 break;
287 } else if (frame->frametype == AST_FRAME_VOICE) {
288 frame = ast_dsp_process(chan, dsp, frame);
289 /* AST_FRAME_DTMF is used all over the DSP code for DTMF, MF, fax, etc.
290 It's used because we can use the frame to store the digit detected.
291 All this means is that we received something we care about. */
292 if (frame->frametype == AST_FRAME_DTMF) {
293 char result = frame->subclass.integer;
294 if (digits_read == 0 && !laxkp && result != '*') {
295 ast_debug(1, "Received MF digit, but no KP yet, ignoring: %c\n", result);
296 ast_frfree(frame);
297 continue;
298 }
299 ast_debug(1, "Received MF digit: %c\n", result);
300 if (result == '*') {
301 /* We received an additional KP, start over? */
302 if (override && digits_read > 0) {
303 ast_debug(1, "Received another KP, starting over\n");
304 str = buf;
305 *str = 0;
306 digits_read = 1; /* we just detected a KP */
307 } else {
308 digits_read++;
309 }
310 /* if we were told not to include the KP digit in the output string, then skip it */
311 if (no_kp) {
312 ast_frfree(frame);
313 continue;
314 }
315 } else {
316 digits_read++;
317 }
318 is_start_digit = (strchr("#", result) || strchr("A", result) || strchr("B", result) || strchr("C", result));
319 /* if we were told not to include the ST digit in the output string, then skip it */
320 if (!no_st || !is_start_digit) {
321 *str++ = result; /* won't write past allotted memory, because of buffer check at top of loop */
322 *str = 0;
323 }
324 /* we received a ST digit (ST, STP, ST2P, or ST3P), so we're done */
325 if (is_start_digit) {
326 pbx_builtin_setvar_helper(chan, "RECEIVEMFSTATUS", "START");
327 ast_frfree(frame);
328 break;
329 }
330 /* only free frame if it was a DSP match. The MF itself should not be muted. */
331 ast_frfree(frame);
332 }
333 }
334 } else {
335 pbx_builtin_setvar_helper(chan, "RECEIVEMFSTATUS", "HANGUP");
336 res = -1;
337 }
338 }
339 ast_dsp_free(dsp);
340 ast_debug(3, "channel '%s' - event loop stopped { timeout: %d, remaining_time: %d }\n", ast_channel_name(chan), timeout, remaining_time);
341 return res;
342}
343
344static int read_mf_exec(struct ast_channel *chan, const char *data)
345{
346#define BUFFER_SIZE 256
347 char tmp[BUFFER_SIZE] = "";
348 int to = 0;
349 double tosec;
350 struct ast_flags flags = {0};
351 char *optargs[OPT_ARG_ARRAY_SIZE];
352 char *argcopy = NULL;
353 int res, features = 0, maxdigits = 0;
354
355 AST_DECLARE_APP_ARGS(arglist,
356 AST_APP_ARG(variable);
357 AST_APP_ARG(timeout);
359 );
360
361 if (ast_strlen_zero(data)) {
362 ast_log(LOG_WARNING, "ReceiveMF requires an argument (variable)\n");
363 return -1;
364 }
365
366 argcopy = ast_strdupa(data);
367
368 AST_STANDARD_APP_ARGS(arglist, argcopy);
369
370 if (!ast_strlen_zero(arglist.options)) {
371 ast_app_parse_options(read_app_options, &flags, optargs, arglist.options);
372 }
373
374 if (!ast_strlen_zero(arglist.timeout)) {
375 tosec = atof(arglist.timeout);
376 if (tosec <= 0) {
377 to = 0;
378 } else {
379 to = tosec * 1000.0;
380 }
381 }
382
383 if (ast_strlen_zero(arglist.variable)) {
384 ast_log(LOG_WARNING, "Invalid! Usage: ReceiveMF(variable[,timeout][,option])\n");
385 return -1;
386 }
388 maxdigits = atoi(optargs[OPT_ARG_MAXDIGITS]);
389 if (maxdigits <= 0) {
390 ast_log(LOG_WARNING, "Invalid maximum number of digits, ignoring: '%s'\n", optargs[OPT_ARG_MAXDIGITS]);
391 maxdigits = 0;
392 }
393 }
394
396 features |= DSP_DIGITMODE_MUTEMAX;
397 }
398
400 features |= DSP_DIGITMODE_MUTECONF;
401 }
402
404 features |= DSP_DIGITMODE_NOQUELCH;
405 }
406
408 features |= DSP_DIGITMODE_RELAXDTMF;
409 }
410
411 res = read_mf_digits(chan, tmp, BUFFER_SIZE, to, features, (ast_test_flag(&flags, OPT_LAX_KP)),
413 pbx_builtin_setvar_helper(chan, arglist.variable, tmp);
414 if (!ast_strlen_zero(tmp)) {
415 ast_verb(3, "MF digits received: '%s'\n", tmp);
416 } else if (!res) { /* if channel hung up, don't print anything out */
417 ast_verb(3, "No MF digits received.\n");
418 }
419 return res;
420}
421
422static int sendmf_exec(struct ast_channel *chan, const char *vdata)
423{
424 int res;
425 char *data;
426 int dinterval = 0, duration = 0, durationkp = 0, durationst = 0;
427 struct ast_channel *chan_found = NULL;
428 struct ast_channel *chan_dest = chan;
429 struct ast_channel *chan_autoservice = NULL;
431 AST_APP_ARG(digits);
432 AST_APP_ARG(dinterval);
433 AST_APP_ARG(duration);
434 AST_APP_ARG(durationkp);
435 AST_APP_ARG(durationst);
436 AST_APP_ARG(channel);
437 );
438
439 if (ast_strlen_zero(vdata)) {
440 ast_log(LOG_WARNING, "SendMF requires an argument\n");
441 return 0;
442 }
443
444 data = ast_strdupa(vdata);
446
447 if (ast_strlen_zero(args.digits)) {
448 ast_log(LOG_WARNING, "The digits argument is required (0-9,*#ABC,wf)\n");
449 return 0;
450 }
451 if (!ast_strlen_zero(args.dinterval)) {
452 ast_app_parse_timelen(args.dinterval, &dinterval, TIMELEN_MILLISECONDS);
453 }
454 if (!ast_strlen_zero(args.duration)) {
455 ast_app_parse_timelen(args.duration, &duration, TIMELEN_MILLISECONDS);
456 }
457 if (!ast_strlen_zero(args.durationkp)) {
458 ast_app_parse_timelen(args.durationkp, &durationkp, TIMELEN_MILLISECONDS);
459 }
460 if (!ast_strlen_zero(args.durationst)) {
461 ast_app_parse_timelen(args.durationst, &durationst, TIMELEN_MILLISECONDS);
462 }
463 if (!ast_strlen_zero(args.channel)) {
464 chan_found = ast_channel_get_by_name(args.channel);
465 if (!chan_found) {
466 ast_log(LOG_WARNING, "No such channel: %s\n", args.channel);
467 return 0;
468 }
469 chan_dest = chan_found;
470 if (chan_found != chan) {
471 chan_autoservice = chan;
472 }
473 }
474 res = ast_mf_stream(chan_dest, chan_autoservice, NULL, args.digits, dinterval <= 0 ? MF_BETWEEN_MS : dinterval,
475 duration <= 0 ? MF_DURATION : duration, durationkp <= 0 ? MF_KP_DURATION : durationkp,
476 durationst <= 0 ? MF_ST_DURATION : durationst, 0);
477 ast_channel_cleanup(chan_found);
478
479 return chan_autoservice ? 0 : res;
480}
481
482static int manager_play_mf(struct mansession *s, const struct message *m)
483{
484 const char *channel = astman_get_header(m, "Channel");
485 const char *digit = astman_get_header(m, "Digit");
486 const char *duration = astman_get_header(m, "Duration");
487 struct ast_channel *chan;
488 unsigned int duration_ms = MF_DURATION;
489
490 if (!(chan = ast_channel_get_by_name(channel))) {
491 astman_send_error(s, m, "Channel not found");
492 return 0;
493 }
494
495 if (ast_strlen_zero(digit)) {
496 astman_send_error(s, m, "No digit specified");
497 chan = ast_channel_unref(chan);
498 return 0;
499 }
500
501 /* Override default duration with KP or ST-specific default durations */
502 if (!strcmp(digit, "*"))
503 duration_ms = MF_KP_DURATION;
504
505 if (!strcmp(digit, "#") || !strcmp(digit, "A") || !strcmp(digit, "B") || !strcmp(digit, "C"))
506 duration_ms = MF_ST_DURATION;
507
508 if (!ast_strlen_zero(duration) && (sscanf(duration, "%30u", &duration_ms) != 1)) {
509 astman_send_error(s, m, "Could not convert Duration parameter");
510 chan = ast_channel_unref(chan);
511 return 0;
512 }
513
514 ast_mf_stream(chan, NULL, NULL, digit, 0, duration_ms, duration_ms, duration_ms, 1);
515
516 chan = ast_channel_unref(chan);
517
518 astman_send_ack(s, m, "MF successfully queued");
519
520 return 0;
521}
522
523static int unload_module(void)
524{
525 int res;
526
529 res |= ast_manager_unregister("PlayMF");
530
531 return res;
532}
533
534static int load_module(void)
535{
536 int res;
537
541
542 return res;
543}
544
545AST_MODULE_INFO_STANDARD_EXTENDED(ASTERISK_GPL_KEY, "MF Sender and Receiver Applications");
char digit
const char * str
Definition: app_jack.c:150
@ OPT_ARG_MAXDIGITS
Definition: app_mf.c:202
@ OPT_ARG_ARRAY_SIZE
Definition: app_mf.c:204
static int sendmf_exec(struct ast_channel *chan, const char *vdata)
Definition: app_mf.c:422
static const char * readmf_name
Definition: app_mf.c:220
#define MF_DURATION
Definition: app_mf.c:224
#define BUFFER_SIZE
static const char sendmf_name[]
Definition: app_mf.c:221
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:245
static int manager_play_mf(struct mansession *s, const struct message *m)
Definition: app_mf.c:482
#define MF_ST_DURATION
Definition: app_mf.c:226
static int load_module(void)
Definition: app_mf.c:534
static int unload_module(void)
Definition: app_mf.c:523
read_option_flags
Definition: app_mf.c:188
@ OPT_PROCESS
Definition: app_mf.c:194
@ OPT_MUTE
Definition: app_mf.c:190
@ OPT_NO_KP
Definition: app_mf.c:195
@ OPT_LAX_KP
Definition: app_mf.c:193
@ OPT_RELAXED
Definition: app_mf.c:192
@ OPT_MAXDIGITS
Definition: app_mf.c:198
@ OPT_QUELCH
Definition: app_mf.c:191
@ OPT_DELAY
Definition: app_mf.c:189
@ OPT_KP_OVERRIDE
Definition: app_mf.c:197
@ OPT_NO_ST
Definition: app_mf.c:196
AST_MODULE_INFO_STANDARD_EXTENDED(ASTERISK_GPL_KEY, "MF Sender and Receiver Applications")
#define MF_KP_DURATION
Definition: app_mf.c:225
static int read_mf_exec(struct ast_channel *chan, const char *data)
Definition: app_mf.c:344
static const struct ast_app_option read_app_options[128]
Definition: app_mf.c:218
#define MF_BETWEEN_MS
Definition: app_mf.c:223
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 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:3190
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4274
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:3006
#define ast_channel_cleanup(c)
Cleanup a channel reference.
Definition: channel.h:3017
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
Definition: channel.c:1481
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:1986
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:2018
const char * astman_get_header(const struct message *m, char *var)
Get header from manager transaction.
Definition: manager.c:1647
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
Definition: manager.c:7697
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:192
#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:327
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