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