+/*
+ * fixup asterisk
+ */
+static int lcr_fixup(struct ast_channel *oldast, struct ast_channel *ast)
+{
+ struct chan_call *call;
+
+ if (!ast) {
+ return -1;
+ }
+
+ ast_mutex_lock(&chan_lock);
+ call = ast->tech_pvt;
+ if (!call) {
+ CERROR(NULL, ast, "Received fixup from Asterisk, but no call instance exists.\n");
+ ast_mutex_unlock(&chan_lock);
+ return -1;
+ }
+
+ CDEBUG(call, ast, "Received fixup from Asterisk.\n");
+ call->ast = ast;
+ ast_mutex_unlock(&chan_lock);
+ return 0;
+}
+
+/*
+ * send_text asterisk
+ */
+static int lcr_send_text(struct ast_channel *ast, const char *text)
+{
+ struct chan_call *call;
+ union parameter newparam;
+
+ ast_mutex_lock(&chan_lock);
+ call = ast->tech_pvt;
+ if (!call) {
+ CERROR(NULL, ast, "Received send_text from Asterisk, but no call instance exists.\n");
+ ast_mutex_unlock(&chan_lock);
+ return -1;
+ }
+
+ CDEBUG(call, ast, "Received send_text from Asterisk. (text=%s)\n", text);
+ memset(&newparam, 0, sizeof(union parameter));
+ strncpy(newparam.notifyinfo.display, text, sizeof(newparam.notifyinfo.display)-1);
+ send_message(MESSAGE_NOTIFY, call->ref, &newparam);
+ ast_mutex_lock(&chan_lock);
+ return 0;
+}
+
+/*
+ * bridge process
+ */
+enum ast_bridge_result lcr_bridge(struct ast_channel *ast1,
+ struct ast_channel *ast2, int flags,
+ struct ast_frame **fo,
+ struct ast_channel **rc, int timeoutms)
+
+{
+ struct chan_call *call1, *call2;
+ struct ast_channel *carr[2], *who;
+ int to;
+ struct ast_frame *f;
+ int bridge_id;
+
+ CDEBUG(NULL, NULL, "Received briding request from Asterisk.\n");
+
+ carr[0] = ast1;
+ carr[1] = ast2;
+
+ /* join via dsp (if the channels are currently open) */
+ ast_mutex_lock(&chan_lock);
+ call1 = ast1->tech_pvt;
+ call2 = ast2->tech_pvt;
+ if (!call1 || !call2) {
+ CDEBUG(NULL, NULL, "Bridge, but we don't have two call instances, exitting.\n");
+ ast_mutex_unlock(&chan_lock);
+ return AST_BRIDGE_COMPLETE;
+ }
+
+ /* join, if both call instances uses dsp */
+ if (!call1->nodsp && !call2->nodsp) {
+ CDEBUG(NULL, NULL, "Both calls use DSP, briding via DSP.\n");
+
+ /* get bridge id and join */
+ bridge_id = new_bridge_id();
+
+ call1->bridge_id = bridge_id;
+ if (call1->bchannel)
+ bchannel_join(call1->bchannel, bridge_id);
+
+ call2->bridge_id = bridge_id;
+ if (call2->bchannel)
+ bchannel_join(call2->bchannel, bridge_id);
+ } else
+ if (call1->nodsp && call2->nodsp)
+ CDEBUG(NULL, NULL, "Both calls use no DSP, briding in channel driver.\n");
+ else
+ CDEBUG(NULL, NULL, "One call uses no DSP, briding in channel driver.\n");
+ call1->bridge_call = call2;
+ call2->bridge_call = call1;
+
+ if (call1->state == CHAN_LCR_STATE_IN_SETUP
+ || call1->state == CHAN_LCR_STATE_IN_DIALING
+ || call1->state == CHAN_LCR_STATE_IN_PROCEEDING
+ || call1->state == CHAN_LCR_STATE_IN_ALERTING) {
+ CDEBUG(call1, ast1, "Bridge established before lcr_answer, so we call it ourself: Calling lcr_answer...\n");
+ lcr_answer(ast1);
+ }
+ if (call2->state == CHAN_LCR_STATE_IN_SETUP
+ || call2->state == CHAN_LCR_STATE_IN_DIALING
+ || call2->state == CHAN_LCR_STATE_IN_PROCEEDING
+ || call2->state == CHAN_LCR_STATE_IN_ALERTING) {
+ CDEBUG(call2, ast2, "Bridge established before lcr_answer, so we call it ourself: Calling lcr_answer...\n");
+ lcr_answer(ast2);
+ }
+
+ ast_mutex_unlock(&chan_lock);
+
+ while(1) {
+ to = -1;
+ who = ast_waitfor_n(carr, 2, &to);
+
+ if (!who) {
+ CDEBUG(NULL, NULL, "Empty read on bridge, breaking out.\n");
+ break;
+ }
+ f = ast_read(who);
+
+ if (!f || f->frametype == AST_FRAME_CONTROL) {
+ if (!f)
+ CDEBUG(NULL, NULL, "Got hangup.\n");
+ else
+ CDEBUG(NULL, NULL, "Got CONTROL.\n");
+ /* got hangup .. */
+ *fo=f;
+ *rc=who;
+ break;
+ }
+
+ if ( f->frametype == AST_FRAME_DTMF ) {
+ CDEBUG(NULL, NULL, "Got DTMF.\n");
+ *fo=f;
+ *rc=who;
+ break;
+ }
+
+
+ if (who == ast1) {
+ ast_write(ast2,f);
+ }
+ else {
+ ast_write(ast1,f);
+ }
+
+ }
+
+ CDEBUG(NULL, NULL, "Releasing bride.\n");
+
+ /* split channels */
+ ast_mutex_lock(&chan_lock);
+ call1 = ast1->tech_pvt;
+ call2 = ast2->tech_pvt;
+ if (call1 && call1->bridge_id)
+ {
+ call1->bridge_id = 0;
+ if (call1->bchannel)
+ bchannel_join(call1->bchannel, 0);
+ if (call1->bridge_call)
+ call1->bridge_call->bridge_call = NULL;
+ }
+ if (call2 && call1->bridge_id)
+ {
+ call2->bridge_id = 0;
+ if (call2->bchannel)
+ bchannel_join(call2->bchannel, 0);
+ if (call2->bridge_call)
+ call2->bridge_call->bridge_call = NULL;
+ }
+ call1->bridge_call = NULL;
+ call2->bridge_call = NULL;
+
+ ast_mutex_unlock(&chan_lock);
+ return AST_BRIDGE_COMPLETE;
+}