00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include "asterisk.h"
00037
00038 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 411314 $")
00039
00040 #include "asterisk/options.h"
00041 #include "asterisk/logger.h"
00042 #include "asterisk/channel.h"
00043 #include "asterisk/module.h"
00044 #include "asterisk/config.h"
00045 #include "asterisk/file.h"
00046 #include "asterisk/pbx.h"
00047 #include "asterisk/frame.h"
00048 #include "asterisk/utils.h"
00049 #include "asterisk/audiohook.h"
00050 #include "asterisk/manager.h"
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127 struct mute_information {
00128 struct ast_audiohook audiohook;
00129 int mute_write;
00130 int mute_read;
00131 };
00132
00133
00134
00135 static void destroy_callback(void *data)
00136 {
00137 struct mute_information *mute = data;
00138
00139
00140 ast_audiohook_destroy(&mute->audiohook);
00141 ast_free(mute);
00142 ast_module_unref(ast_module_info->self);
00143 }
00144
00145
00146 static const struct ast_datastore_info mute_datastore = {
00147 .type = "mute",
00148 .destroy = destroy_callback
00149 };
00150
00151
00152 static int mute_callback(struct ast_audiohook *audiohook, struct ast_channel *chan, struct ast_frame *frame, enum ast_audiohook_direction direction)
00153 {
00154 struct ast_datastore *datastore = NULL;
00155 struct mute_information *mute = NULL;
00156
00157
00158
00159 if (audiohook->status == AST_AUDIOHOOK_STATUS_DONE) {
00160 return 0;
00161 }
00162
00163 ast_channel_lock(chan);
00164
00165 if (!(datastore = ast_channel_datastore_find(chan, &mute_datastore, NULL))) {
00166 ast_channel_unlock(chan);
00167 ast_debug(2, "Can't find any datastore to use. Bad. \n");
00168 return 0;
00169 }
00170
00171 mute = datastore->data;
00172
00173
00174
00175 if (frame->frametype == AST_FRAME_VOICE) {
00176 ast_debug(2, "Audio frame - direction %s mute READ %s WRITE %s\n", direction == AST_AUDIOHOOK_DIRECTION_READ ? "read" : "write", mute->mute_read ? "on" : "off", mute->mute_write ? "on" : "off");
00177
00178
00179 if ((direction == AST_AUDIOHOOK_DIRECTION_READ && mute->mute_read) || (direction == AST_AUDIOHOOK_DIRECTION_WRITE && mute->mute_write)) {
00180
00181 ast_frame_clear(frame);
00182 }
00183 }
00184 ast_channel_unlock(chan);
00185
00186 return 0;
00187 }
00188
00189
00190
00191
00192 static struct ast_datastore *initialize_mutehook(struct ast_channel *chan)
00193 {
00194 struct ast_datastore *datastore = NULL;
00195 struct mute_information *mute = NULL;
00196
00197 ast_debug(2, "Initializing new Mute Audiohook \n");
00198
00199
00200 if (!(datastore = ast_datastore_alloc(&mute_datastore, NULL))) {
00201 return NULL;
00202 }
00203
00204 if (!(mute = ast_calloc(1, sizeof(*mute)))) {
00205 ast_datastore_free(datastore);
00206 return NULL;
00207 }
00208 ast_audiohook_init(&mute->audiohook, AST_AUDIOHOOK_TYPE_MANIPULATE, "Mute", AST_AUDIOHOOK_MANIPULATE_ALL_RATES);
00209 mute->audiohook.manipulate_callback = mute_callback;
00210 datastore->data = mute;
00211 return datastore;
00212 }
00213
00214
00215
00216
00217 static int mute_add_audiohook(struct ast_channel *chan, struct mute_information *mute, struct ast_datastore *datastore)
00218 {
00219
00220 ast_channel_datastore_add(chan, datastore);
00221 if (ast_audiohook_attach(chan, &mute->audiohook)) {
00222 ast_log(LOG_ERROR, "Failed to attach audiohook for muting channel %s\n", ast_channel_name(chan));
00223 return -1;
00224 }
00225 ast_module_ref(ast_module_info->self);
00226 ast_debug(2, "Initialized audiohook on channel %s\n", ast_channel_name(chan));
00227 return 0;
00228 }
00229
00230
00231 static int func_mute_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
00232 {
00233 struct ast_datastore *datastore = NULL;
00234 struct mute_information *mute = NULL;
00235 int is_new = 0;
00236 int turnon;
00237
00238 if (!chan) {
00239 ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
00240 return -1;
00241 }
00242
00243 ast_channel_lock(chan);
00244 if (!(datastore = ast_channel_datastore_find(chan, &mute_datastore, NULL))) {
00245 if (!(datastore = initialize_mutehook(chan))) {
00246 ast_channel_unlock(chan);
00247 return 0;
00248 }
00249 is_new = 1;
00250 }
00251 mute = datastore->data;
00252
00253 turnon = ast_true(value);
00254 if (!strcasecmp(data, "out")) {
00255 mute->mute_write = turnon;
00256 ast_debug(1, "%s channel - outbound \n", turnon ? "Muting" : "Unmuting");
00257 } else if (!strcasecmp(data, "in")) {
00258 mute->mute_read = turnon;
00259 ast_debug(1, "%s channel - inbound \n", turnon ? "Muting" : "Unmuting");
00260 } else if (!strcasecmp(data,"all")) {
00261 mute->mute_write = mute->mute_read = turnon;
00262 }
00263
00264 if (is_new) {
00265 if (mute_add_audiohook(chan, mute, datastore)) {
00266
00267 ast_datastore_free(datastore);
00268 ast_free(mute);
00269 }
00270 }
00271 ast_channel_unlock(chan);
00272
00273 return 0;
00274 }
00275
00276
00277 static struct ast_custom_function mute_function = {
00278 .name = "MUTEAUDIO",
00279 .write = func_mute_write,
00280 };
00281
00282 static int manager_mutestream(struct mansession *s, const struct message *m)
00283 {
00284 const char *channel = astman_get_header(m, "Channel");
00285 const char *id = astman_get_header(m,"ActionID");
00286 const char *state = astman_get_header(m,"State");
00287 const char *direction = astman_get_header(m,"Direction");
00288 char id_text[256];
00289 struct ast_channel *c = NULL;
00290 struct ast_datastore *datastore = NULL;
00291 struct mute_information *mute = NULL;
00292 int is_new = 0;
00293 int turnon;
00294
00295 if (ast_strlen_zero(channel)) {
00296 astman_send_error(s, m, "Channel not specified");
00297 return 0;
00298 }
00299 if (ast_strlen_zero(state)) {
00300 astman_send_error(s, m, "State not specified");
00301 return 0;
00302 }
00303 if (ast_strlen_zero(direction)) {
00304 astman_send_error(s, m, "Direction not specified");
00305 return 0;
00306 }
00307
00308
00309 c = ast_channel_get_by_name(channel);
00310 if (!c) {
00311 astman_send_error(s, m, "No such channel");
00312 return 0;
00313 }
00314
00315 ast_channel_lock(c);
00316
00317 if (!(datastore = ast_channel_datastore_find(c, &mute_datastore, NULL))) {
00318 if (!(datastore = initialize_mutehook(c))) {
00319 ast_channel_unlock(c);
00320 ast_channel_unref(c);
00321 astman_send_error(s, m, "Memory allocation failure");
00322 return 0;
00323 }
00324 is_new = 1;
00325 }
00326 mute = datastore->data;
00327
00328 turnon = ast_true(state);
00329 if (!strcasecmp(direction, "in")) {
00330 mute->mute_read = turnon;
00331 } else if (!strcasecmp(direction, "out")) {
00332 mute->mute_write = turnon;
00333 } else if (!strcasecmp(direction, "all")) {
00334 mute->mute_read = mute->mute_write = turnon;
00335 }
00336
00337 if (is_new) {
00338 if (mute_add_audiohook(c, mute, datastore)) {
00339
00340 ast_datastore_free(datastore);
00341 ast_free(mute);
00342 ast_channel_unlock(c);
00343 ast_channel_unref(c);
00344 astman_send_error(s, m, "Couldn't add mute audiohook");
00345 return 0;
00346 }
00347 }
00348 ast_channel_unlock(c);
00349 ast_channel_unref(c);
00350
00351 if (!ast_strlen_zero(id)) {
00352 snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", id);
00353 } else {
00354 id_text[0] = '\0';
00355 }
00356 astman_append(s, "Response: Success\r\n"
00357 "%s"
00358 "\r\n", id_text);
00359 return 0;
00360 }
00361
00362
00363 static int load_module(void)
00364 {
00365 int res;
00366
00367 res = ast_custom_function_register(&mute_function);
00368 res |= ast_manager_register_xml("MuteAudio", EVENT_FLAG_SYSTEM, manager_mutestream);
00369
00370 return (res ? AST_MODULE_LOAD_DECLINE : AST_MODULE_LOAD_SUCCESS);
00371 }
00372
00373 static int unload_module(void)
00374 {
00375 ast_custom_function_unregister(&mute_function);
00376
00377 ast_manager_unregister("MuteAudio");
00378
00379 return 0;
00380 }
00381
00382 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Mute audio stream resources");