Merge "README-SERIOUSLY.bestpractices.md: Speling correetions."
[asterisk/asterisk.git] / apps / app_senddtmf.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2005, Digium, Inc.
5  *
6  * Mark Spencer <markster@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 App to send DTMF digits
22  *
23  * \author Mark Spencer <markster@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/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                 </syntax>
84                 <description>
85                         <para>Plays a dtmf digit on the specified channel.</para>
86                 </description>
87         </manager>
88  ***/
89
90 static const char senddtmf_name[] = "SendDTMF";
91
92 static int senddtmf_exec(struct ast_channel *chan, const char *vdata)
93 {
94         int res;
95         char *data;
96         int dinterval = 0, duration = 0;
97         struct ast_channel *chan_found = NULL;
98         struct ast_channel *chan_dest = chan;
99         struct ast_channel *chan_autoservice = NULL;
100         AST_DECLARE_APP_ARGS(args,
101                 AST_APP_ARG(digits);
102                 AST_APP_ARG(dinterval);
103                 AST_APP_ARG(duration);
104                 AST_APP_ARG(channel);
105         );
106
107         if (ast_strlen_zero(vdata)) {
108                 ast_log(LOG_WARNING, "SendDTMF requires an argument\n");
109                 return 0;
110         }
111
112         data = ast_strdupa(vdata);
113         AST_STANDARD_APP_ARGS(args, data);
114
115         if (ast_strlen_zero(args.digits)) {
116                 ast_log(LOG_WARNING, "The digits argument is required (0-9,*#,a-d,A-D,wfF)\n");
117                 return 0;
118         }
119         if (!ast_strlen_zero(args.dinterval)) {
120                 ast_app_parse_timelen(args.dinterval, &dinterval, TIMELEN_MILLISECONDS);
121         }
122         if (!ast_strlen_zero(args.duration)) {
123                 ast_app_parse_timelen(args.duration, &duration, TIMELEN_MILLISECONDS);
124         }
125         if (!ast_strlen_zero(args.channel)) {
126                 chan_found = ast_channel_get_by_name(args.channel);
127                 if (!chan_found) {
128                         ast_log(LOG_WARNING, "No such channel: %s\n", args.channel);
129                         return 0;
130                 }
131                 chan_dest = chan_found;
132                 if (chan_found != chan) {
133                         chan_autoservice = chan;
134                 }
135         }
136         res = ast_dtmf_stream(chan_dest, chan_autoservice, args.digits,
137                 dinterval <= 0 ? 250 : dinterval, duration);
138         if (chan_found) {
139                 ast_channel_unref(chan_found);
140         }
141
142         return chan_autoservice ? 0 : res;
143 }
144
145 static int manager_play_dtmf(struct mansession *s, const struct message *m)
146 {
147         const char *channel = astman_get_header(m, "Channel");
148         const char *digit = astman_get_header(m, "Digit");
149         const char *duration = astman_get_header(m, "Duration");
150         struct ast_channel *chan;
151         unsigned int duration_ms = 0;
152
153         if (!(chan = ast_channel_get_by_name(channel))) {
154                 astman_send_error(s, m, "Channel not found");
155                 return 0;
156         }
157
158         if (ast_strlen_zero(digit)) {
159                 astman_send_error(s, m, "No digit specified");
160                 chan = ast_channel_unref(chan);
161                 return 0;
162         }
163
164         if (!ast_strlen_zero(duration) && (sscanf(duration, "%30u", &duration_ms) != 1)) {
165                 astman_send_error(s, m, "Could not convert Duration parameter");
166                 chan = ast_channel_unref(chan);
167                 return 0;
168         }
169
170         ast_senddigit_external(chan, *digit, duration_ms);
171
172         chan = ast_channel_unref(chan);
173
174         astman_send_ack(s, m, "DTMF successfully queued");
175
176         return 0;
177 }
178
179 static int unload_module(void)
180 {
181         int res;
182
183         res = ast_unregister_application(senddtmf_name);
184         res |= ast_manager_unregister("PlayDTMF");
185
186         return res;
187 }
188
189 static int load_module(void)
190 {
191         int res;
192
193         res = ast_manager_register_xml("PlayDTMF", EVENT_FLAG_CALL, manager_play_dtmf);
194         res |= ast_register_application_xml(senddtmf_name, senddtmf_exec);
195
196         return res;
197 }
198
199 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Send DTMF digits Application");