[asterisk-commits] may: branch may/chan_mcu r396414 - /team/may/chan_mcu/branches/10/addons/

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Thu Aug 8 14:02:30 CDT 2013


Author: may
Date: Thu Aug  8 14:02:28 2013
New Revision: 396414

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=396414
Log:
initial public chan_mcu/res_xml_rpc code 

Added:
    team/may/chan_mcu/branches/10/addons/chan_mcu.c   (with props)
    team/may/chan_mcu/branches/10/addons/mcu_common.h   (with props)
    team/may/chan_mcu/branches/10/addons/res_xmlrpc_mcu.c   (with props)
    team/may/chan_mcu/branches/10/addons/res_xmlrpc_mcu.exports.in   (with props)
Modified:
    team/may/chan_mcu/branches/10/addons/Makefile

Modified: team/may/chan_mcu/branches/10/addons/Makefile
URL: http://svnview.digium.com/svn/asterisk/team/may/chan_mcu/branches/10/addons/Makefile?view=diff&rev=396414&r1=396413&r2=396414
==============================================================================
--- team/may/chan_mcu/branches/10/addons/Makefile (original)
+++ team/may/chan_mcu/branches/10/addons/Makefile Thu Aug  8 14:02:28 2013
@@ -31,6 +31,8 @@
             cdr_mysql \
             chan_mobile \
             chan_ooh323 \
+            chan_mcu \
+            res_xmlrpc_mcu \
             format_mp3 \
             res_config_mysql
 
@@ -65,6 +67,10 @@
 $(if $(filter format_mp3,$(EMBEDDED_MODS)),modules.link,format_mp3.so): mp3/common.o mp3/dct64_i386.o mp3/decode_ntom.o mp3/layer3.o mp3/tabinit.o mp3/interface.o
 
 chan_ooh323.o: _ASTCFLAGS+=$(H323CFLAGS)
+chan_mcu.o: _ASTCFLAGS+=-I/usr/local/xmlrpc/include
+res_xmlrpc_mcu.o: _ASTCFLAGS+=-I/usr/local/xmlrpc/include
+chan_mcu.so: LIBS+=-L/usr/local/xmlrpc/lib -lxmlrpc -lxmlrpc_client -lxmlrpc_xmlparse -lxmlrpc_xmltok -lxmlrpc_abyss -lxmlrpc_server -lxmlrpc_util
+res_xmlrpc_mcu.so: LIBS+=-L/usr/local/xmlrpc/lib -lxmlrpc -lxmlrpc_client -lxmlrpc_xmlparse -lxmlrpc_xmltok -lxmlrpc_abyss -lxmlrpc_server -lxmlrpc_util
 
 $(if $(filter chan_ooh323,$(EMBEDDED_MODS)),modules.link,chan_ooh323.so): _ASTCFLAGS+=$(H323CFLAGS)
 $(if $(filter chan_ooh323,$(EMBEDDED_MODS)),modules.link,chan_ooh323.so): $(addprefix ooh323c/src/,$(H323OBJS)) chan_ooh323.o ooh323cDriver.o

