Asterisk - The Open Source Telephony Project  18.5.0
Data Structures | Enumerations | Functions | Variables
func_volume.c File Reference

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"
Include dependency graph for func_volume.c:

Go to the source code of this file.

Data Structures

struct  volume_information
 

Enumerations

enum  volume_flags { VOLUMEFLAG_CHANGE = (1 << 1) }
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
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_read (struct ast_channel *chan, const char *cmd, char *data, char *buffer, size_t buflen)
 
static int volume_write (struct ast_channel *chan, const char *cmd, char *data, const char *value)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Technology independent volume control" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "30ef0c93b36035ec78c9cfd712d36d9b" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, .support_level = AST_MODULE_SUPPORT_CORE, }
 
static const struct ast_module_infoast_module_info = &__mod_info
 
static const struct ast_datastore_info volume_datastore
 Static structure for datastore information. More...
 
static struct ast_custom_function volume_function
 
static const struct ast_app_option volume_opts [128] = { [ 'p' ] = { .flag = VOLUMEFLAG_CHANGE }, }
 

Detailed Description

Technology independent volume control.

Author
Joshua Colp jcolp.nosp@m.@dig.nosp@m.ium.c.nosp@m.om

Definition in file func_volume.c.

Enumeration Type Documentation

◆ volume_flags

Enumerator
VOLUMEFLAG_CHANGE 

Definition at line 78 of file func_volume.c.

78  {
79  VOLUMEFLAG_CHANGE = (1 << 1),
80 };

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 285 of file func_volume.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 285 of file func_volume.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module* AST_MODULE_SELF_SYM ( void  )

Definition at line 285 of file func_volume.c.

◆ destroy_callback()

static void destroy_callback ( void *  data)
static

Definition at line 86 of file func_volume.c.

References ast_audiohook_destroy(), ast_audiohook_detach(), ast_audiohook_lock, ast_audiohook_unlock, ast_free, and volume_information::audiohook.

87 {
88  struct volume_information *vi = data;
89 
90  /* Destroy the audiohook, and destroy ourselves */
95  ast_free(vi);
96 
97  return;
98 }
int ast_audiohook_destroy(struct ast_audiohook *audiohook)
Destroys an audiohook structure.
Definition: audiohook.c:133
#define ast_audiohook_unlock(ah)
Unlock an audiohook.
Definition: audiohook.h:300
int ast_audiohook_detach(struct ast_audiohook *audiohook)
Detach audiohook from channel.
Definition: audiohook.c:579
#define ast_free(a)
Definition: astmm.h:182
struct ast_audiohook audiohook
Definition: func_volume.c:72
#define ast_audiohook_lock(ah)
Lock an audiohook.
Definition: audiohook.h:295

◆ load_module()

static int load_module ( void  )
static

Definition at line 280 of file func_volume.c.

References ast_custom_function_register.

281 {
283 }
static struct ast_custom_function volume_function
Definition: func_volume.c:269
#define ast_custom_function_register(acf)
Register a custom function.
Definition: pbx.h:1508

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 275 of file func_volume.c.

References ast_custom_function_unregister().

276 {
278 }
static struct ast_custom_function volume_function
Definition: func_volume.c:269
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.

◆ volume_callback()

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 106 of file func_volume.c.

References AST_AUDIOHOOK_DIRECTION_READ, AST_AUDIOHOOK_STATUS_DONE, ast_channel_datastore_find(), ast_frame_adjust_volume_float(), AST_FRAME_DTMF, AST_FRAME_VOICE, ast_test_flag, ast_datastore::data, ast_frame::frametype, ast_frame_subclass::integer, NULL, volume_information::rx_gain, ast_audiohook::status, ast_frame::subclass, volume_information::tx_gain, and VOLUMEFLAG_CHANGE.

Referenced by volume_write().

