aboutsummaryrefslogtreecommitdiffstats
path: root/channels
diff options
context:
space:
mode:
authorrmudgett <rmudgett@f38db490-d61c-443f-a65b-d21fe96a405b>2010-11-20 03:11:15 +0000
committerrmudgett <rmudgett@f38db490-d61c-443f-a65b-d21fe96a405b>2010-11-20 03:11:15 +0000
commit713f10d9fce0e9940f04e09bc0dd788574f22a16 (patch)
tree9b041025490cd4c71b8b4131e61b21fdceabec07 /channels
parentd58d0887ce93e8d66d939e013743251bf6cb2bf6 (diff)
One way audio before answering call waiting call on analog port.
* Analog call waiting Caller ID spills could get stuck resulting in one way audio until the waiting call is answered. This only happens on the second (and later) call waiting call if the active call is not the first call. * The CLI/AMI "dahdi show channel" command could report the wrong channel information. Must keep the struct analog_pvt.owner and struct dahdi_pvt.owner pointer in sync. git-svn-id: http://svn.digium.com/svn/asterisk/branches/1.8@295747 f38db490-d61c-443f-a65b-d21fe96a405b
Diffstat (limited to 'channels')
-rw-r--r--channels/chan_dahdi.c8
-rw-r--r--channels/sig_analog.c53
-rw-r--r--channels/sig_analog.h1
3 files changed, 40 insertions, 22 deletions
diff --git a/channels/chan_dahdi.c b/channels/chan_dahdi.c
index 34364a06a..8319161ee 100644
--- a/channels/chan_dahdi.c
+++ b/channels/chan_dahdi.c
@@ -2246,6 +2246,13 @@ static void my_set_pulsedial(void *pvt, int flag)
p->pulsedial = flag;
}
+static void my_set_new_owner(void *pvt, struct ast_channel *new_owner)
+{
+ struct dahdi_pvt *p = pvt;
+
+ p->owner = new_owner;
+}
+
static const char *my_get_orig_dialstring(void *pvt)
{
struct dahdi_pvt *p = pvt;
@@ -3528,6 +3535,7 @@ static struct analog_callback dahdi_analog_callbacks =
.cancel_cidspill = my_cancel_cidspill,
.confmute = my_confmute,
.set_pulsedial = my_set_pulsedial,
+ .set_new_owner = my_set_new_owner,
.get_orig_dialstring = my_get_orig_dialstring,
.set_needringing = my_set_needringing,
.set_polarity = my_set_polarity,
diff --git a/channels/sig_analog.c b/channels/sig_analog.c
index 6788b8309..ba6ed45c8 100644
--- a/channels/sig_analog.c
+++ b/channels/sig_analog.c
@@ -412,6 +412,14 @@ static int analog_play_tone(struct analog_pvt *p, enum analog_sub sub, enum anal
return -1;
}
+static void analog_set_new_owner(struct analog_pvt *p, struct ast_channel *new_owner)
+{
+ p->owner = new_owner;
+ if (p->calls->set_new_owner) {
+ p->calls->set_new_owner(p->chan_pvt, new_owner);
+ }
+}
+
static struct ast_channel * analog_new_ast_channel(struct analog_pvt *p, int state, int startpbx, enum analog_sub sub, const struct ast_channel *requestor)
{
struct ast_channel *c;
@@ -426,7 +434,7 @@ static struct ast_channel * analog_new_ast_channel(struct analog_pvt *p, int sta
}
p->subs[sub].owner = c;
if (!p->owner) {
- p->owner = c;
+ analog_set_new_owner(p, c);
}
return c;
}
@@ -1290,7 +1298,7 @@ int analog_hangup(struct analog_pvt *p, struct ast_channel *ast)
/* Move to the call-wait, but un-own us until they flip back. */
analog_swap_subs(p, ANALOG_SUB_CALLWAIT, ANALOG_SUB_REAL);
analog_unalloc_sub(p, ANALOG_SUB_CALLWAIT);
- p->owner = NULL;
+ analog_set_new_owner(p, NULL);
} else {
/* The three way hung up, but we still have a call wait */
ast_debug(1, "We were in the threeway and have a callwait still. Ditching the threeway.\n");
@@ -1301,11 +1309,11 @@ int analog_hangup(struct analog_pvt *p, struct ast_channel *ast)
another call */
ast_debug(1, "Call was complete, setting owner to former third call\n");
analog_set_inthreeway(p, ANALOG_SUB_REAL, 0);
- p->owner = p->subs[ANALOG_SUB_REAL].owner;
+ analog_set_new_owner(p, p->subs[ANALOG_SUB_REAL].owner);
} else {
/* This call hasn't been completed yet... Set owner to NULL */
ast_debug(1, "Call was incomplete, setting owner to NULL\n");
- p->owner = NULL;
+ analog_set_new_owner(p, NULL);
}
}
} else if (p->subs[ANALOG_SUB_CALLWAIT].allocd) {
@@ -1313,14 +1321,14 @@ int analog_hangup(struct analog_pvt *p, struct ast_channel *ast)
analog_lock_sub_owner(p, ANALOG_SUB_CALLWAIT);
if (!p->subs[ANALOG_SUB_CALLWAIT].owner) {
/* The call waiting call dissappeared. */
- p->owner = NULL;
+ analog_set_new_owner(p, NULL);
break;
}
/* Move to the call-wait and switch back to them. */
analog_swap_subs(p, ANALOG_SUB_CALLWAIT, ANALOG_SUB_REAL);
analog_unalloc_sub(p, ANALOG_SUB_CALLWAIT);
- p->owner = p->subs[ANALOG_SUB_REAL].owner;
+ analog_set_new_owner(p, p->subs[ANALOG_SUB_REAL].owner);
if (p->owner->_state != AST_STATE_UP) {
ast_queue_control(p->subs[ANALOG_SUB_REAL].owner, AST_CONTROL_ANSWER);
}
@@ -1337,11 +1345,11 @@ int analog_hangup(struct analog_pvt *p, struct ast_channel *ast)
another call */
ast_debug(1, "Call was complete, setting owner to former third call\n");
analog_set_inthreeway(p, ANALOG_SUB_REAL, 0);
- p->owner = p->subs[ANALOG_SUB_REAL].owner;
+ analog_set_new_owner(p, p->subs[ANALOG_SUB_REAL].owner);
} else {
/* This call hasn't been completed yet... Set owner to NULL */
ast_debug(1, "Call was incomplete, setting owner to NULL\n");
- p->owner = NULL;
+ analog_set_new_owner(p, NULL);
}
}
break;
@@ -1402,7 +1410,7 @@ int analog_hangup(struct analog_pvt *p, struct ast_channel *ast)
}
if (!p->subs[ANALOG_SUB_REAL].owner && !p->subs[ANALOG_SUB_CALLWAIT].owner && !p->subs[ANALOG_SUB_THREEWAY].owner) {
- p->owner = NULL;
+ analog_set_new_owner(p, NULL);
analog_set_ringtimeout(p, 0);
analog_set_confirmanswer(p, 0);
analog_set_pulsedial(p, 0);
@@ -1512,7 +1520,7 @@ int analog_answer(struct analog_pvt *p, struct ast_channel *ast)
ast_debug(1, "Finally swapping real and threeway\n");
analog_play_tone(p, ANALOG_SUB_THREEWAY, -1);
analog_swap_subs(p, ANALOG_SUB_THREEWAY, ANALOG_SUB_REAL);
- p->owner = p->subs[ANALOG_SUB_REAL].owner;
+ analog_set_new_owner(p, p->subs[ANALOG_SUB_REAL].owner);
}
}
@@ -2252,7 +2260,7 @@ static void *__analog_ss_thread(void *data)
}
analog_swap_subs(p, ANALOG_SUB_REAL, ANALOG_SUB_THREEWAY);
analog_unalloc_sub(p, ANALOG_SUB_THREEWAY);
- p->owner = p->subs[ANALOG_SUB_REAL].owner;
+ analog_set_new_owner(p, p->subs[ANALOG_SUB_REAL].owner);
if (ast_bridged_channel(p->subs[ANALOG_SUB_REAL].owner)) {
ast_queue_control(p->subs[ANALOG_SUB_REAL].owner, AST_CONTROL_UNHOLD);
}
@@ -2264,7 +2272,7 @@ static void *__analog_ss_thread(void *data)
analog_play_tone(p, idx, -1);
analog_swap_subs(p, ANALOG_SUB_REAL, ANALOG_SUB_THREEWAY);
analog_unalloc_sub(p, ANALOG_SUB_THREEWAY);
- p->owner = p->subs[ANALOG_SUB_REAL].owner;
+ analog_set_new_owner(p, p->subs[ANALOG_SUB_REAL].owner);
ast_hangup(chan);
goto quit;
}
@@ -2744,7 +2752,7 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
ast_verb(3, "Channel %d still has (callwait) call, ringing phone\n", p->channel);
analog_unalloc_sub(p, ANALOG_SUB_CALLWAIT);
analog_stop_callwait(p);
- p->owner = NULL;
+ analog_set_new_owner(p, NULL);
/* Don't start streaming audio yet if the incoming call isn't up yet */
if (p->subs[ANALOG_SUB_REAL].owner->_state != AST_STATE_UP) {
analog_set_dialing(p, 1);
@@ -2794,7 +2802,7 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
analog_swap_subs(p, ANALOG_SUB_THREEWAY, ANALOG_SUB_REAL);
/* Unlock the 3-way call that we swapped to real-call. */
ast_channel_unlock(p->subs[ANALOG_SUB_REAL].owner);
- p->owner = NULL;
+ analog_set_new_owner(p, NULL);
/* Ring the phone */
analog_ring(p);
} else {
@@ -2817,7 +2825,7 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
analog_swap_subs(p, ANALOG_SUB_THREEWAY, ANALOG_SUB_REAL);
/* Unlock the 3-way call that we swapped to real-call. */
ast_channel_unlock(p->subs[ANALOG_SUB_REAL].owner);
- p->owner = NULL;
+ analog_set_new_owner(p, NULL);
/* Ring the phone */
analog_ring(p);
}
@@ -3064,7 +3072,7 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
/* Swap to call-wait */
analog_swap_subs(p, ANALOG_SUB_REAL, ANALOG_SUB_CALLWAIT);
analog_play_tone(p, ANALOG_SUB_REAL, -1);
- p->owner = p->subs[ANALOG_SUB_REAL].owner;
+ analog_set_new_owner(p, p->subs[ANALOG_SUB_REAL].owner);
ast_debug(1, "Making %s the new owner\n", p->owner->name);
if (p->subs[ANALOG_SUB_REAL].owner->_state == AST_STATE_RINGING) {
ast_setstate(p->subs[ANALOG_SUB_REAL].owner, AST_STATE_UP);
@@ -3149,7 +3157,8 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
if (res) {
ast_log(LOG_WARNING, "Unable to start dial recall tone on channel %d\n", p->channel);
}
- p->ss_astchan = p->owner = chan;
+ analog_set_new_owner(p, chan);
+ p->ss_astchan = chan;
if (ast_pthread_create_detached(&threadid, NULL, __analog_ss_thread, p)) {
ast_log(LOG_WARNING, "Unable to start simple switch on channel %d\n", p->channel);
res = analog_play_tone(p, ANALOG_SUB_REAL, ANALOG_TONE_CONGESTION);
@@ -3191,7 +3200,7 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
/* Swap back -- we're dropping the real 3-way that isn't finished yet*/
analog_swap_subs(p, ANALOG_SUB_THREEWAY, ANALOG_SUB_REAL);
orig_3way_sub = ANALOG_SUB_REAL;
- p->owner = p->subs[ANALOG_SUB_REAL].owner;
+ analog_set_new_owner(p, p->subs[ANALOG_SUB_REAL].owner);
}
/* Drop the last call and stop the conference */
ast_verb(3, "Dropping three-way call on %s\n", p->subs[ANALOG_SUB_THREEWAY].owner->name);
@@ -3215,13 +3224,13 @@ static struct ast_frame *__analog_handle_event(struct analog_pvt *p, struct ast_
if (ast_bridged_channel(p->subs[orig_3way_sub].owner)) {
ast_queue_control(p->subs[orig_3way_sub].owner, AST_CONTROL_UNHOLD);
}
- p->owner = p->subs[ANALOG_SUB_REAL].owner;
+ analog_set_new_owner(p, p->subs[ANALOG_SUB_REAL].owner);
} else {
ast_verb(3, "Dumping incomplete call on %s\n", p->subs[ANALOG_SUB_THREEWAY].owner->name);
analog_swap_subs(p, ANALOG_SUB_THREEWAY, ANALOG_SUB_REAL);
orig_3way_sub = ANALOG_SUB_REAL;
ast_softhangup_nolock(p->subs[ANALOG_SUB_THREEWAY].owner, AST_SOFTHANGUP_DEV);
- p->owner = p->subs[ANALOG_SUB_REAL].owner;
+ analog_set_new_owner(p, p->subs[ANALOG_SUB_REAL].owner);
if (ast_bridged_channel(p->subs[ANALOG_SUB_REAL].owner)) {
ast_queue_control(p->subs[ANALOG_SUB_REAL].owner, AST_CONTROL_UNHOLD);
}
@@ -3457,7 +3466,7 @@ struct ast_frame *analog_exception(struct analog_pvt *p, struct ast_channel *ast
if ((res != ANALOG_EVENT_RINGEROFF) && (res != ANALOG_EVENT_RINGERON) &&
(res != ANALOG_EVENT_HOOKCOMPLETE)) {
ast_debug(1, "Restoring owner of channel %d on event %d\n", p->channel, res);
- p->owner = p->subs[ANALOG_SUB_REAL].owner;
+ analog_set_new_owner(p, p->subs[ANALOG_SUB_REAL].owner);
if (p->owner && ast != p->owner) {
/*
* Could this even happen?
@@ -3834,7 +3843,7 @@ int analog_fixup(struct ast_channel *oldchan, struct ast_channel *newchan, void
int x;
ast_debug(1, "New owner for channel %d is %s\n", new_pvt->channel, newchan->name);
if (new_pvt->owner == oldchan) {
- new_pvt->owner = newchan;
+ analog_set_new_owner(new_pvt, newchan);
}
for (x = 0; x < 3; x++) {
if (new_pvt->subs[x].owner == oldchan) {
diff --git a/channels/sig_analog.h b/channels/sig_analog.h
index 3c33aebf0..d7b6011a3 100644
--- a/channels/sig_analog.h
+++ b/channels/sig_analog.h
@@ -231,6 +231,7 @@ struct analog_callback {
void (* const cancel_cidspill)(void *pvt);
int (* const confmute)(void *pvt, int mute);
void (* const set_pulsedial)(void *pvt, int flag);
+ void (* const set_new_owner)(void *pvt, struct ast_channel *new_owner);
const char *(* const get_orig_dialstring)(void *pvt);
};