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 231 of file func_volume.c.
References ast_custom_function_register.
00232 { 00233 return ast_custom_function_register(&volume_function); 00234 }
static int unload_module | ( | void | ) | [static] |
Definition at line 226 of file func_volume.c.
References ast_custom_function_unregister().
00227 { 00228 return ast_custom_function_unregister(&volume_function); 00229 }
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, 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 AST_STANDARD_APP_ARGS(args, data); 00166 00167 ast_channel_lock(chan); 00168 if (!(datastore = ast_channel_datastore_find(chan, &volume_datastore, NULL))) { 00169 ast_channel_unlock(chan); 00170 /* Allocate a new datastore to hold the reference to this volume and audiohook information */ 00171 if (!(datastore = ast_datastore_alloc(&volume_datastore, NULL))) 00172 return 0; 00173 if (!(vi = ast_calloc(1, sizeof(*vi)))) { 00174 ast_datastore_free(datastore); 00175 return 0; 00176 } 00177 ast_audiohook_init(&vi->audiohook, AST_AUDIOHOOK_TYPE_MANIPULATE, "Volume"); 00178 vi->audiohook.manipulate_callback = volume_callback; 00179 ast_set_flag(&vi->audiohook, AST_AUDIOHOOK_WANTS_DTMF); 00180 is_new = 1; 00181 } else { 00182 ast_channel_unlock(chan); 00183 vi = datastore->data; 00184 } 00185 00186 /* Adjust gain on volume information structure */ 00187 if (ast_strlen_zero(args.direction)) { 00188 ast_log(LOG_ERROR, "Direction must be specified for VOLUME function\n"); 00189 return -1; 00190 } 00191 00192 if (!strcasecmp(args.direction, "tx")) { 00193 vi->tx_gain = atoi(value); 00194 } else if (!strcasecmp(args.direction, "rx")) { 00195 vi->rx_gain = atoi(value); 00196 } else { 00197 ast_log(LOG_ERROR, "Direction must be either RX or TX\n"); 00198 } 00199 00200 if (is_new) { 00201 datastore->data = vi; 00202 ast_channel_lock(chan); 00203 ast_channel_datastore_add(chan, datastore); 00204 ast_channel_unlock(chan); 00205 ast_audiohook_attach(chan, &vi->audiohook); 00206 } 00207 00208 /* Add Option data to struct */ 00209 00210 if (!ast_strlen_zero(args.options)) { 00211 struct ast_flags flags = { 0 }; 00212 ast_app_parse_options(volume_opts, &flags, NULL, args.options); 00213 vi->flags = flags.flags; 00214 } else { 00215 vi->flags = 0; 00216 } 00217 00218 return 0; 00219 }
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 221 of file func_volume.c.