res_mutestream.c 6.0 KB

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