Technology independent volume control. More...
#include "asterisk.h"
#include "asterisk/module.h"
#include "asterisk/channel.h"
#include "asterisk/pbx.h"
#include "asterisk/utils.h"
#include "asterisk/audiohook.h"
#include "asterisk/app.h"
Go to the source code of this file.
Data Structures | |
struct | volume_information |
Enumerations | |
enum | volume_flags { VOLUMEFLAG_CHANGE = (1 << 1) } |
Functions | |
AST_APP_OPTIONS (volume_opts,{AST_APP_OPTION('p', VOLUMEFLAG_CHANGE),}) | |
AST_MODULE_INFO_STANDARD (ASTERISK_GPL_KEY,"Technology independent volume control") | |
static void | destroy_callback (void *data) |
static int | load_module (void) |
static int | unload_module (void) |
static int | volume_callback (struct ast_audiohook *audiohook, struct ast_channel *chan, struct ast_frame *frame, enum ast_audiohook_direction direction) |
static int | volume_write (struct ast_channel *chan, const char *cmd, char *data, const char *value) |
Variables | |
static struct ast_datastore_info | volume_datastore |
Static structure for datastore information. | |
static struct ast_custom_function | volume_function |
Technology independent volume control.
Definition in file func_volume.c.
enum volume_flags |
Definition at line 80 of file func_volume.c.
00080 { 00081 VOLUMEFLAG_CHANGE = (1 << 1), 00082 };
AST_APP_OPTIONS | ( | volume_opts | ) |
AST_MODULE_INFO_STANDARD | ( | ASTERISK_GPL_KEY | , | |
"Technology independent volume control" | ||||
) |
static void destroy_callback | ( | void * | data | ) | [static] |
Definition at line 88 of file func_volume.c.
References ast_audiohook_destroy(), ast_audiohook_detach(), ast_audiohook_lock, ast_audiohook_unlock, ast_free, and volume_information::audiohook.
00089 { 00090 struct volume_information *vi = data; 00091 00092 /* Destroy the audiohook, and destroy ourselves */ 00093 ast_audiohook_lock(&vi->audiohook); 00094 ast_audiohook_detach(&vi->audiohook); 00095 ast_audiohook_unlock(&vi->audiohook); 00096 ast_audiohook_destroy(&vi->audiohook); 00097 ast_free(vi); 00098 00099 return; 00100 }
static int load_module | ( | void | ) | [static] |
Definition at line 236 of file func_volume.c.
References ast_custom_function_register.
00237 { 00238 return ast_custom_function_register(&volume_function); 00239 }
static int unload_module | ( | void | ) | [static] |
Definition at line 231 of file func_volume.c.
References ast_custom_function_unregister().
00232 { 00233 return ast_custom_function_unregister(&volume_function); 00234 }
static int volume_callback | ( | struct ast_audiohook * | audiohook, | |
struct ast_channel * | chan, | |||
struct ast_frame * | frame, | |||
enum ast_audiohook_direction | direction | |||
) | [static] |
Definition at line 108 of file func_volume.c.
References AST_AUDIOHOOK_DIRECTION_READ, AST_AUDIOHOOK_STATUS_DONE, ast_channel_datastore_find(), ast_frame_adjust_volume(), AST_FRAME_DTMF, AST_FRAME_VOICE, ast_test_flag, ast_datastore::data, ast_frame::frametype, ast_frame_subclass::integer, volume_information::rx_gain, ast_audiohook::status, ast_frame::subclass, volume_information::tx_gain, and VOLUMEFLAG_CHANGE.
Referenced by volume_write().
00109 { 00110 struct ast_datastore *datastore = NULL; 00111 struct volume_information *vi = NULL; 00112 int *gain = NULL; 00113 00114 /* If the audiohook is stopping it means the channel is shutting down.... but we let the datastore destroy take care of it */ 00115 if (audiohook->status == AST_AUDIOHOOK_STATUS_DONE) 00116 return 0; 00117 00118 /* Grab datastore which contains our gain information */ 00119 if (!(datastore = ast_channel_datastore_find(chan, &volume_datastore, NULL))) 00120 return 0; 00121 00122 vi = datastore->data; 00123 00124 /* If this is DTMF then allow them to increase/decrease the gains */ 00125 if (ast_test_flag(vi, VOLUMEFLAG_CHANGE)) { 00126 if (frame->frametype == AST_FRAME_DTMF) { 00127 /* Only use DTMF coming from the source... not going to it */ 00128 if (direction != AST_AUDIOHOOK_DIRECTION_READ) 00129 return 0; 00130 if (frame->subclass.integer == '*') { 00131 vi->tx_gain += 1; 00132 vi->rx_gain += 1; 00133 } else if (frame->subclass.integer == '#') { 00134 vi->tx_gain -= 1; 00135 vi->rx_gain -= 1; 00136 } 00137 } 00138 } 00139 00140 00141 if (frame->frametype == AST_FRAME_VOICE) { 00142 /* Based on direction of frame grab the gain, and confirm it is applicable */ 00143 if (!(gain = (direction == AST_AUDIOHOOK_DIRECTION_READ) ? &vi->rx_gain : &vi->tx_gain) || !*gain) 00144 return 0; 00145 /* Apply gain to frame... easy as pi */ 00146 ast_frame_adjust_volume(frame, *gain); 00147 } 00148 00149 return 0; 00150 }
static int volume_write | ( | struct ast_channel * | chan, | |
const char * | cmd, | |||
char * | data, | |||
const char * | value | |||
) | [static] |
Definition at line 152 of file func_volume.c.
References args, AST_APP_ARG, ast_app_parse_options(), ast_audiohook_attach(), ast_audiohook_init(), AST_AUDIOHOOK_TYPE_MANIPULATE, AST_AUDIOHOOK_WANTS_DTMF, ast_calloc, ast_channel_datastore_add(), ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, ast_datastore_alloc, ast_datastore_free(), AST_DECLARE_APP_ARGS, ast_log(), ast_set_flag, AST_STANDARD_APP_ARGS, ast_strlen_zero(), volume_information::audiohook, ast_datastore::data, ast_flags::flags, volume_information::flags, LOG_ERROR, LOG_WARNING, ast_audiohook::manipulate_callback, volume_information::rx_gain, volume_information::tx_gain, and volume_callback().
00153 { 00154 struct ast_datastore *datastore = NULL; 00155 struct volume_information *vi = NULL; 00156 int is_new = 0; 00157 00158 /* Separate options from argument */ 00159 00160 AST_DECLARE_APP_ARGS(args, 00161 AST_APP_ARG(direction); 00162 AST_APP_ARG(options); 00163 ); 00164 00165 if (!chan) { 00166 ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd); 00167 return -1; 00168 } 00169 00170 AST_STANDARD_APP_ARGS(args, data); 00171 00172 ast_channel_lock(chan); 00173 if (!(datastore = ast_channel_datastore_find(chan, &volume_datastore, NULL))) { 00174 ast_channel_unlock(chan); 00175 /* Allocate a new datastore to hold the reference to this volume and audiohook information */ 00176 if (!(datastore = ast_datastore_alloc(&volume_datastore, NULL))) 00177 return 0; 00178 if (!(vi = ast_calloc(1, sizeof(*vi)))) { 00179 ast_datastore_free(datastore); 00180 return 0; 00181 } 00182 ast_audiohook_init(&vi->audiohook, AST_AUDIOHOOK_TYPE_MANIPULATE, "Volume"); 00183 vi->audiohook.manipulate_callback = volume_callback; 00184 ast_set_flag(&vi->audiohook, AST_AUDIOHOOK_WANTS_DTMF); 00185 is_new = 1; 00186 } else { 00187 ast_channel_unlock(chan); 00188 vi = datastore->data; 00189 } 00190 00191 /* Adjust gain on volume information structure */ 00192 if (ast_strlen_zero(args.direction)) { 00193 ast_log(LOG_ERROR, "Direction must be specified for VOLUME function\n"); 00194 return -1; 00195 } 00196 00197 if (!strcasecmp(args.direction, "tx")) { 00198 vi->tx_gain = atoi(value); 00199 } else if (!strcasecmp(args.direction, "rx")) { 00200 vi->rx_gain = atoi(value); 00201 } else { 00202 ast_log(LOG_ERROR, "Direction must be either RX or TX\n"); 00203 } 00204 00205 if (is_new) { 00206 datastore->data = vi; 00207 ast_channel_lock(chan); 00208 ast_channel_datastore_add(chan, datastore); 00209 ast_channel_unlock(chan); 00210 ast_audiohook_attach(chan, &vi->audiohook); 00211 } 00212 00213 /* Add Option data to struct */ 00214 00215 if (!ast_strlen_zero(args.options)) { 00216 struct ast_flags flags = { 0 }; 00217 ast_app_parse_options(volume_opts, &flags, NULL, args.options); 00218 vi->flags = flags.flags; 00219 } else { 00220 vi->flags = 0; 00221 } 00222 00223 return 0; 00224 }
struct ast_datastore_info volume_datastore [static] |
{ .type = "volume", .destroy = destroy_callback }
Static structure for datastore information.
Definition at line 103 of file func_volume.c.
struct ast_custom_function volume_function [static] |
{ .name = "VOLUME", .write = volume_write, }
Definition at line 226 of file func_volume.c.