func_volume.c
Go to the documentation of this file.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 #include "asterisk.h"
00030
00031 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 135680 $")
00032
00033 #include "asterisk/module.h"
00034 #include "asterisk/channel.h"
00035 #include "asterisk/pbx.h"
00036 #include "asterisk/utils.h"
00037 #include "asterisk/audiohook.h"
00038
00039 struct volume_information {
00040 struct ast_audiohook audiohook;
00041 int tx_gain;
00042 int rx_gain;
00043 };
00044
00045 static void destroy_callback(void *data)
00046 {
00047 struct volume_information *vi = data;
00048
00049
00050 ast_audiohook_destroy(&vi->audiohook);
00051 free(vi);
00052
00053 return;
00054 }
00055
00056
00057 static const struct ast_datastore_info volume_datastore = {
00058 .type = "volume",
00059 .destroy = destroy_callback
00060 };
00061
00062 static int volume_callback(struct ast_audiohook *audiohook, struct ast_channel *chan, struct ast_frame *frame, enum ast_audiohook_direction direction)
00063 {
00064 struct ast_datastore *datastore = NULL;
00065 struct volume_information *vi = NULL;
00066 int *gain = NULL;
00067
00068
00069 if (audiohook->status == AST_AUDIOHOOK_STATUS_DONE)
00070 return 0;
00071
00072
00073 if (!(datastore = ast_channel_datastore_find(chan, &volume_datastore, NULL)))
00074 return 0;
00075
00076 vi = datastore->data;
00077
00078
00079 if (frame->frametype == AST_FRAME_DTMF) {
00080
00081 if (direction != AST_AUDIOHOOK_DIRECTION_READ)
00082 return 0;
00083 if (frame->subclass == '*') {
00084 vi->tx_gain += 1;
00085 vi->rx_gain += 1;
00086 } else if (frame->subclass == '#') {
00087 vi->tx_gain -= 1;
00088 vi->rx_gain -= 1;
00089 }
00090 } else if (frame->frametype == AST_FRAME_VOICE) {
00091
00092 if (!(gain = (direction == AST_AUDIOHOOK_DIRECTION_READ) ? &vi->rx_gain : &vi->tx_gain) || !*gain)
00093 return 0;
00094
00095 ast_frame_adjust_volume(frame, *gain);
00096 }
00097
00098 return 0;
00099 }
00100
00101 static int volume_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
00102 {
00103 struct ast_datastore *datastore = NULL;
00104 struct volume_information *vi = NULL;
00105 int is_new = 0;
00106
00107 if (!(datastore = ast_channel_datastore_find(chan, &volume_datastore, NULL))) {
00108
00109 if (!(datastore = ast_datastore_alloc(&volume_datastore, NULL)))
00110 return 0;
00111 if (!(vi = ast_calloc(1, sizeof(*vi)))) {
00112 ast_datastore_free(datastore);
00113 return 0;
00114 }
00115 ast_audiohook_init(&vi->audiohook, AST_AUDIOHOOK_TYPE_MANIPULATE, "Volume");
00116 vi->audiohook.manipulate_callback = volume_callback;
00117 ast_set_flag(&vi->audiohook, AST_AUDIOHOOK_WANTS_DTMF);
00118 is_new = 1;
00119 } else {
00120 vi = datastore->data;
00121 }
00122
00123
00124 if (!strcasecmp(data, "tx"))
00125 vi->tx_gain = atoi(value);
00126 else if (!strcasecmp(data, "rx"))
00127 vi->rx_gain = atoi(value);
00128
00129 if (is_new) {
00130 datastore->data = vi;
00131 ast_channel_datastore_add(chan, datastore);
00132 ast_audiohook_attach(chan, &vi->audiohook);
00133 }
00134
00135 return 0;
00136 }
00137
00138 static struct ast_custom_function volume_function = {
00139 .name = "VOLUME",
00140 .synopsis = "Set the TX or RX volume of a channel",
00141 .syntax = "VOLUME(TX|RX)",
00142 .desc =
00143 " The VOLUME function can be used to increase or decrease the tx or\n"
00144 "rx gain of any channel. For example:\n"
00145 " Set(VOLUME(TX)=3)\n"
00146 " Set(VOLUME(RX)=2)\n",
00147 .write = volume_write,
00148 };
00149
00150 static int unload_module(void)
00151 {
00152 return ast_custom_function_unregister(&volume_function);
00153 }
00154
00155 static int load_module(void)
00156 {
00157 return ast_custom_function_register(&volume_function);
00158 }
00159
00160 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Technology independent volume control");