Asterisk - The Open Source Telephony Project  18.5.0
app_senddtmf.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  * Mark Spencer <[email protected]>
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 App to send DTMF digits
22  *
23  * \author Mark Spencer <[email protected]>
24  *
25  * \ingroup applications
26  */
27 
28 /*** MODULEINFO
29  <support_level>core</support_level>
30  ***/
31 
32 #include "asterisk.h"
33 
34 #include "asterisk/pbx.h"
35 #include "asterisk/module.h"
36 #include "asterisk/app.h"
37 #include "asterisk/manager.h"
38 #include "asterisk/channel.h"
39 
40 /*** DOCUMENTATION
41  <application name="SendDTMF" language="en_US">
42  <synopsis>
43  Sends arbitrary DTMF digits
44  </synopsis>
45  <syntax>
46  <parameter name="digits" required="true">
47  <para>List of digits 0-9,*#,a-d,A-D to send also w for a half second pause,
48  W for a one second pause, and f or F for a flash-hook if the channel supports
49  flash-hook.</para>
50  </parameter>
51  <parameter name="timeout_ms" required="false">
52  <para>Amount of time to wait in ms between tones. (defaults to .25s)</para>
53  </parameter>
54  <parameter name="duration_ms" required="false">
55  <para>Duration of each digit</para>
56  </parameter>
57  <parameter name="channel" required="false">
58  <para>Channel where digits will be played</para>
59  </parameter>
60  </syntax>
61  <description>
62  <para>It will send all digits or terminate if it encounters an error.</para>
63  </description>
64  <see-also>
65  <ref type="application">Read</ref>
66  </see-also>
67  </application>
68  <manager name="PlayDTMF" language="en_US">
69  <synopsis>
70  Play DTMF signal on a specific channel.
71  </synopsis>
72  <syntax>
73  <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
74  <parameter name="Channel" required="true">
75  <para>Channel name to send digit to.</para>
76  </parameter>
77  <parameter name="Digit" required="true">
78  <para>The DTMF digit to play.</para>
79  </parameter>
80  <parameter name="Duration" required="false">
81  <para>The duration, in milliseconds, of the digit to be played.</para>
82  </parameter>
83  <parameter name="Receive" required="false">
84  <para>Emulate receiving DTMF on this channel instead of sending it out.</para>
85  </parameter>
86  </syntax>
87  <description>
88  <para>Plays a dtmf digit on the specified channel.</para>
89  </description>
90  </manager>
91  ***/
92 
93 static const char senddtmf_name[] = "SendDTMF";
94 
95 static int senddtmf_exec(struct ast_channel *chan, const char *vdata)
96 {
97  int res;
98  char *data;
99  int dinterval = 0, duration = 0;
100  struct ast_channel *chan_found = NULL;
101  struct ast_channel *chan_dest = chan;
102  struct ast_channel *chan_autoservice = NULL;
104  AST_APP_ARG(digits);
105  AST_APP_ARG(dinterval);
106  AST_APP_ARG(duration);
108  );
109 
110  if (ast_strlen_zero(vdata)) {
111  ast_log(LOG_WARNING, "SendDTMF requires an argument\n");
112  return 0;
113  }
114 
115  data = ast_strdupa(vdata);
117 
118  if (ast_strlen_zero(args.digits)) {
119  ast_log(LOG_WARNING, "The digits argument is required (0-9,*#,a-d,A-D,wfF)\n");
120  return 0;
121  }
122  if (!ast_strlen_zero(args.dinterval)) {
123  ast_app_parse_timelen(args.dinterval, &dinterval, TIMELEN_MILLISECONDS);
124  }
125  if (!ast_strlen_zero(args.duration)) {
126  ast_app_parse_timelen(args.duration, &duration, TIMELEN_MILLISECONDS);
127  }
128  if (!ast_strlen_zero(args.channel)) {
129  chan_found = ast_channel_get_by_name(args.channel);
130  if (!chan_found) {
131  ast_log(LOG_WARNING, "No such channel: %s\n", args.channel);
132  return 0;
133  }
134  chan_dest = chan_found;
135  if (chan_found != chan) {
136  chan_autoservice = chan;
137  }
138  }
139  res = ast_dtmf_stream(chan_dest, chan_autoservice, args.digits,
140  dinterval <= 0 ? 250 : dinterval, duration);
141  if (chan_found) {
142  ast_channel_unref(chan_found);
143  }
144 
145  return chan_autoservice ? 0 : res;
146 }
147 
148 static int manager_play_dtmf(struct mansession *s, const struct message *m)
149 {
150  const char *channel = astman_get_header(m, "Channel");
151  const char *digit = astman_get_header(m, "Digit");
152  const char *duration = astman_get_header(m, "Duration");
153  const char *receive_s = astman_get_header(m, "Receive");
154  struct ast_channel *chan;
155  unsigned int duration_ms = 0;
156 
157  if (!(chan = ast_channel_get_by_name(channel))) {
158  astman_send_error(s, m, "Channel not found");
159  return 0;
160  }
161 
162  if (ast_strlen_zero(digit)) {
163  astman_send_error(s, m, "No digit specified");
164  chan = ast_channel_unref(chan);
165  return 0;
166  }
167 
168  if (!ast_strlen_zero(duration) && (sscanf(duration, "%30u", &duration_ms) != 1)) {
169  astman_send_error(s, m, "Could not convert Duration parameter");
170  chan = ast_channel_unref(chan);
171  return 0;
172  }
173 
174  if (ast_true(receive_s)) {
175  struct ast_frame f = { AST_FRAME_DTMF, };
176  f.len = duration_ms;
177  f.subclass.integer = *digit;
178  ast_queue_frame(chan, &f);
179  } else {
180  ast_senddigit_external(chan, *digit, duration_ms);
181  }
182 
183  chan = ast_channel_unref(chan);
184 
185  astman_send_ack(s, m, "DTMF successfully queued");
186 
187  return 0;
188 }
189 
190 static int unload_module(void)
191 {
192  int res;
193 
195  res |= ast_manager_unregister("PlayDTMF");
196 
197  return res;
198 }
199 
200 static int load_module(void)
201 {
202  int res;
203 
206 
207  return res;
208 }
209 
210 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Send DTMF digits Application");
int ast_dtmf_stream(struct ast_channel *chan, struct ast_channel *peer, const char *digits, int between, unsigned int duration)
Send a string of DTMF digits to a channel.
Definition: main/app.c:981
char digit
Main Channel structure associated with a channel.
#define AST_MODULE_INFO_STANDARD(keystr, desc)
Definition: module.h:567
Asterisk main include file. File version handling, generic pbx functions.
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2981
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
#define LOG_WARNING
Definition: logger.h:274
#define EVENT_FLAG_CALL
Definition: manager.h:72
int ast_senddigit_external(struct ast_channel *chan, char digit, unsigned int duration)
Send a DTMF digit to a channel from an external thread.
Definition: channel.c:5032
void astman_send_ack(struct mansession *s, const struct message *m, char *msg)
Send ack in manager transaction.
Definition: manager.c:3191
Definition: muted.c:95
const char * args
#define NULL
Definition: resample.c:96
static int manager_play_dtmf(struct mansession *s, const struct message *m)
Definition: app_senddtmf.c:148
#define AST_FRAME_DTMF
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx_app.c:392
struct ast_frame_subclass subclass
const char * astman_get_header(const struct message *m, char *var)
Get header from mananger transaction.
Definition: manager.c:2820
#define ast_strlen_zero(foo)
Definition: strings.h:52
static int load_module(void)
Definition: app_senddtmf.c:200
#define ast_log
Definition: astobj2.c:42
General Asterisk PBX channel definitions.
In case you didn&#39;t read that giant block of text above the mansession_session struct, the struct mansession is named this solely to keep the API the same in Asterisk. This structure really represents data that is different from Manager action to Manager action. The mansession_session pointer contained within points to session-specific data.
Definition: manager.c:1625
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
Core PBX routines and definitions.
int ast_queue_frame(struct ast_channel *chan, struct ast_frame *f)
Queue one or more frames to a channel&#39;s frame queue.
Definition: channel.c:1139
int ast_manager_unregister(const char *action)
Unregister a registered manager command.
Definition: manager.c:7258
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
Definition: main/utils.c:1951
static int senddtmf_exec(struct ast_channel *chan, const char *vdata)
Definition: app_senddtmf.c:95
static int unload_module(void)
Definition: app_senddtmf.c:190
static const char senddtmf_name[]
Definition: app_senddtmf.c:93
Data structure associated with a single frame of data.
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:3113
#define ast_manager_register_xml(action, authority, func)
Register a manager callback using XML documentation to describe the manager.
Definition: manager.h:186
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
Definition: channel.c:1454
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:3159
Asterisk module definitions.
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:626
#define AST_APP_ARG(name)
Define an application argument.