aboutsummaryrefslogtreecommitdiffstats
path: root/channels
diff options
context:
space:
mode:
authorkpfleming <kpfleming@f38db490-d61c-443f-a65b-d21fe96a405b>2005-09-07 01:30:01 +0000
committerkpfleming <kpfleming@f38db490-d61c-443f-a65b-d21fe96a405b>2005-09-07 01:30:01 +0000
commit38ba89121ef20c5c80c48257c14b480864215da0 (patch)
tree8165a261cb124dd45a1b6129516aabef87fce470 /channels
parent054df857925f00c4fc914fe2c08e4744e15d24fa (diff)
add new channel option (via ast_channel_setoption()) to let channel drivers adjust txgain/rxgain if they are able (only Zap channels at this time)
modify app_chanspy to use new gain option reformat app_chanspy to match coding guidelines add user-controlled volume adjustment to app_meetme (issue #4170, heavily modified to actually work on Zap channels) git-svn-id: http://svn.digium.com/svn/asterisk/trunk@6519 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'channels')
-rwxr-xr-xchannels/chan_iax2.c35
-rwxr-xr-xchannels/chan_zap.c248
2 files changed, 177 insertions, 106 deletions
diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c
index b05544f24..9c1c5f489 100755
--- a/channels/chan_iax2.c
+++ b/channels/chan_iax2.c
@@ -2992,18 +2992,29 @@ static int iax2_setoption(struct ast_channel *c, int option, void *data, int dat
{
struct ast_option_header *h;
int res;
- h = malloc(datalen + sizeof(struct ast_option_header));
- if (h) {
- h->flag = AST_OPTION_FLAG_REQUEST;
- h->option = htons(option);
- memcpy(h->data, data, datalen);
- res = send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_CONTROL,
- AST_CONTROL_OPTION, 0, (unsigned char *)h, datalen + sizeof(struct ast_option_header), -1);
- free(h);
- return res;
- } else
- ast_log(LOG_WARNING, "Out of memory\n");
- return -1;
+
+ switch (option) {
+ case AST_OPTION_TXGAIN:
+ case AST_OPTION_RXGAIN:
+ /* these two cannot be sent, because they require a result */
+ errno = ENOSYS;
+ return -1;
+ default:
+ h = malloc(datalen + sizeof(*h));
+ if (h) {
+ h->flag = AST_OPTION_FLAG_REQUEST;
+ h->option = htons(option);
+ memcpy(h->data, data, datalen);
+ res = send_command_locked(PTR_TO_CALLNO(c->tech_pvt), AST_FRAME_CONTROL,
+ AST_CONTROL_OPTION, 0, (unsigned char *) h,
+ datalen + sizeof(*h), -1);
+ free(h);
+ return res;
+ } else {
+ ast_log(LOG_WARNING, "Out of memory\n");
+ return -1;
+ }
+ }
}
static struct ast_frame *iax2_read(struct ast_channel *c)
diff --git a/channels/chan_zap.c b/channels/chan_zap.c
index 6bf8f6398..e6e31d2a9 100755
--- a/channels/chan_zap.c
+++ b/channels/chan_zap.c
@@ -1409,50 +1409,105 @@ static void zt_disable_ec(struct zt_pvt *p)
p->echocanon = 0;
}
-int set_actual_gain(int fd, int chan, float rxgain, float txgain, int law)
+static void fill_txgain(struct zt_gains *g, float gain, int law)
{
- struct zt_gains g;
- float ltxgain;
- float lrxgain;
- int j,k;
- g.chan = chan;
- if ((rxgain != 0.0) || (txgain != 0.0)) {
- /* caluculate linear value of tx gain */
- ltxgain = pow(10.0,txgain / 20.0);
- /* caluculate linear value of rx gain */
- lrxgain = pow(10.0,rxgain / 20.0);
- if (law == ZT_LAW_ALAW) {
- for (j=0;j<256;j++) {
- k = (int)(((float)AST_ALAW(j)) * lrxgain);
- if (k > 32767) k = 32767;
- if (k < -32767) k = -32767;
- g.rxgain[j] = AST_LIN2A(k);
- k = (int)(((float)AST_ALAW(j)) * ltxgain);
- if (k > 32767) k = 32767;
- if (k < -32767) k = -32767;
- g.txgain[j] = AST_LIN2A(k);
+ int j;
+ short k;
+ float linear_gain = pow(10.0, gain / 20.0);
+
+ switch (law) {
+ case ZT_LAW_ALAW:
+ for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) {
+ if (gain) {
+ k = (short) (((float) AST_ALAW(j)) * linear_gain);
+ g->txgain[j] = AST_LIN2A(k);
+ } else {
+ g->txgain[j] = j;
}
- } else {
- for (j=0;j<256;j++) {
- k = (int)(((float)AST_MULAW(j)) * lrxgain);
- if (k > 32767) k = 32767;
- if (k < -32767) k = -32767;
- g.rxgain[j] = AST_LIN2MU(k);
- k = (int)(((float)AST_MULAW(j)) * ltxgain);
- if (k > 32767) k = 32767;
- if (k < -32767) k = -32767;
- g.txgain[j] = AST_LIN2MU(k);
+ }
+ break;
+ case ZT_LAW_MULAW:
+ for (j = 0; j < (sizeof(g->txgain) / sizeof(g->txgain[0])); j++) {
+ if (gain) {
+ k = (short) (((float) AST_MULAW(j)) * linear_gain);
+ g->txgain[j] = AST_LIN2MU(k);
+ } else {
+ g->txgain[j] = j;
}
}
- } else {
- for (j=0;j<256;j++) {
- g.rxgain[j] = j;
- g.txgain[j] = j;
+ break;
+ }
+}
+
+static void fill_rxgain(struct zt_gains *g, float gain, int law)
+{
+ int j;
+ short k;
+ float linear_gain = pow(10.0, gain / 20.0);
+
+ switch (law) {
+ case ZT_LAW_ALAW:
+ for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) {
+ if (gain) {
+ k = (short) (((float) AST_ALAW(j)) * linear_gain);
+ g->rxgain[j] = AST_LIN2A(k);
+ } else {
+ g->rxgain[j] = j;
+ }
}
+ break;
+ case ZT_LAW_MULAW:
+ for (j = 0; j < (sizeof(g->rxgain) / sizeof(g->rxgain[0])); j++) {
+ if (gain) {
+ k = (short) (((float) AST_MULAW(j)) * linear_gain);
+ g->rxgain[j] = AST_LIN2MU(k);
+ } else {
+ g->rxgain[j] = j;
+ }
+ }
+ break;
}
-
- /* set 'em */
- return(ioctl(fd,ZT_SETGAINS,&g));
+}
+
+int set_actual_txgain(int fd, int chan, float gain, int law)
+{
+ struct zt_gains g;
+ int res;
+
+ memset(&g, 0, sizeof(g));
+ g.chan = chan;
+ res = ioctl(fd, ZT_GETGAINS, &g);
+ if (res) {
+ ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno));
+ return res;
+ }
+
+ fill_txgain(&g, gain, law);
+
+ return ioctl(fd, ZT_SETGAINS, &g);
+}
+
+int set_actual_rxgain(int fd, int chan, float gain, int law)
+{
+ struct zt_gains g;
+ int res;
+
+ memset(&g, 0, sizeof(g));
+ g.chan = chan;
+ res = ioctl(fd, ZT_GETGAINS, &g);
+ if (res) {
+ ast_log(LOG_DEBUG, "Failed to read gains: %s\n", strerror(errno));
+ return res;
+ }
+
+ fill_rxgain(&g, gain, law);
+
+ return ioctl(fd, ZT_SETGAINS, &g);
+}
+
+int set_actual_gain(int fd, int chan, float rxgain, float txgain, int law)
+{
+ return set_actual_txgain(fd, chan, txgain, law) | set_actual_rxgain(fd, chan, rxgain, law);
}
static inline int zt_set_hook(int fd, int hs)
@@ -2570,65 +2625,78 @@ static int zt_answer(struct ast_channel *ast)
static int zt_setoption(struct ast_channel *chan, int option, void *data, int datalen)
{
-char *cp;
-int x;
-
+ char *cp;
+ signed char *scp;
+ int x;
+ int index;
struct zt_pvt *p = chan->tech_pvt;
-
- if ((option != AST_OPTION_TONE_VERIFY) && (option != AST_OPTION_AUDIO_MODE) &&
- (option != AST_OPTION_TDD) && (option != AST_OPTION_RELAXDTMF))
- {
- errno = ENOSYS;
- return -1;
- }
- cp = (char *)data;
- if ((!cp) || (datalen < 1))
- {
+ /* all supported options require data */
+ if (!data || (datalen < 1)) {
errno = EINVAL;
return -1;
- }
+ }
+
switch(option) {
- case AST_OPTION_TONE_VERIFY:
+ case AST_OPTION_TXGAIN:
+ scp = (signed char *) data;
+ index = zt_get_index(chan, p, 0);
+ if (index < 0) {
+ ast_log(LOG_WARNING, "No index in TXGAIN?\n");
+ return -1;
+ }
+ ast_log(LOG_DEBUG, "Setting actual tx gain on %s to %f\n", chan->name, p->txgain + (float) *scp);
+ return set_actual_txgain(p->subs[index].zfd, 0, p->txgain + (float) *scp, p->law);
+ case AST_OPTION_RXGAIN:
+ scp = (signed char *) data;
+ index = zt_get_index(chan, p, 0);
+ if (index < 0) {
+ ast_log(LOG_WARNING, "No index in RXGAIN?\n");
+ return -1;
+ }
+ ast_log(LOG_DEBUG, "Setting actual rx gain on %s to %f\n", chan->name, p->rxgain + (float) *scp);
+ return set_actual_rxgain(p->subs[index].zfd, 0, p->rxgain + (float) *scp, p->law);
+ case AST_OPTION_TONE_VERIFY:
if (!p->dsp)
break;
- switch(*cp) {
- case 1:
- ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
- ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | p->dtmfrelax); /* set mute mode if desired */
+ cp = (char *) data;
+ switch (*cp) {
+ case 1:
+ ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF(1) on %s\n",chan->name);
+ ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | p->dtmfrelax); /* set mute mode if desired */
break;
- case 2:
- ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
- ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax); /* set mute mode if desired */
+ case 2:
+ ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: MUTECONF/MAX(2) on %s\n",chan->name);
+ ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_MUTECONF | DSP_DIGITMODE_MUTEMAX | p->dtmfrelax); /* set mute mode if desired */
break;
- default:
- ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
- ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax); /* set mute mode if desired */
+ default:
+ ast_log(LOG_DEBUG, "Set option TONE VERIFY, mode: OFF(0) on %s\n",chan->name);
+ ast_dsp_digitmode(p->dsp,DSP_DIGITMODE_DTMF | p->dtmfrelax); /* set mute mode if desired */
break;
}
break;
- case AST_OPTION_TDD: /* turn on or off TDD */
+ case AST_OPTION_TDD:
+ /* turn on or off TDD */
+ cp = (char *) data;
+ p->mate = 0;
if (!*cp) { /* turn it off */
ast_log(LOG_DEBUG, "Set option TDD MODE, value: OFF(0) on %s\n",chan->name);
if (p->tdd) tdd_free(p->tdd);
p->tdd = 0;
- p->mate = 0;
break;
}
- if (*cp == 2)
- ast_log(LOG_DEBUG, "Set option TDD MODE, value: MATE(2) on %s\n",chan->name);
- else ast_log(LOG_DEBUG, "Set option TDD MODE, value: ON(1) on %s\n",chan->name);
- p->mate = 0;
+ ast_log(LOG_DEBUG, "Set option TDD MODE, value: %s(%d) on %s\n",
+ (*cp == 2) ? "MATE" : "ON", (int) *cp, chan->name);
zt_disable_ec(p);
/* otherwise, turn it on */
if (!p->didtdd) { /* if havent done it yet */
unsigned char mybuf[41000],*buf;
int size,res,fd,len;
- int index;
struct pollfd fds[1];
+
buf = mybuf;
- memset(buf,0x7f,sizeof(mybuf)); /* set to silence */
- ast_tdd_gen_ecdisa(buf + 16000,16000); /* put in tone */
+ memset(buf, 0x7f, sizeof(mybuf)); /* set to silence */
+ ast_tdd_gen_ecdisa(buf + 16000, 16000); /* put in tone */
len = 40000;
index = zt_get_index(chan, p, 0);
if (index < 0) {
@@ -2649,7 +2717,7 @@ int x;
ast_log(LOG_DEBUG, "poll (for write) ret. 0 on channel %d\n", p->channel);
continue;
}
- /* if got exception */
+ /* if got exception */
if (fds[0].revents & POLLPRI) return -1;
if (!(fds[0].revents & POLLOUT)) {
ast_log(LOG_DEBUG, "write fd not ready on channel %d\n", p->channel);
@@ -2671,36 +2739,27 @@ int x;
p->tdd = 0;
p->mate = 1;
break;
- }
+ }
if (!p->tdd) { /* if we dont have one yet */
p->tdd = tdd_new(); /* allocate one */
}
break;
- case AST_OPTION_RELAXDTMF: /* Relax DTMF decoding (or not) */
+ case AST_OPTION_RELAXDTMF: /* Relax DTMF decoding (or not) */
if (!p->dsp)
break;
- if (!*cp)
- {
- ast_log(LOG_DEBUG, "Set option RELAX DTMF, value: OFF(0) on %s\n",chan->name);
- x = 0;
- }
- else
- {
- ast_log(LOG_DEBUG, "Set option RELAX DTMF, value: ON(1) on %s\n",chan->name);
- x = 1;
- }
- ast_dsp_digitmode(p->dsp,x ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF | p->dtmfrelax);
+ cp = (char *) data;
+ ast_log(LOG_DEBUG, "Set option RELAX DTMF, value: %s(%d) on %s\n",
+ *cp ? "ON" : "OFF", (int) *cp, chan->name);
+ ast_dsp_digitmode(p->dsp, ((*cp) ? DSP_DIGITMODE_RELAXDTMF : DSP_DIGITMODE_DTMF) | p->dtmfrelax);
break;
- case AST_OPTION_AUDIO_MODE: /* Set AUDIO mode (or not) */
- if (!*cp)
- {
- ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: OFF(0) on %s\n",chan->name);
+ case AST_OPTION_AUDIO_MODE: /* Set AUDIO mode (or not) */
+ cp = (char *) data;
+ if (!*cp) {
+ ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: OFF(0) on %s\n", chan->name);
x = 0;
zt_disable_ec(p);
- }
- else
- {
- ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: ON(1) on %s\n",chan->name);
+ } else {
+ ast_log(LOG_DEBUG, "Set option AUDIO MODE, value: ON(1) on %s\n", chan->name);
x = 1;
}
if (ioctl(p->subs[SUB_REAL].zfd, ZT_AUDIOMODE, &x) == -1)
@@ -2708,6 +2767,7 @@ int x;
break;
}
errno = 0;
+
return 0;
}