Author: may
Date: Thu Aug  8 14:05:28 2013
New Revision: 396416

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

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

Modified: team/may/chan_mcu/branches/1.8/addons/Makefile
URL: 
http://svnview.digium.com/svn/asterisk/team/may/chan_mcu/branches/1.8/addons/Makefile?view=diff&rev=396416&r1=396415&r2=396416
==============================================================================
--- team/may/chan_mcu/branches/1.8/addons/Makefile (original)
+++ team/may/chan_mcu/branches/1.8/addons/Makefile Thu Aug  8 14:05: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/1.8/addons/chan_mcu.c
URL: 
http://svnview.digium.com/svn/asterisk/team/may/chan_mcu/branches/1.8/addons/chan_mcu.c?view=auto&rev=396416
==============================================================================
--- team/may/chan_mcu/branches/1.8/addons/chan_mcu.c (added)
+++ team/may/chan_mcu/branches/1.8/addons/chan_mcu.c Thu Aug  8 14:05: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 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, format_t 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,
+       .capabilities = -1,
+       .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 format_t mcu_get_codec(struct ast_channel *chan);
+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, format_t 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;
+       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 (p->owner->nativeformats & 
AST_FORMAT_ALAW) {
+                                               p->audio_codec = PCMA;  // alaw 
preferred
+                                       } else {
+                                               p->audio_codec = SPEEX16;
+                                       }
+                                       SendStartAudio(p);
+                               }
+                               if (!p->video_codec && p->audio_port) {
+#ifdef AST_FORMAT_VP8
+                                       if (p->owner->nativeformats & 
AST_FORMAT_VP8) {
+                                               p->video_codec = VP8;   // vp8 
preferred
+                                       } else {
+#endif
+                                               p->video_codec = H264;
+#ifdef AST_FORMAT_VP8
+                                       }
+#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 (!(f->subclass.codec & p->owner->nativeformats)) {
+                       ast_debug(1, "Oooh, voice format changed to %s\n", 
ast_getformatname(f->subclass.codec));
+                       p->owner->nativeformats = f->subclass.codec;
+                       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;
+
+       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, format_t cap, 
+                                       const char *linkedid)
+{
+       struct ast_channel *chan = NULL;
+       format_t tmpfmt = 0;
+
+       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) {
+                       tmpfmt = ast_best_codec(cap);
+                       tmpfmt |= (cap & AST_FORMAT_VIDEO_MASK);
+               }
+               chan->nativeformats = chan->rawwriteformat = 
chan->rawreadformat = 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, format_t cap, const 
struct ast_channel *requestor, void *data, int *cause)
+{
+       struct ast_channel *chan;
+       char formats[FORMAT_STRING_SIZE];
+       struct mcu_pvt *p;
+
+       if (mcuDebug) {
+               ast_verbose("mcu_request data %s format %s\n", (char *)data,
+                               
ast_getformatname_multiple(formats,FORMAT_STRING_SIZE,cap));
+       }
+
+       if (!(cap & AST_FORMAT_AUDIO_MASK) || (!(cap & AST_FORMAT_SPEEX16) && 
!(cap & AST_FORMAT_ALAW))) {
+               ast_log(LOG_NOTICE, "Asked to get a channel of unsupported 
format '%s' (we support alaw/speex16 audio only now)\n", 
+                                       
ast_getformatname_multiple(formats,FORMAT_STRING_SIZE,cap));
+               goto failure;
+       }
+
+       // h.264 and vp8 only now
+       if ((cap & AST_FORMAT_VIDEO_MASK)) {
+               if (!(cap & AST_FORMAT_H264)
+#ifdef AST_FORMAT_VP8
+               && !(cap & AST_FORMAT_VP8)
+#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 format_t mcu_get_codec(struct ast_channel *chan)
+{
+       return 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, format_t codecs, 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);
+}
+
+void onSetAudioCodec(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, *rtpmapP, *acP, *mediaP;
+       
+
+       xmlrpc_env_init(&env);
+       ast_mutex_lock(&p->lock);
+       if (mcuDebug) {
+               ast_verbose("onSetAudioCodec\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)) {

[... 1713 lines stripped ...]

--
_____________________________________________________________________
-- Bandwidth and Colocation Provided by http://www.api-digital.com --

svn-commits mailing list
To UNSUBSCRIBE or update options visit:
   http://lists.digium.com/mailman/listinfo/svn-commits

Reply via email to