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: 89545 $")
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 ast_channel_lock(chan);
00239 if (!(datastore = ast_channel_datastore_find(chan, &mute_datastore, NULL))) {
00240 if (!(datastore = initialize_mutehook(chan))) {
00241 ast_channel_unlock(chan);
00242 return 0;
00243 }
00244 is_new = 1;
00245 }
00246 mute = datastore->data;
00247
00248 turnon = ast_true(value);
00249 if (!strcasecmp(data, "out")) {
00250 mute->mute_write = turnon;
00251 ast_debug(1, "%s channel - outbound \n", turnon ? "Muting" : "Unmuting");
00252 } else if (!strcasecmp(data, "in")) {
00253 mute->mute_read = turnon;
00254 ast_debug(1, "%s channel - inbound \n", turnon ? "Muting" : "Unmuting");
00255 } else if (!strcasecmp(data,"all")) {
00256 mute->mute_write = mute->mute_read = turnon;
00257 }
00258
00259 if (is_new) {
00260 if (mute_add_audiohook(chan, mute, datastore)) {
00261
00262 ast_datastore_free(datastore);
00263 ast_free(mute);
00264 }
00265 }
00266 ast_channel_unlock(chan);
00267
00268 return 0;
00269 }
00270
00271
00272 static struct ast_custom_function mute_function = {
00273 .name = "MUTEAUDIO",
00274 .write = func_mute_write,
00275 };
00276
00277 static int manager_mutestream(struct mansession *s, const struct message *m)
00278 {
00279 const char *channel = astman_get_header(m, "Channel");
00280 const char *id = astman_get_header(m,"ActionID");
00281 const char *state = astman_get_header(m,"State");
00282 const char *direction = astman_get_header(m,"Direction");
00283 char id_text[256];
00284 struct ast_channel *c = NULL;
00285 struct ast_datastore *datastore = NULL;
00286 struct mute_information *mute = NULL;
00287 int is_new = 0;
00288 int turnon;
00289
00290 if (ast_strlen_zero(channel)) {
00291 astman_send_error(s, m, "Channel not specified");
00292 return 0;
00293 }
00294 if (ast_strlen_zero(state)) {
00295 astman_send_error(s, m, "State not specified");
00296 return 0;
00297 }
00298 if (ast_strlen_zero(direction)) {
00299 astman_send_error(s, m, "Direction not specified");
00300 return 0;
00301 }
00302
00303
00304 c = ast_channel_get_by_name(channel);
00305 if (!c) {
00306 astman_send_error(s, m, "No such channel");
00307 return 0;
00308 }
00309
00310 ast_channel_lock(c);
00311
00312 if (!(datastore = ast_channel_datastore_find(c, &mute_datastore, NULL))) {
00313 if (!(datastore = initialize_mutehook(c))) {
00314 ast_channel_unlock(c);
00315 ast_channel_unref(c);
00316 astman_send_error(s, m, "Memory allocation failure");
00317 return 0;
00318 }
00319 is_new = 1;
00320 }
00321 mute = datastore->data;
00322
00323 turnon = ast_true(state);
00324 if (!strcasecmp(direction, "in")) {
00325 mute->mute_read = turnon;
00326 } else if (!strcasecmp(direction, "out")) {
00327 mute->mute_write = turnon;
00328 } else if (!strcasecmp(direction, "all")) {
00329 mute->mute_read = mute->mute_write = turnon;
00330 }
00331
00332 if (is_new) {
00333 if (mute_add_audiohook(c, mute, datastore)) {
00334
00335 ast_datastore_free(datastore);
00336 ast_free(mute);
00337 ast_channel_unlock(c);
00338 ast_channel_unref(c);
00339 astman_send_error(s, m, "Couldn't add mute audiohook");
00340 return 0;
00341 }
00342 }
00343 ast_channel_unlock(c);
00344 ast_channel_unref(c);
00345
00346 if (!ast_strlen_zero(id)) {
00347 snprintf(id_text, sizeof(id_text), "ActionID: %s\r\n", id);
00348 } else {
00349 id_text[0] = '\0';
00350 }
00351 astman_append(s, "Response: Success\r\n"
00352 "%s"
00353 "\r\n", id_text);
00354 return 0;
00355 }
00356
00357
00358 static int load_module(void)
00359 {
00360 int res;
00361
00362 res = ast_custom_function_register(&mute_function);
00363 res |= ast_manager_register_xml("MuteAudio", EVENT_FLAG_SYSTEM, manager_mutestream);
00364
00365 return (res ? AST_MODULE_LOAD_DECLINE : AST_MODULE_LOAD_SUCCESS);
00366 }
00367
00368 static int unload_module(void)
00369 {
00370 ast_custom_function_unregister(&mute_function);
00371
00372 ast_manager_unregister("MuteAudio");
00373
00374 return 0;
00375 }
00376
00377 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Mute audio stream resources");