Merge "res_pjsip/res_pjsip_callerid: NULL check on caller id name string"
[asterisk/asterisk.git] / res / res_mutestream.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2009, Olle E. Johansson
5  *
6  * Olle E. Johansson <oej@edvina.net>
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 MUTESTREAM audiohooks
22  *
23  * \author Olle E. Johansson <oej@edvina.net>
24  *
25  *  \ingroup functions
26  *
27  * \note This module only handles audio streams today, but can easily be appended to also
28  * zero out text streams if there's an application for it.
29  * When we know and understands what happens if we zero out video, we can do that too.
30  */
31
32 /*** MODULEINFO
33         <support_level>core</support_level>
34  ***/
35
36 #include "asterisk.h"
37
38 #include "asterisk/options.h"
39 #include "asterisk/logger.h"
40 #include "asterisk/channel.h"
41 #include "asterisk/module.h"
42 #include "asterisk/config.h"
43 #include "asterisk/file.h"
44 #include "asterisk/pbx.h"
45 #include "asterisk/frame.h"
46 #include "asterisk/utils.h"
47 #include "asterisk/audiohook.h"
48 #include "asterisk/manager.h"
49
50 /*** DOCUMENTATION
51         <function name="MUTEAUDIO" language="en_US">
52                 <synopsis>
53                         Muting audio streams in the channel
54                 </synopsis>
55                 <syntax>
56                         <parameter name="direction" required="true">
57                                 <para>Must be one of </para>
58                                 <enumlist>
59                                         <enum name="in">
60                                                 <para>Inbound stream (to the PBX)</para>
61                                         </enum>
62                                         <enum name="out">
63                                                 <para>Outbound stream (from the PBX)</para>
64                                         </enum>
65                                         <enum name="all">
66                                                 <para>Both streams</para>
67                                         </enum>
68                                 </enumlist>
69                         </parameter>
70                 </syntax>
71                 <description>
72                         <para>The MUTEAUDIO function can be used to mute inbound (to the PBX) or outbound audio in a call.
73                         </para>
74                         <para>Examples:
75                         </para>
76                         <para>
77                         MUTEAUDIO(in)=on
78                         </para>
79                         <para>
80                         MUTEAUDIO(in)=off
81                         </para>
82                 </description>
83         </function>
84         <manager name="MuteAudio" language="en_US">
85                 <synopsis>
86                         Mute an audio stream.
87                 </synopsis>
88                 <syntax>
89                         <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
90                         <parameter name="Channel" required="true">
91                                 <para>The channel you want to mute.</para>
92                         </parameter>
93                         <parameter name="Direction" required="true">
94                                 <enumlist>
95                                         <enum name="in">
96                                                 <para>Set muting on inbound audio stream. (to the PBX)</para>
97                                         </enum>
98                                         <enum name="out">
99                                                 <para>Set muting on outbound audio stream. (from the PBX)</para>
100                                         </enum>
101                                         <enum name="all">
102                                                 <para>Set muting on inbound and outbound audio streams.</para>
103                                         </enum>
104                                 </enumlist>
105                         </parameter>
106                         <parameter name="State" required="true">
107                                 <enumlist>
108                                         <enum name="on">
109                                                 <para>Turn muting on.</para>
110                                         </enum>
111                                         <enum name="off">
112                                                 <para>Turn muting off.</para>
113                                         </enum>
114                                 </enumlist>
115                         </parameter>
116                 </syntax>
117                 <description>
118                         <para>Mute an incoming or outgoing audio stream on a channel.</para>
119                 </description>
120         </manager>
121  ***/
122
123
124 static int mute_channel(struct ast_channel *chan, const char *direction, int mute)
125 {
126         unsigned int mute_direction = 0;
127         enum ast_frame_type frametype = AST_FRAME_VOICE;
128         int ret = 0;
129
130         if (!strcmp(direction, "in")) {
131                 mute_direction = AST_MUTE_DIRECTION_READ;
132         } else if (!strcmp(direction, "out")) {
133                 mute_direction = AST_MUTE_DIRECTION_WRITE;
134         } else if (!strcmp(direction, "all")) {
135                 mute_direction = AST_MUTE_DIRECTION_READ | AST_MUTE_DIRECTION_WRITE;
136         } else {
137                 return -1;
138         }
139
140         ast_channel_lock(chan);
141
142         if (mute) {
143                 ret = ast_channel_suppress(chan, mute_direction, frametype);
144         } else {
145                 ret = ast_channel_unsuppress(chan, mute_direction, frametype);
146         }
147
148         ast_channel_unlock(chan);
149
150         return ret;
151 }
152
153 /*! \brief Mute dialplan function */
154 static int func_mute_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
155 {
156         if (!chan) {
157                 ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
158                 return -1;
159         }
160
161         return mute_channel(chan, data, ast_true(value));
162 }
163
164 /* Function for debugging - might be useful */
165 static struct ast_custom_function mute_function = {
166         .name = "MUTEAUDIO",
167         .write = func_mute_write,
168 };
169
170 static int manager_mutestream(struct mansession *s, const struct message *m)
171 {
172         const char *channel = astman_get_header(m, "Channel");
173         const char *id = astman_get_header(m,"ActionID");
174         const char *state = astman_get_header(m,"State");
175         const char *direction = astman_get_header(m,"Direction");
176         char id_text[256];
177         struct ast_channel *c = NULL;
178
179         if (ast_strlen_zero(channel)) {
180                 astman_send_error(s, m, "Channel not specified");
181                 return 0;
182         }
183         if (ast_strlen_zero(state)) {
184                 astman_send_error(s, m, "State not specified");
185                 return 0;
186         }
187         if (ast_strlen_zero(direction)) {
188                 astman_send_error(s, m, "Direction not specified");
189                 return 0;
190         }
191         /* Ok, we have everything */
192
193         c = ast_channel_get_by_name(channel);
194         if (!c) {
195                 astman_send_error(s, m, "No such channel");
196                 return 0;
197         }
198
199         if (mute_channel(c, direction, ast_true(state))) {
200                 astman_send_error(s, m, "Failed to mute/unmute stream");
201                 ast_channel_unref(c);
202                 return 0;
203         }
204
205         ast_channel_unref(c);
206
207         if (!ast_strlen_zero(id)) {
208                 snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", id);
209         } else {
210                 id_text[0] = '\0';
211         }
212         astman_append(s, "Response: Success\r\n"
213                 "%s"
214                 "\r\n", id_text);
215         return 0;
216 }
217
218
219 static int load_module(void)
220 {
221         int res;
222
223         res = ast_custom_function_register(&mute_function);
224         res |= ast_manager_register_xml("MuteAudio", EVENT_FLAG_SYSTEM, manager_mutestream);
225
226         return (res ? AST_MODULE_LOAD_DECLINE : AST_MODULE_LOAD_SUCCESS);
227 }
228
229 static int unload_module(void)
230 {
231         ast_custom_function_unregister(&mute_function);
232         /* Unregister AMI actions */
233         ast_manager_unregister("MuteAudio");
234
235         return 0;
236 }
237
238 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Mute audio stream resources");