107 {
108  struct ast_datastore *datastore = NULL;
109  struct volume_information *vi = NULL;
110  float *gain = NULL;
111 
112  /* If the audiohook is stopping it means the channel is shutting down.... but we let the datastore destroy take care of it */
113  if (audiohook->status == AST_AUDIOHOOK_STATUS_DONE)
114  return 0;
115 
116  /* Grab datastore which contains our gain information */
117  if (!(datastore = ast_channel_datastore_find(chan, &volume_datastore, NULL)))
118  return 0;
119 
120  vi = datastore->data;
121 
122  /* If this is DTMF then allow them to increase/decrease the gains */
123  if (ast_test_flag(vi, VOLUMEFLAG_CHANGE)) {
124  if (frame->frametype == AST_FRAME_DTMF) {
125  /* Only use DTMF coming from the source... not going to it */
127  return 0;
128  if (frame->subclass.integer == '*') {
129  vi->tx_gain += 1;
130  vi->rx_gain += 1;
131  } else if (frame->subclass.integer == '#') {
132  vi->tx_gain -= 1;
133  vi->rx_gain -= 1;
134  }
135  }
136  }
137 
138 
139  if (frame->frametype == AST_FRAME_VOICE) {
140  /* Based on direction of frame grab the gain, and confirm it is applicable */
141  if (!(gain = (direction == AST_AUDIOHOOK_DIRECTION_READ) ? &vi->rx_gain : &vi->tx_gain) || !*gain)
142  return 0;
143  /* Apply gain to frame... easy as pi */
144  ast_frame_adjust_volume_float(frame, *gain);
145  }
146 
147  return 0;
148 }
#define ast_test_flag(p, flag)
Definition: utils.h:63
Structure for a data store object.
Definition: datastore.h:68
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2404
#define NULL
Definition: resample.c:96
#define AST_FRAME_DTMF
struct ast_frame_subclass subclass
int ast_frame_adjust_volume_float(struct ast_frame *f, float adjustment)
Adjusts the volume of the audio samples contained in a frame.
Definition: main/frame.c:812
static const struct ast_datastore_info volume_datastore
Static structure for datastore information.
Definition: func_volume.c:101
void * data
Definition: datastore.h:70
enum ast_audiohook_status status
Definition: audiohook.h:107
enum ast_frame_type frametype
direction

◆ volume_read()

static int volume_read ( struct ast_channel chan,
const char *  cmd,
char *  data,
char *  buffer,
size_t  buflen 
)
static

Definition at line 224 of file func_volume.c.

References args, AST_APP_ARG, ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, AST_DECLARE_APP_ARGS, ast_log, AST_STANDARD_APP_ARGS, ast_strlen_zero, ast_datastore::data, LOG_ERROR, LOG_WARNING, NULL, options, volume_information::rx_gain, and volume_information::tx_gain.

225 {
226  struct ast_datastore *datastore = NULL;
227  struct volume_information *vi = NULL;
228 
229  /* Separate options from argument */
230 
234  );
235 
236  if (!chan) {
237  ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
238  return -1;
239  }
240 
242 
243  ast_channel_lock(chan);
244  if (!(datastore = ast_channel_datastore_find(chan, &volume_datastore, NULL))) {
245  ast_channel_unlock(chan);
246  return -1; /* no active audiohook, nothing to read */
247  } else {
248  ast_channel_unlock(chan);
249  vi = datastore->data;
250  }
251 
252  /* Obtain current gain using volume information structure */
253  if (ast_strlen_zero(args.direction)) {
254  ast_log(LOG_ERROR, "Direction must be specified for VOLUME function\n");
255  return -1;
256  }
257 
258  if (!strcasecmp(args.direction, "tx")) {
259  snprintf(buffer, buflen, "%f", vi->tx_gain);
260  } else if (!strcasecmp(args.direction, "rx")) {
261  snprintf(buffer, buflen, "%f", vi->rx_gain);
262  } else {
263  ast_log(LOG_ERROR, "Direction must be either RX or TX\n");
264  }
265 
266  return 0;
267 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
#define LOG_WARNING
Definition: logger.h:274
Structure for a data store object.
Definition: datastore.h:68
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2404
const char * args
#define NULL
Definition: resample.c:96
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_log
Definition: astobj2.c:42
static const struct ast_datastore_info volume_datastore
Static structure for datastore information.
Definition: func_volume.c:101
#define LOG_ERROR
Definition: logger.h:285
#define ast_channel_unlock(chan)
Definition: channel.h:2946
void * data
Definition: datastore.h:70
static struct test_options options
direction
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
#define AST_APP_ARG(name)
Define an application argument.

◆ volume_write()

static int volume_write ( struct ast_channel chan,
const char *  cmd,
char *  data,
const char *  value 
)
static

Definition at line 150 of file func_volume.c.

References args, AST_APP_ARG, ast_app_parse_options(), ast_audiohook_attach(), ast_audiohook_init(), AST_AUDIOHOOK_MANIPULATE_ALL_RATES, 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, volume_information::flags, ast_flags::flags, LOG_ERROR, LOG_WARNING, ast_audiohook::manipulate_callback, NULL, options, volume_information::rx_gain, volume_information::tx_gain, volume_callback(), and volume_opts.