Added: team/may/chan_mcu/branches/10/addons/chan_mcu.c
URL: http://svnview.digium.com/svn/asterisk/team/may/chan_mcu/branches/10/addons/chan_mcu.c?view=auto&rev=396414
==============================================================================
--- team/may/chan_mcu/branches/10/addons/chan_mcu.c (added)
+++ team/may/chan_mcu/branches/10/addons/chan_mcu.c Thu Aug  8 14:02:28 2013
@@ -1,0 +1,2123 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ */
+
+/*! \file
+ *
+ * \brief Medooze MediaMixer channel driver
+ *
+ * \ingroup channel_drivers
+ */
+
+/*** MODULEINFO
+	<defaultenabled>no</defaultenabled>
+	<depend>res_xmlrpc_mcu</depend>
+	<support_level>extended</support_level>
+ ***/
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
+#include <fcntl.h>
+#include <sys/signal.h>
+
+#include <xmlrpc-c/base.h>
+#include <xmlrpc-c/client.h>
+
+#include "asterisk/lock.h"
+#include "asterisk/channel.h"
+#include "asterisk/config.h"
+#include "asterisk/module.h"
+#include "asterisk/pbx.h"
+#include "asterisk/sched.h"
+#include "asterisk/io.h"
+#include "asterisk/acl.h"
+#include "asterisk/callerid.h"
+#include "asterisk/file.h"
+#include "asterisk/cli.h"
+#include "asterisk/app.h"
+#include "asterisk/rtp_engine.h"
+#include "asterisk/causes.h"
+
+#include "mcu_common.h"
+
+#define FORMAT_STRING_SIZE 512
+
+#define H264_PAYLOAD_NAME "102"
+#define VP8_PAYLOAD_NAME "103"
+#define ALAW_PAYLOAD_NAME "8"
+#define SPEEX16_PAYLOAD_NAME "111"
+
+// from MCU media mixer
+enum AudioType {PCMA=8,PCMU=0,GSM=3,SPEEX16=117,AMR=118,TELEPHONE_EVENT=100,NELLY8=130,NELLY11=131};
+enum VideoType {H263_1996=34,H263_1998=103,MPEG4=104,H264=99,SORENSON=100,VP8=107};
+
+static const char tdesc[] = "MCU Channel Driver";
+static const char type[] = "MCU";
+static const char xmlrpc_cname[] = "Asterisk XMLRPC client";
+static const char xmlrpc_cversion[] = "0.1";
+static char defaultCLID[] = "asterisk";
+static const char config[] = "chan_mcu.conf";
+
+static struct ast_sockaddr bindaddr;
+
+struct ast_module *myself;
+
+/** Asterisk RTP stuff*/
+static struct ast_sched_context *sched;
+static struct io_context *io;
+
+
+static xmlrpc_env xmlrpcenv;
+
+struct mcu_pvt {
+	ast_mutex_t lock;               /* Channel private lock */
+	struct ast_channel *owner;	/* owner channel */
+	struct ast_rtp_instance *rtp;
+	struct ast_rtp_instance *vrtp; /* Placeholder for now */
+	time_t lastrtptx;
+	time_t lastrtprx;
+	xmlrpc_client *xr_client;
+	ast_mutex_t xrlock;
+	ast_cond_t xrcond;
+	int xreqs;
+	int stop_rpc;
+	struct ast_format_cap *cap;
+	char *clid;
+	// char mcuId[MAXHOSTNAMELEN];
+	int confId;
+	int partId;
+	int audio_port, video_port;
+	char *a_redirip, *a_redirport;
+	char *v_redirip, *v_redirport;
+	struct mcu_call* mcu_call;
+	enum AudioType audio_codec;
+	enum VideoType video_codec;
+	int init_done;
+	pthread_t finishThread;
+//
+	xmlrpc_server_info *qxr_server;
+	char *qxr_method;
+	xmlrpc_value *qxr_parm;
+	xmlrpc_response_handler *qxr_cbfunc;
+	xmlrpc_env env;
+//
+	struct mcu_pvt* next;
+};
+
+/* Forward declarations */
+static struct ast_channel *mcu_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, void *data, int *cause);
+static int mcu_call(struct ast_channel *ast, char *dest, int timeout);
+static int mcu_hangup(struct ast_channel *ast);
+static struct ast_frame *mcu_read(struct ast_channel *ast);
+static int mcu_write(struct ast_channel *ast, struct ast_frame *f);
+static int mcu_indicate(struct ast_channel *ast, int condition, const void *data, size_t datalen);
+static int mcu_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
+static struct ast_frame  *mcu_rtp_read(struct ast_channel *ast, struct mcu_pvt *p);
+
+static void mcu_destroy(struct mcu_pvt *pvt);
+
+static int reload_config(int reload);
+
+
+/* direct xmlrpc calls */
+void SendStartAudio(struct mcu_pvt *p);
+void SendStartVideo(struct mcu_pvt *p);
+void SendReStartSending(struct mcu_pvt *p);
+
+/* callbacks from xmlrpc lib */
+void onCreateParticipant(const char* url, const char* method, xmlrpc_value *params, void *user_data,
+                                xmlrpc_env *faultP, xmlrpc_value *resultP);
+void onStartAudioReceiving(const char* url, const char* method, xmlrpc_value *params, void *user_data, 
+				xmlrpc_env *faultP, xmlrpc_value *resultP);
+void onStartVideoReceiving(const char* url, const char* method, xmlrpc_value *params, void *user_data, 
+				xmlrpc_env *faultP, xmlrpc_value *resultP);
+void onAddMosaicParticipant(const char* url, const char* method, xmlrpc_value *params, void *user_data, 
+				xmlrpc_env *faultP, xmlrpc_value *resultP);
+void onAddSidebarParticipant(const char* url, const char* method, xmlrpc_value *params, void *user_data, 
+				xmlrpc_env *faultP, xmlrpc_value *resultP);
+void onSetAudioCodec(const char* url, const char* method, xmlrpc_value *params, void *user_data, 
+				xmlrpc_env *faultP, xmlrpc_value *resultP);
+void onSetVideoCodec(const char* url, const char* method, xmlrpc_value *params, void *user_data, 
+				xmlrpc_env *faultP, xmlrpc_value *resultP);
+void onStartAudioSending(const char* url, const char* method, xmlrpc_value *params, void *user_data, 
+				xmlrpc_env *faultP, xmlrpc_value *resultP);
+void onStartVideoSending(const char* url, const char* method, xmlrpc_value *params, void *user_data, 
+				xmlrpc_env *faultP, xmlrpc_value *resultP);
+void onReStartAudioSending(const char* url, const char* method, xmlrpc_value *params, void *user_data, 
+				xmlrpc_env *faultP, xmlrpc_value *resultP);
+void onDeleteParticipant(const char* url, const char* method, xmlrpc_value *params, void *user_data, 
+				xmlrpc_env *faultP, xmlrpc_value *resultP);
+
+/* Channel driver declaration */
+static struct ast_channel_tech mcu_tech = {
+	.type = "MCU",
+	.description = tdesc,
+	.requester = mcu_request,
+	.call = mcu_call,
+	.hangup = mcu_hangup,
+	.read = mcu_read,
+	.write = mcu_write,
+	.write_video = mcu_write,
+	.write_text = mcu_write,
+	.indicate = mcu_indicate,
+	.fixup = mcu_fixup,
+	.bridge = ast_rtp_instance_bridge,
+	.early_bridge = ast_rtp_instance_early_bridge,
+};
+
+static enum ast_rtp_glue_result mcu_get_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance **rtp);
+static enum ast_rtp_glue_result mcu_get_vrtp_peer(struct ast_channel *chan, struct ast_rtp_instance **rtp);
+static void mcu_get_codec(struct ast_channel *chan, struct ast_format_cap *result);
+static int mcu_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *instance, struct ast_rtp_instance *vinstance, struct ast_rtp_instance *tinstance, const struct ast_format_cap *cap, int nat_active);
+
+static struct ast_rtp_glue mcu_rtp = {
+        .type = type,
+        .get_rtp_info = mcu_get_rtp_peer,
+        .get_vrtp_info = mcu_get_vrtp_peer,
+        .update_peer = mcu_set_rtp_peer,
+	.get_codec = mcu_get_codec,
+};
+
+
+AST_MUTEX_DEFINE_STATIC(mcu_cn_lock);
+static long int mcu_callnum = 0;
+
+static int mcuDebug = 1;	/* Debug flag */
+
+static void loop_cleanup(void* dummy) 
+{
+	struct mcu_pvt *pvt = (struct mcu_pvt *) dummy;
+	ast_verbose("-- loop thread cleaned\n");
+	ast_mutex_destroy(&pvt->xrlock);
+	ast_cond_destroy(&pvt->xrcond);
+	xmlrpc_client_destroy(pvt->xr_client);
+	xmlrpc_server_info_free(pvt->qxr_server);
+
+	ast_mutex_destroy(&pvt->lock);
+
+	pvt->cap = ast_format_cap_destroy(pvt->cap);
+	if (pvt->rtp) {
+		ast_rtp_instance_destroy(pvt->rtp);
+	}
+	if (pvt->vrtp) {
+		ast_rtp_instance_destroy(pvt->vrtp);
+	}
+
+	if (pvt->mcu_call) {
+		free(pvt->mcu_call);
+	}
+
+	free(pvt);
+}
+
+static void* xmlrpc_loop(void* dummy) {
+	struct mcu_pvt *pvt = (struct mcu_pvt *) dummy;
+	ast_verbose("-- loop started\n");
+
+	ast_mutex_lock(&pvt->xrlock);
+
+	while (!pvt->stop_rpc) {
+		struct timeval wait;
+		struct timespec ts;
+
+		wait = ast_tvadd(ast_tvnow(), ast_samp2tv(300, 1000));
+		ts.tv_sec = wait.tv_sec;
+		ts.tv_nsec = wait.tv_usec * 1000;
+		ast_cond_timedwait(&pvt->xrcond, &pvt->xrlock, &ts);
+
+		while (pvt->xreqs) {
+			pvt->xreqs = 0;
+			ast_verbose("--- loop thread sending %s\n", pvt->qxr_method);
+			xmlrpc_client_start_rpc(&pvt->env, pvt->xr_client, pvt->qxr_server, pvt->qxr_method, pvt->qxr_parm, 
+								pvt->qxr_cbfunc, (void *)pvt);
+			if (pvt->env.fault_code) {
+				ast_log(LOG_ERROR, "xmlrpc parse fault %d:%s\n", pvt->env.fault_code, pvt->env.fault_string);
+				continue;
+			}
+			xmlrpc_client_event_loop_finish(pvt->xr_client);
+			// xmlrpc_DECREF(pvt->qxr_parm);
+			
+		}
+
+	}
+
+	ast_mutex_unlock(&pvt->xrlock);
+	ast_verbose("-- loop exited\n");
+	return NULL;	// never here
+}
+
+static void* loop_thread(void *dummy)
+{
+	void *ret = NULL;
+	pthread_cleanup_push(loop_cleanup, dummy);
+	ret = xmlrpc_loop(dummy);
+	pthread_cleanup_pop(1);
+	return ret;
+}
+
+
+static int mcu_write(struct ast_channel *ast, struct ast_frame *f)
+{
+	struct mcu_pvt *p = ast->tech_pvt;
+	struct ast_format tmpfmt;
+	int res = 0;
+	if (p) {
+		ast_mutex_lock(&p->lock);
+		if (!p->init_done) {
+			ast_mutex_unlock(&p->lock);
+			return res;
+		}
+		p->lastrtptx = time(NULL);
+		switch (f->frametype) {
+		case AST_FRAME_VOICE:
+			if (p->rtp) {
+				if (!p->audio_codec) {
+					if ((ast_format_cap_iscompatible(p->owner->nativeformats, ast_format_set(&tmpfmt, AST_FORMAT_ALAW, 0)))) {
+						p->audio_codec = PCMA;	// alaw preffered
+					} else {
+						p->audio_codec = SPEEX16;
+					}
+					SendStartAudio(p);
+				}
+				if (!p->video_codec && p->audio_port) {
+#ifdef AST_FORMAT_VP8
+					if ((ast_format_cap_iscompatible(p->owner->nativeformats, ast_format_set(&tmpfmt, AST_FORMAT_VP8, 0)))) {
+						p->video_codec = VP8;
+					} else {
+						p->video_codec = H264;
+					}
+#else
+					p->video_codec = H264;
+#endif
+					SendStartVideo(p);
+				}
+				res = ast_rtp_instance_write(p->rtp, f);
+			}
+			break;
+		case AST_FRAME_VIDEO:
+			if (p->vrtp) {
+				res = ast_rtp_instance_write(p->vrtp, f);
+			}
+			break;
+		default:
+			ast_log(LOG_WARNING, "Can't send to %s frame type of %d\n", ast->name,
+						f->frametype);
+		}
+		ast_mutex_unlock(&p->lock);
+	}
+
+	return res;
+}
+
+
+
+static struct ast_frame *mcu_read(struct ast_channel *ast)
+{
+	struct ast_frame *fr;
+	static struct ast_frame null_frame = { AST_FRAME_NULL, };
+	struct mcu_pvt *p = ast->tech_pvt;
+	
+	if (!p) {
+		return &null_frame;
+	}
+	ast_mutex_lock(&p->lock);
+	if (p->rtp) {
+		fr = mcu_rtp_read(ast, p);
+	} else {
+		fr = &null_frame;
+	}
+	ast_mutex_unlock(&p->lock);
+	return fr;
+}
+
+/*! \brief Function called when we should read a frame from the channel */
+static struct ast_frame  *mcu_rtp_read(struct ast_channel *ast, struct mcu_pvt *p)
+{
+	static struct ast_frame null_frame = { AST_FRAME_NULL, };
+	struct ast_frame *f = &null_frame;
+	switch (ast->fdno) {
+		case 0:		// Audio
+			f = ast_rtp_instance_read(p->rtp, 0);
+			p->lastrtprx = time(NULL);
+			break;
+		case 1:		// RTCP
+			f = ast_rtp_instance_read(p->rtp, 1);
+			break;
+		case 2:		// Video
+			f = ast_rtp_instance_read(p->vrtp, 0);
+			p->lastrtprx = time(NULL);
+			break;
+		case 3:		// RTCP Video
+			f = ast_rtp_instance_read(p->vrtp, 0);
+			break;
+		default:
+			f = &null_frame;
+	}
+
+	if (f && p->owner && (f->frametype == AST_FRAME_VOICE)) {
+		/* We already hold the channel lock */
+		if (!(ast_format_cap_iscompatible(p->owner->nativeformats, &f->subclass.format))) {
+			ast_debug(1, "Oooh, voice format changed to %s\n", ast_getformatname(&f->subclass.format));
+			ast_format_cap_set(p->owner->nativeformats, &f->subclass.format);
+			ast_set_read_format(p->owner, &p->owner->readformat);
+			ast_set_write_format(p->owner, &p->owner->writeformat);
+		}
+	}
+	return f;
+}
+
+static int configure_rtp(struct mcu_pvt *pvt) {
+
+
+	//struct ast_sockaddr tmp;
+	//ast_parse_arg("::", PARSE_ADDR, &tmp);
+
+	if (!(pvt->rtp = ast_rtp_instance_new("asterisk", sched, &bindaddr, NULL))) {
+		ast_log(LOG_ERROR, "Unable to create RTP session: %s\n", strerror(errno));
+		return 0;
+	}
+	if (!(pvt->vrtp = ast_rtp_instance_new("asterisk", sched, &bindaddr, NULL))) {
+		ast_log(LOG_ERROR, "Unable to create video RTP session: %s\n", strerror(errno));
+		return 0;
+	}
+
+	if (pvt->owner) {
+		while (pvt->owner && ast_channel_trylock(pvt->owner)) {
+			ast_debug(1,"Failed to grab lock, trying again\n");
+			DEADLOCK_AVOIDANCE(&pvt->lock);
+		}
+		if (!pvt->owner) {
+			ast_log(LOG_ERROR, "Channel has no owner\n");
+			return 0;
+		}
+	} else {
+		ast_log(LOG_ERROR, "Channel has no owner\n");
+		return 0;
+	}
+
+	ast_channel_set_fd(pvt->owner, 0, ast_rtp_instance_fd(pvt->rtp, 0));
+	ast_channel_set_fd(pvt->owner, 1, ast_rtp_instance_fd(pvt->rtp, 1));
+	ast_channel_set_fd(pvt->owner, 2, ast_rtp_instance_fd(pvt->vrtp, 0));
+	ast_channel_set_fd(pvt->owner, 3, ast_rtp_instance_fd(pvt->vrtp, 1));
+
+	ast_channel_unlock(pvt->owner);
+
+	return 1;
+}
+
+static struct mcu_pvt *mcu_alloc(char *url)
+{
+	struct mcu_pvt *pvt = NULL;
+	// struct xmlrpc_clientparms clientParms;
+
+	if (mcuDebug) {
+		ast_verbose("--- mcu alloc for %s" , url);
+	}
+
+	if (!(pvt = ast_calloc(1, sizeof(*pvt)))) {
+		ast_log(LOG_ERROR, "Couldn't allocate private mcu structure\n");
+		return NULL;
+	}
+
+	if (!(pvt->cap = ast_format_cap_alloc_nolock())) {
+		ast_free(pvt);
+		ast_log(LOG_ERROR, "Couldn't allocate private mcu structure\n");
+		return NULL;
+	}
+
+	/* initialize xmlrpc structure here */
+
+	// clientParms.transport = "curl";
+	xmlrpc_client_create(&xmlrpcenv, XMLRPC_CLIENT_NO_FLAGS, xmlrpc_cname, xmlrpc_cversion, 
+				NULL, 0, &pvt->xr_client);
+				// &clientParms, XMLRPC_CPSIZE(transport), &pvt->xr_client);
+
+	if (!pvt->xr_client) {
+		ast_log(LOG_ERROR, "Couldn't allocate xmlrpc client data, fault is %d:%s\n", xmlrpcenv.fault_code, xmlrpcenv.fault_string);
+		return NULL;
+	}
+
+
+	ast_mutex_init(&pvt->lock);
+	ast_mutex_lock(&pvt->lock);
+
+	ast_mutex_init(&pvt->xrlock);
+	ast_cond_init(&pvt->xrcond, NULL);
+
+	ast_mutex_unlock(&pvt->lock);
+	return pvt;
+}
+
+static void mcu_destroy(struct mcu_pvt *pvt)
+{
+	ast_mutex_lock(&pvt->lock);
+
+	if (pvt->clid) {
+		free(pvt->clid);
+	}
+
+	if (pvt->a_redirip) {
+		free(pvt->a_redirip);
+	}
+	if (pvt->a_redirport) {
+		free(pvt->a_redirport);
+	}
+	if (pvt->v_redirip) {
+		free(pvt->v_redirip);
+	}
+	if (pvt->v_redirport) {
+		free(pvt->v_redirport);
+	}
+
+	if (pvt->owner) {
+		while(ast_channel_trylock(pvt->owner)) {
+			ast_debug(1, "Failed to grab lock, trying again\n");
+			DEADLOCK_AVOIDANCE(&pvt->lock);
+		}
+		ast_debug(1, "Detaching from %s\n", pvt->owner->name);
+		pvt->owner->tech_pvt = NULL;
+		ast_channel_unlock(pvt->owner);
+		pvt->owner = NULL;
+		ast_module_unref(myself);
+	}
+
+	/* ast_mutex_lock(&pvt->xrlock);
+	xmlrpc_client_destroy(pvt->xr_client);
+	pvt->xr_client = NULL;
+	ast_mutex_unlock(&pvt->xrlock); */
+
+	pvt->stop_rpc = 1;
+
+	ast_mutex_unlock(&pvt->lock);
+}
+static struct ast_channel*  mcu_chan_new(struct mcu_pvt *p, int state, char *url, struct ast_format_cap *cap, 
+					const char *linkedid)
+{
+	struct ast_channel *chan = NULL;
+	struct ast_format tmpfmt;
+
+	if (mcuDebug) {
+		ast_verbose("--- mcu_new %s\n", url);
+	}
+	ast_mutex_lock(&mcu_cn_lock);
+	chan = ast_channel_alloc(1, state, "", "", "", "", "", linkedid, 0, "MCU/%s-%ld", url, mcu_callnum);
+	mcu_callnum++;
+	ast_mutex_unlock(&mcu_cn_lock);
+	if (chan) {
+		ast_channel_lock(chan);
+		chan->tech = &mcu_tech;
+		if (cap) {
+			ast_format_cap_copy(chan->nativeformats, cap);
+			ast_best_codec(cap, &tmpfmt);
+			ast_format_copy(&chan->rawwriteformat, &tmpfmt);
+			ast_format_copy(&chan->rawwriteformat, &tmpfmt);
+			ast_set_write_format(chan, &tmpfmt);
+			ast_set_read_format(chan, &tmpfmt);
+		}
+		chan->tech_pvt = (void *)p;
+		p->owner = chan;
+		ast_module_ref(myself);
+		ast_update_use_count();
+		ast_setstate(chan, state);
+		ast_channel_unlock(chan);
+	}
+
+	return chan;
+}
+
+/*! \brief Function called when we should prepare to call the destination */
+static struct ast_channel *mcu_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, void *data, int *cause)
+{
+	struct ast_channel *chan;
+	char formats[FORMAT_STRING_SIZE];
+	struct mcu_pvt *p;
+	struct ast_format tmpfmt;
+
+
+	if (mcuDebug) {
+		ast_verbose("mcu_request data %s format %s\n", (char *)data,
+				ast_getformatname_multiple(formats,FORMAT_STRING_SIZE,cap));
+	}
+
+	if (!(ast_format_cap_has_type(cap, AST_FORMAT_TYPE_AUDIO)) ||
+			 (!(ast_format_cap_iscompatible(cap, ast_format_set(&tmpfmt, AST_FORMAT_ALAW, 0))) && !(ast_format_cap_iscompatible(cap, ast_format_set(&tmpfmt, AST_FORMAT_SPEEX16, 0))))) {
+		ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%s' (we support alaw audio only now)\n", 
+					ast_getformatname_multiple(formats,FORMAT_STRING_SIZE,cap));
+		goto failure;
+	}
+
+	// h.264 and vp8 only now
+	if (ast_format_cap_has_type(cap, AST_FORMAT_TYPE_VIDEO)) {
+#ifdef AST_FORMAT_VP8
+		if (!(ast_format_cap_iscompatible(cap, ast_format_set(&tmpfmt, AST_FORMAT_H264, 0))) &&
+				!(ast_format_cap_iscompatible(cap, ast_format_set(&tmpfmt, AST_FORMAT_VP8, 0)))) {
+#else
+		if (!(ast_format_cap_iscompatible(cap, ast_format_set(&tmpfmt, AST_FORMAT_H264, 0)))) {
+#endif
+			ast_log(LOG_NOTICE, "H.264 or VP8 video only supported\n");
+			goto failure;
+		}
+	}
+
+	if (!(p = mcu_alloc((char *)data))) {
+		ast_log(LOG_WARNING, "Can't build pvt data for %s\n", (char *)data);
+		goto failure;
+	}
+
+	ast_mutex_lock(&p->lock);
+	chan = mcu_chan_new(p, AST_STATE_DOWN, (char *)data, cap, requestor ? requestor->linkedid : NULL);
+	ast_mutex_unlock(&p->lock);
+
+	if (!chan) {
+		mcu_destroy(p);
+		goto failure;
+	}
+
+	if (!configure_rtp(p)) {
+		mcu_destroy(p);
+		goto failure;
+	}
+
+	if (mcuDebug) {
+		ast_verbose("mcu_request success\n");
+	}
+
+	return chan;
+
+failure:
+	*cause = AST_CAUSE_FAILURE;
+	return NULL;
+}
+
+/*! \brief Function called when we should actually call the destination */
+static int mcu_call(struct ast_channel *ast, char *dest, int timeout)
+{
+	struct mcu_pvt *p = ast->tech_pvt;
+
+	xmlrpc_value *confP, *nameP, *typP, *barP, *mosP;
+
+	pthread_attr_t attr;
+
+	if (!p) {
+		return -1;
+	}
+
+	if (mcuDebug) {
+		ast_verbose("--- MCU Call\n");
+	}
+
+	xmlrpc_env_init(&p->env);
+
+	ast_mutex_lock(&p->lock);
+
+	p->clid = defaultCLID;
+
+	if (ast->connected.id.name.valid && ast->connected.id.name.str && ast->connected.id.name.str[0]) {
+		p->clid = strdup(ast->connected.id.name.str);
+	} else {
+		if (ast->connected.id.number.valid && ast->connected.id.number.str && ast->connected.id.number.str[0]) {
+			p->clid = strdup(ast->connected.id.number.str);
+		}
+	}
+
+	if (dest) {
+		p->mcu_call = get_conference_by_name(dest);
+		if (p->mcu_call) {
+			p->confId = p->mcu_call->confId;
+		} else {
+			return -1;
+		}
+	}
+	if (!p->confId || !p->mcu_call->url) {
+		ast_mutex_unlock(&p->lock);
+		return -1;
+	}
+	p->qxr_server = xmlrpc_server_info_new(&p->env, p->mcu_call->url);
+
+	/* creating xmlrpc finishing thread */
+	ast_mutex_lock(&p->xrlock);
+
+	pthread_attr_init(&attr);
+	if ((errno = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED | PTHREAD_CREATE_JOINABLE))) {
+		ast_log(LOG_WARNING, "pthread_attr_setdetachstate: %s\n", strerror(errno));
+	}
+	if(ast_pthread_create_detached_background(&p->finishThread, NULL, loop_thread, p) < 0) {
+		ast_log(LOG_ERROR, "Unable to start loop thread for channel %s\n", ast->name);
+		ast_mutex_unlock(&p->lock);
+		return -1;
+	}
+
+	/* call mcu to create participaant */
+
+	if (mcuDebug) {
+		ast_verbose("xmlrpc_call: %s \"%s\" %s\n", p->mcu_call->url, "CreateParticipant", p->clid);
+	}
+
+	// xmlrpc_client_start_rpcf(&env, p->xr_client, p->mcuId, "CreateParticipant", onCreateParticipant, p, 
+	//			"(isiii)", p->confId, p->clid, 0,0,0);
+
+	confP = xmlrpc_int_new(&p->env, p->confId);
+	nameP = xmlrpc_string_new(&p->env, p->clid);
+	mosP = xmlrpc_int_new(&p->env, 0);
+	typP = xmlrpc_int_new(&p->env, 0);
+	barP = xmlrpc_int_new(&p->env, 0);
+	p->qxr_parm = xmlrpc_array_new(&p->env);
+	xmlrpc_array_append_item(&p->env, p->qxr_parm, confP);
+	xmlrpc_array_append_item(&p->env, p->qxr_parm, nameP);
+	xmlrpc_array_append_item(&p->env, p->qxr_parm, mosP);
+	xmlrpc_array_append_item(&p->env, p->qxr_parm, typP);
+	xmlrpc_array_append_item(&p->env, p->qxr_parm, barP);
+
+	xmlrpc_DECREF(confP);
+	xmlrpc_DECREF(nameP);
+	xmlrpc_DECREF(mosP);
+	xmlrpc_DECREF(typP);
+	xmlrpc_DECREF(barP);
+
+	p->qxr_cbfunc = onCreateParticipant;
+	p->qxr_method = "CreateParticipant";
+	p->xreqs = 1;
+
+	ast_mutex_unlock(&p->xrlock);
+	ast_cond_signal(&p->xrcond);
+
+	// xmlrpc_client_event_loop_finish(p->xr_client);
+
+	/* xmlrpc_client_call2f(&xmlrpcenv, p->xr_client, p->mcuId, "CreateParticipant", &rpcres, 
+				"(isiii)", p->confId, p->clid, 0,0,0);
+
+	if (xmlrpcenv.fault_code) {
+		ast_log(LOG_ERROR, "xmlrpc fault %d:%s\n", xmlrpcenv.fault_code, xmlrpcenv.fault_string);
+	}
+
+	xmlrpc_parse_value(&xmlrpcenv, rpcres, "{s:(i),*}", "returnVal", &p->partId);
+
+	if (xmlrpcenv.fault_code) {
+		ast_log(LOG_ERROR, "xmlrpc parse fault %d:%s\n", xmlrpcenv.fault_code, xmlrpcenv.fault_string);
+	}
+
+	xmlrpc_DECREF(rpcres);
+
+	if (mcuDebug) {
+		ast_verbose("mcu_call: partId is %s:%d\n", tmpstr, p->partId);
+	} */
+	
+
+	ast_mutex_unlock(&p->lock);
+
+	if (mcuDebug) {
+		ast_verbose("+++ MCU Call\n");
+	}
+
+	return 0;
+}
+
+/*! \brief Function called when we should hang the channel up */
+static int mcu_hangup(struct ast_channel *ast)
+{
+	struct mcu_pvt *p = ast->tech_pvt;
+	xmlrpc_value *confP, *partP;
+	xmlrpc_env env;
+
+	xmlrpc_env_init(&env);
+
+	if (p) {
+		ast_mutex_lock(&p->lock);
+	}
+
+	/* call mcu to delete participaant */
+
+	if (mcuDebug) {
+		ast_verbose("xmlrpc_call: %s \"%s\" %s\n", p->mcu_call->url, "DeleteParticipant", p->clid);
+	}
+
+	ast_mutex_lock(&p->xrlock);
+
+	// xmlrpc_parse_value(env, param_array, "(ii)", &confId,&partId);
+
+	confP = xmlrpc_int_new(&env, p->confId);
+	partP = xmlrpc_int_new(&env, p->partId);
+	p->qxr_parm = xmlrpc_array_new(&env);
+	xmlrpc_array_append_item(&env, p->qxr_parm, confP);
+	xmlrpc_array_append_item(&env, p->qxr_parm, partP);
+
+	xmlrpc_DECREF(confP);
+	xmlrpc_DECREF(partP);
+
+	p->qxr_cbfunc = onDeleteParticipant;
+	p->qxr_method = "DeleteParticipant";
+	p->xreqs = 1;
+
+	ast_mutex_unlock(&p->xrlock);
+	ast_cond_signal(&p->xrcond);
+	ast_mutex_unlock(&p->lock);
+
+	mcu_destroy(p);
+
+	return 0;
+}
+
+static int mcu_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
+{
+	struct mcu_pvt *p = NULL;
+	int ret = -1;
+
+	if (!newchan || !newchan->tech_pvt) {
+		if (!newchan)
+			ast_log(LOG_WARNING, "No new channel! Fixup of %s failed.\n", oldchan->name);
+		if (!newchan->tech_pvt)
+			ast_log(LOG_WARNING, "No MCU tech on new chan, Fixup of %s failed.\n", oldchan->name);
+		return -1;
+	}
+
+	p = newchan->tech_pvt;
+
+	ast_mutex_lock(&p->lock);
+
+	if (p->owner != oldchan) {
+		ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, p->owner);
+	} else {
+		p->owner = newchan;
+		ret = 0;
+	}
+
+	ast_mutex_unlock(&p->lock);
+	return ret;
+}
+
+
+static int mcu_indicate(struct ast_channel *ast, int condition, const void *data, size_t datalen)
+{
+	struct mcu_pvt *p = ast->tech_pvt;
+	int res = -1;
+
+	if (!p) {
+		return -1;
+	}
+
+	if (mcuDebug) {
+		ast_verbose("mcu_indicate %d on %s\n", condition, ast->name);
+	}
+
+	ast_mutex_lock(&p->lock);
+	switch (condition) {
+	case AST_CONTROL_SRCUPDATE:
+	case AST_CONTROL_SRCCHANGE:
+		if (p->rtp) {
+			ast_rtp_instance_update_source(p->rtp);
+		}
+		if (p->vrtp) {
+			ast_rtp_instance_update_source(p->vrtp);
+		}
+		res = 0;
+		break;
+	default:
+		ast_log(LOG_WARNING, "Don't know how to indicate %d on %s\n", condition, ast->name);
+	}
+	ast_mutex_unlock(&p->lock);
+	return res;
+}
+
+
+/*
+	RTP handling
+ */
+
+static void mcu_get_codec(struct ast_channel *chan, struct ast_format_cap *result)
+{
+	ast_format_cap_append(result, chan->nativeformats);
+}
+
+static enum ast_rtp_glue_result mcu_get_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance **rtp)
+{
+	struct mcu_pvt *pvt = NULL;
+	enum ast_rtp_glue_result res = AST_RTP_GLUE_RESULT_REMOTE;
+	struct ast_sockaddr tmp;
+
+	if (!(pvt = (struct mcu_pvt *) chan->tech_pvt) || !pvt->rtp || !pvt->audio_port) {
+		return AST_RTP_GLUE_RESULT_FORBID;
+	}
+
+	ast_mutex_lock(&pvt->lock);
+
+	*rtp = pvt->rtp ? ao2_ref(pvt->rtp, +1), pvt->rtp : NULL;
+	ast_rtp_instance_get_remote_address(*rtp, &tmp);
+	if (mcuDebug) {
+		ast_verbose("mcu_get_rtp_peer  %s -> %s:%d, %d\n", chan->name, ast_sockaddr_stringify_addr(&tmp),
+						ast_sockaddr_port(&tmp), res);
+	}
+
+	ast_mutex_unlock(&pvt->lock);
+	return res;
+	
+}
+
+
+static enum ast_rtp_glue_result mcu_get_vrtp_peer(struct ast_channel *chan, struct ast_rtp_instance **rtp)
+{
+	struct mcu_pvt *pvt = NULL;
+	enum ast_rtp_glue_result res = AST_RTP_GLUE_RESULT_REMOTE;
+	struct ast_sockaddr tmp;
+
+	if (!(pvt = (struct mcu_pvt *) chan->tech_pvt) || !pvt->vrtp || !pvt->video_port) {
+		return AST_RTP_GLUE_RESULT_FORBID;
+	}
+
+	ast_mutex_lock(&pvt->lock);
+
+	/* get rtp from mcu */
+
+
+	*rtp = pvt->vrtp ? ao2_ref(pvt->vrtp, +1), pvt->vrtp : NULL;
+	ast_rtp_instance_get_remote_address(*rtp, &tmp);
+	if (mcuDebug) {
+		ast_verbose("mcu_get_vrtp_peer  %s -> %s:%d, %d\n", chan->name, ast_sockaddr_stringify_addr(&tmp),
+						ast_sockaddr_port(&tmp), res);
+	}
+
+	ast_mutex_unlock(&pvt->lock);
+	return res;
+}
+
+static int mcu_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *instance, struct ast_rtp_instance *vinstance, struct ast_rtp_instance *tinstance, const struct ast_format_cap *cap, int nat_active)
+{
+	struct mcu_pvt* pvt = NULL;
+	struct ast_sockaddr tmp;
+	int changed = 0;
+
+	ast_channel_lock(chan);
+	pvt = chan->tech_pvt;
+	ast_mutex_lock(&pvt->lock);
+
+	if (instance) {
+		ast_rtp_instance_get_remote_address(instance, &tmp);
+		if (pvt->a_redirip && pvt->a_redirport && 
+				!strcmp(pvt->a_redirip, ast_sockaddr_stringify_host(&tmp)) &&
+				!strcmp(pvt->a_redirport, ast_sockaddr_stringify_port(&tmp))) {
+			changed = 0;
+		} else {
+			if (pvt->a_redirip) {
+				free(pvt->a_redirip);
+			}
+			if (pvt->a_redirport) {
+				free(pvt->a_redirport);
+			}
+			pvt->a_redirip = strdup(ast_sockaddr_stringify_host(&tmp));
+			pvt->a_redirport = strdup(ast_sockaddr_stringify_port(&tmp));
+			changed = 1;
+		}
+		if (mcuDebug) {
+			ast_verbose("mcu_set_rtp_peer  %s(a) -> %s:%d (%s)\n", chan->name, ast_sockaddr_stringify_addr(&tmp),
+						ast_sockaddr_port(&tmp), changed ? "changed" : "no change");
+		}
+	}
+	if (vinstance) {
+		ast_rtp_instance_get_remote_address(vinstance, &tmp);
+		if (pvt->v_redirip && pvt->v_redirport && 
+				!strcmp(pvt->v_redirip, ast_sockaddr_stringify_host(&tmp)) &&
+				!strcmp(pvt->v_redirport, ast_sockaddr_stringify_port(&tmp))) {
+			changed = 0;
+		} else {
+			if (pvt->v_redirip) {
+				free(pvt->v_redirip);
+			}
+			if (pvt->v_redirport) {
+				free(pvt->v_redirport);
+			}
+			pvt->v_redirip = strdup(ast_sockaddr_stringify_host(&tmp));
+			pvt->v_redirport = strdup(ast_sockaddr_stringify_port(&tmp));
+			changed = 1;
+		}
+		if (mcuDebug) {
+			ast_verbose("mcu_set_rtp_peer  %s(v) -> %s:%d (%s)\n", chan->name, ast_sockaddr_stringify_addr(&tmp),
+						ast_sockaddr_port(&tmp), changed ? "changed" : "no change");
+		}
+	}
+	if (changed) {
+		SendReStartSending(pvt);
+	}
+	ast_mutex_unlock(&pvt->lock);
+	ast_channel_unlock(chan);
+	return 0;
+}
+
+
+/*
+	Direct XML RPC calls
+ */
+
+void SendReStartSending(struct mcu_pvt *p)
+{
+	xmlrpc_env env;
+	xmlrpc_value *confP, *partP, *mediaP, *ipP, *portP, *rtpmapP, *acP;
+
+	xmlrpc_env_init(&env);
+
+	ast_mutex_unlock(&p->lock);
+	ast_mutex_lock(&p->xrlock);
+	ast_mutex_lock(&p->lock);
+
+	if (p->a_redirip) {
+
+		if (mcuDebug) {
+			ast_verbose("reset audio to %s:%s\n", p->a_redirip, p->a_redirport);
+		}
+
+		confP = xmlrpc_int_new(&env, p->confId);
+		partP = xmlrpc_int_new(&env, p->partId);
+		mediaP = xmlrpc_int_new(&env, 0);		// audio
+
+		ipP = xmlrpc_string_new(&env, p->a_redirip);
+		portP = xmlrpc_int_new(&env, atoi(p->a_redirport));
+	
+		rtpmapP = xmlrpc_struct_new(&env);
+		acP = xmlrpc_int_new(&env, p->audio_codec);
+		if (p->audio_codec == PCMA) {
+			xmlrpc_struct_set_value(&env, rtpmapP, ALAW_PAYLOAD_NAME, acP);
+		} else {
+			xmlrpc_struct_set_value(&env, rtpmapP, SPEEX16_PAYLOAD_NAME, acP);
+		}
+
+		p->qxr_parm = xmlrpc_array_new(&p->env);
+		xmlrpc_array_append_item(&p->env, p->qxr_parm, confP);
+		xmlrpc_array_append_item(&p->env, p->qxr_parm, partP);
+		xmlrpc_array_append_item(&p->env, p->qxr_parm, mediaP);
+		xmlrpc_array_append_item(&p->env, p->qxr_parm, ipP);
+		xmlrpc_array_append_item(&p->env, p->qxr_parm, portP);
+		xmlrpc_array_append_item(&p->env, p->qxr_parm, rtpmapP);
+
+		xmlrpc_DECREF(confP);
+		xmlrpc_DECREF(partP);
+		xmlrpc_DECREF(mediaP);
+		xmlrpc_DECREF(ipP);
+		xmlrpc_DECREF(portP);
+		xmlrpc_DECREF(rtpmapP);
+
+		p->qxr_cbfunc = onReStartAudioSending;
+		p->qxr_method = "StartSending";
+
+		p->xreqs = 1;
+
+		ast_mutex_unlock(&p->xrlock);
+		ast_cond_signal(&p->xrcond);
+	}
+}
+
+void SendStartAudio(struct mcu_pvt *p)
+{
+	xmlrpc_env env;
+	xmlrpc_value *confP, *partP, *codecP;
+
+	xmlrpc_env_init(&env);
+
+	ast_mutex_unlock(&p->lock);
+	ast_mutex_lock(&p->xrlock);
+	ast_mutex_lock(&p->lock);
+
+	if (p->audio_codec) {
+		if (mcuDebug) {
+			ast_verbose("sending SetAudioCodec %d\n", p->audio_codec);
+		}
+
+		confP = xmlrpc_int_new(&p->env, p->confId);
+		partP = xmlrpc_int_new(&p->env, p->partId);
+		codecP = xmlrpc_int_new(&p->env, p->audio_codec);
+		p->qxr_parm = xmlrpc_array_new(&p->env);
+		xmlrpc_array_append_item(&p->env, p->qxr_parm, confP);
+		xmlrpc_array_append_item(&p->env, p->qxr_parm, partP);
+		xmlrpc_array_append_item(&p->env, p->qxr_parm, codecP);
+
+		xmlrpc_DECREF(confP);
+		xmlrpc_DECREF(partP);
+		xmlrpc_DECREF(codecP);
+
+		p->qxr_cbfunc = onSetAudioCodec;
+		p->qxr_method = "SetAudioCodec";
+		p->xreqs = 1;
+
+		ast_mutex_unlock(&p->xrlock);
+		ast_cond_signal(&p->xrcond);
+	}
+
+}
+
+void SendStartVideo(struct mcu_pvt *p)
+{
+	xmlrpc_env env;
+	xmlrpc_value *confP, *partP, *codecP, *modeP, *fpsP, *bitrateP, *qualityP, *fillLevelP, *intraPeriodP;
+
+	xmlrpc_env_init(&env);
+
+	ast_mutex_unlock(&p->lock);
+	while (p->owner && ast_mutex_trylock(&p->xrlock)) {
+		ast_debug(1, "Failed to grab lock, trying again\n");
+		CHANNEL_DEADLOCK_AVOIDANCE(p->owner);
+	}
+	ast_mutex_lock(&p->lock);
+	if (!p->owner) {
+		return;
+	}
+
+	if (p->video_codec) {
+		if (mcuDebug) {
+			ast_verbose("sending SetVideoCodec %d\n", p->video_codec);
+		}
+		confP = xmlrpc_int_new(&p->env, p->confId);
+		partP = xmlrpc_int_new(&p->env, p->partId);
+		codecP = xmlrpc_int_new(&p->env, p->video_codec);
+		modeP = xmlrpc_int_new(&p->env, p->mcu_call->mode);
+		fpsP = xmlrpc_int_new(&p->env, p->mcu_call->fps);
+		bitrateP = xmlrpc_int_new(&p->env, p->mcu_call->bitrate);
+		qualityP = xmlrpc_int_new(&p->env, 0);
+		fillLevelP = xmlrpc_int_new(&p->env, 0);
+		intraPeriodP = xmlrpc_int_new(&p->env, p->mcu_call->intraPeriod);
+		
+		p->qxr_parm = xmlrpc_array_new(&p->env);
+		xmlrpc_array_append_item(&p->env, p->qxr_parm, confP);
+		xmlrpc_array_append_item(&p->env, p->qxr_parm, partP);
+		xmlrpc_array_append_item(&p->env, p->qxr_parm, codecP);
+		xmlrpc_array_append_item(&p->env, p->qxr_parm, modeP);
+		xmlrpc_array_append_item(&p->env, p->qxr_parm, fpsP);
+		xmlrpc_array_append_item(&p->env, p->qxr_parm, bitrateP);
+		xmlrpc_array_append_item(&p->env, p->qxr_parm, qualityP);
+		xmlrpc_array_append_item(&p->env, p->qxr_parm, fillLevelP);
+		xmlrpc_array_append_item(&p->env, p->qxr_parm, intraPeriodP);
+		
+		xmlrpc_DECREF(confP);
+		xmlrpc_DECREF(partP);
+		xmlrpc_DECREF(codecP);
+		xmlrpc_DECREF(modeP);
+		xmlrpc_DECREF(fpsP);
+		xmlrpc_DECREF(bitrateP);
+		xmlrpc_DECREF(qualityP);
+		xmlrpc_DECREF(fillLevelP);
+		xmlrpc_DECREF(intraPeriodP);
+
+		p->qxr_cbfunc = onSetVideoCodec;
+		p->qxr_method = "SetVideoCodec";
+		p->xreqs = 1;
+
+		ast_mutex_unlock(&p->xrlock);
+		ast_cond_signal(&p->xrcond);
+	}
+
+}
+
+/*
+	Callbacks from XMLRPC lib
+ */
+
+void onCreateParticipant(const char* url, const char* method, xmlrpc_value *params, void *user_data, 
+				xmlrpc_env *faultP, xmlrpc_value *resultP)
+{
+	struct ast_channel *c;
+	struct mcu_pvt *p = (struct mcu_pvt *)user_data;
+	xmlrpc_env env;
+
+	xmlrpc_value *confP, *partP, *posP;
+
+	xmlrpc_env_init(&env);
+	ast_mutex_lock(&p->lock);
+
+	if (mcuDebug) {
+		ast_verbose("onCreateParticipant\n");
+	}
+	if (!faultP->fault_occurred) {
+		xmlrpc_parse_value(&p->env, resultP, "{s:(i),*}", "returnVal", &p->partId);
+		if (p->env.fault_code) {
+			ast_log(LOG_ERROR, "xmlrpc parse fault %d:%s\n", p->env.fault_code, p->env.fault_string);
+		}
+		// xmlrpc_DECREF(resultP);
+		if (!p->partId) {
+			ast_log(LOG_ERROR, "participant ID not returned\n");
+		}
+	}
+
+	ast_verbose("+++ partId = %d\n", p->partId);
+
+	if (!p->owner) {
+		ast_log(LOG_ERROR, "No matching call found\n");
+		ast_mutex_unlock(&p->lock);
+		return;
+	}
+
+	while (p->owner && ast_channel_trylock(p->owner)) {
+		ast_debug(1, "Failed to grab lock, trying again\n");
+		DEADLOCK_AVOIDANCE(&p->lock);
+	}
+
+	if (!p->owner) {
+		ast_log(LOG_ERROR, "No matching call found\n");
+		ast_mutex_unlock(&p->lock);
+		return;
+	}
+
+	c = p->owner;
+
+	if (p->partId) {
+		ast_queue_control(c, AST_CONTROL_PROCEEDING);
+	} else {
+		ast_queue_control(c, AST_CONTROL_HANGUP);
+		ast_channel_unlock(c);
+		ast_mutex_unlock(&p->lock);
+		return;
+	}
+
+	/* Sending StartReceiving for audio */
+
+	/* ast_format_cap_iter_start(chan->nativeformats);
+	while (!ast_format_cap_iter_next(chan->nativeformats, &tmpfmt)) {
+		if (AST_FORMAT_GET_TYPE(tmpfmt.id) == AST_FORMAT_TYPE_AUDIO) {
+			continue;
+		}
+	} */
+
+	// Fix me here !!! we must get codec payload
+	// audio_codec = ast_rtp_codecs_get_payload_format();
+
+	ast_channel_unlock(c);
+
+	if (mcuDebug) {
+		ast_verbose("sending AddMosaicParticipant to mcu on %s\n", c->name);
+	}
+	xmlrpc_env_init(&env);
+	confP = xmlrpc_int_new(&env, p->confId);
+	partP = xmlrpc_int_new(&env, p->partId);
+	posP = xmlrpc_int_new(&env, 0);
+	p->qxr_parm = xmlrpc_array_new(&env);
+	xmlrpc_array_append_item(&env, p->qxr_parm, confP);
+	xmlrpc_array_append_item(&env, p->qxr_parm, posP);
+	xmlrpc_array_append_item(&env, p->qxr_parm, partP);
+
+	xmlrpc_DECREF(confP);
+	xmlrpc_DECREF(partP);
+	xmlrpc_DECREF(posP);
+
+	p->qxr_cbfunc = onAddMosaicParticipant;
+	p->qxr_method = "AddMosaicParticipant";
+	p->xreqs = 1;
+	ast_mutex_unlock(&p->lock);
+	
+}
+
+void onAddMosaicParticipant(const char* url, const char* method, xmlrpc_value *params, void *user_data, 
+				xmlrpc_env *faultP, xmlrpc_value *resultP)
+{
+	struct mcu_pvt *p = (struct mcu_pvt *)user_data;
+	struct ast_channel *c;
+	int rc = 0;
+	xmlrpc_env env;
+
+	xmlrpc_value *confP, *partP, *posP;
+
+	xmlrpc_env_init(&env);
+
+	ast_mutex_lock(&p->lock);
+	if (mcuDebug) {
+		ast_verbose("onAddMosaicParticipant\n");
+	}
+
+	if (!faultP->fault_occurred) {
+		xmlrpc_parse_value(&env, resultP, "{s:i,*}", "returnCode", &rc);
+		if (env.fault_code) {
+			ast_log(LOG_ERROR, "xmlrpc parse fault %d:%s\n", env.fault_code, env.fault_string);
+		}
+		// xmlrpc_DECREF(resultP);
+	}
+
+	if (!p->owner) {
+		ast_log(LOG_ERROR, "No matching call found\n");
+		ast_mutex_unlock(&p->lock);
+		return;
+	}
+
+	while (p->owner && ast_channel_trylock(p->owner)) {
+		ast_debug(1, "Failed to grab lock, trying again\n");
+		DEADLOCK_AVOIDANCE(&p->lock);
+	}
+
+	if (!p->owner) {
+		ast_log(LOG_ERROR, "No matching call found\n");
+		ast_mutex_unlock(&p->lock);
+		return;
+	}
+
+	c = p->owner;
+
+	if (rc != 1) {
+		ast_queue_control(c, AST_CONTROL_HANGUP);
+		ast_channel_unlock(c);
+		ast_mutex_unlock(&p->lock);
+		return;
+	}
+
+	ast_channel_unlock(c);
+	
+
+	if (mcuDebug) {
+		ast_verbose("sending AddSideBarParticipant to mcu on %s\n", c->name);
+	}
+	xmlrpc_env_init(&env);
+	confP = xmlrpc_int_new(&env, p->confId);
+	partP = xmlrpc_int_new(&env, p->partId);
+	posP = xmlrpc_int_new(&env, 0);
+	p->qxr_parm = xmlrpc_array_new(&env);
+	xmlrpc_array_append_item(&env, p->qxr_parm, confP);
+	xmlrpc_array_append_item(&env, p->qxr_parm, posP);
+	xmlrpc_array_append_item(&env, p->qxr_parm, partP);
+
+	xmlrpc_DECREF(confP);
+	xmlrpc_DECREF(partP);
+	xmlrpc_DECREF(posP);
+
+	p->qxr_cbfunc = onAddSidebarParticipant;
+	p->qxr_method = "AddSidebarParticipant";
+	p->xreqs = 1;
+	ast_mutex_unlock(&p->lock);
+}
+
+void onAddSidebarParticipant(const char* url, const char* method, xmlrpc_value *params, void *user_data, 
+				xmlrpc_env *faultP, xmlrpc_value *resultP)
+{
+	struct mcu_pvt *p = (struct mcu_pvt *)user_data;
+	struct ast_channel *c;
+	int rc = 0;
+	xmlrpc_env env;
+
+	xmlrpc_env_init(&env);
+	ast_mutex_lock(&p->lock);
+	if (mcuDebug) {
+		ast_verbose("onAddSideBarParticipant\n");
+	}
+
+	if (!faultP->fault_occurred) {
+		xmlrpc_parse_value(&env, resultP, "{s:i,*}", "returnCode", &rc);
+		if (env.fault_code) {
+			ast_log(LOG_ERROR, "xmlrpc parse fault %d:%s\n", env.fault_code, env.fault_string);
+		}
+		// xmlrpc_DECREF(resultP);
+	}
+
+	if (!p->owner) {
+		ast_log(LOG_ERROR, "No matching call found\n");
+		ast_mutex_unlock(&p->lock);
+		return;
+	}
+
+	while (p->owner && ast_channel_trylock(p->owner)) {
+		ast_debug(1, "Failed to grab lock, trying again\n");
+		DEADLOCK_AVOIDANCE(&p->lock);
+	}
+
+	if (!p->owner) {
+		ast_log(LOG_ERROR, "No matching call found\n");
+		ast_mutex_unlock(&p->lock);
+		return;
+	}
+
+	c = p->owner;
+
+	if (rc == 1) {
+		ast_queue_control(c, AST_CONTROL_PROGRESS);
+	} else {
+		ast_queue_control(c, AST_CONTROL_HANGUP);
+		ast_channel_unlock(c);
+		ast_mutex_unlock(&p->lock);
+		return;
+	}
+
+	ast_channel_unlock(c);
+
+	p->init_done = 1;
+	ast_mutex_unlock(&p->lock);
+}
+

[... 1745 lines stripped ...]



More information about the asterisk-commits mailing list