151 {
152  struct ast_datastore *datastore = NULL;
153  struct volume_information *vi = NULL;
154  int is_new = 0;
155 
156  /* Separate options from argument */
157 
161  );
162 
163  if (!chan) {
164  ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
165  return -1;
166  }
167 
169 
170  ast_channel_lock(chan);
171  if (!(datastore = ast_channel_datastore_find(chan, &volume_datastore, NULL))) {
172  ast_channel_unlock(chan);
173  /* Allocate a new datastore to hold the reference to this volume and audiohook information */
174  if (!(datastore = ast_datastore_alloc(&volume_datastore, NULL)))
175  return 0;
176  if (!(vi = ast_calloc(1, sizeof(*vi)))) {
177  ast_datastore_free(datastore);
178  return 0;
179  }
183  is_new = 1;
184  } else {
185  ast_channel_unlock(chan);
186  vi = datastore->data;
187  }
188 
189  /* Adjust gain on volume information structure */
190  if (ast_strlen_zero(args.direction)) {
191  ast_log(LOG_ERROR, "Direction must be specified for VOLUME function\n");
192  return -1;
193  }
194 
195  if (!strcasecmp(args.direction, "tx")) {
196  vi->tx_gain = atof(value);
197  } else if (!strcasecmp(args.direction, "rx")) {
198  vi->rx_gain = atof(value);
199  } else {
200  ast_log(LOG_ERROR, "Direction must be either RX or TX\n");
201  }
202 
203  if (is_new) {
204  datastore->data = vi;
205  ast_channel_lock(chan);
206  ast_channel_datastore_add(chan, datastore);
207  ast_channel_unlock(chan);
208  ast_audiohook_attach(chan, &vi->audiohook);
209  }
210 
211  /* Add Option data to struct */
212 
213  if (!ast_strlen_zero(args.options)) {
214  struct ast_flags flags = { 0 };
215  ast_app_parse_options(volume_opts, &flags, NULL, args.options);
216  vi->flags = flags.flags;
217  } else {
218  vi->flags = 0;
219  }
220 
221  return 0;
222 }
#define ast_channel_lock(chan)
Definition: channel.h:2945
static const struct ast_app_option volume_opts[128]
Definition: func_volume.c:84
#define ast_set_flag(p, flag)
Definition: utils.h:70
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
#define LOG_WARNING
Definition: logger.h:274
unsigned int flags
Definition: utils.h:200
int ast_audiohook_attach(struct ast_channel *chan, struct ast_audiohook *audiohook)
Attach audiohook to channel.
Definition: audiohook.c:501
unsigned int flags
Definition: func_volume.c:75
Structure for a data store object.
Definition: datastore.h:68
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2404
const char * args
#define NULL
Definition: resample.c:96
int value
Definition: syslog.c:37
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition: datastore.c:68
#define ast_strlen_zero(foo)
Definition: strings.h:52
ast_audiohook_manipulate_callback manipulate_callback
Definition: audiohook.h:117
int ast_audiohook_init(struct ast_audiohook *audiohook, enum ast_audiohook_type type, const char *source, enum ast_audiohook_init_flags flags)
Initialize an audiohook structure.
Definition: audiohook.c:108
#define ast_log
Definition: astobj2.c:42
static const struct ast_datastore_info volume_datastore
Static structure for datastore information.
Definition: func_volume.c:101
int ast_app_parse_options(const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr)
Parses a string containing application options and sets flags/arguments.
Definition: main/app.c:2906
#define LOG_ERROR
Definition: logger.h:285
#define ast_channel_unlock(chan)
Definition: channel.h:2946
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
Structure used to handle boolean flags.
Definition: utils.h:199
void * data
Definition: datastore.h:70
struct ast_audiohook audiohook
Definition: func_volume.c:72
static int volume_callback(struct ast_audiohook *audiohook, struct ast_channel *chan, struct ast_frame *frame, enum ast_audiohook_direction direction)
Definition: func_volume.c:106
#define ast_datastore_alloc(info, uid)
Definition: datastore.h:89
static struct test_options options
direction
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2390
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
#define AST_APP_ARG(name)
Define an application argument.

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Technology independent volume control" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "30ef0c93b36035ec78c9cfd712d36d9b" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, .support_level = AST_MODULE_SUPPORT_CORE, }
static

Definition at line 285 of file func_volume.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 285 of file func_volume.c.

◆ volume_datastore

const struct ast_datastore_info volume_datastore
static
Initial value:
= {
.type = "volume",
.destroy = destroy_callback
}
static void destroy_callback(void *data)
Definition: func_volume.c:86

Static structure for datastore information.

Definition at line 101 of file func_volume.c.

◆ volume_function

struct ast_custom_function volume_function
static
Initial value:
= {
.name = "VOLUME",
.write = volume_write,
.read = volume_read,
}
static int volume_read(struct ast_channel *chan, const char *cmd, char *data, char *buffer, size_t buflen)
Definition: func_volume.c:224
static int volume_write(struct ast_channel *chan, const char *cmd, char *data, const char *value)
Definition: func_volume.c:150

Definition at line 269 of file func_volume.c.

◆ volume_opts

const struct ast_app_option volume_opts[128] = { [ 'p' ] = { .flag = VOLUMEFLAG_CHANGE }, }
static

Definition at line 84 of file func_volume.c.

Referenced by volume_write().