diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/UsersApp.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/UsersApp.scala
index d6414a1b3e2e8f77502686ed377f8ddfa2bedd39..4b3087ec946ec4400f364d86b2f93f151a99a2f7 100755
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/UsersApp.scala
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/UsersApp.scala
@@ -420,7 +420,8 @@ trait UsersApp {
   }
 
   def handleUserJoinedVoiceFromPhone(msg: UserJoinedVoiceConfMessage) = {
-    log.info("User joining from phone.  meetingId=" + props.meetingProp.intId + " userId=" + msg.userId + " extUserId=" + msg.externUserId)
+    log.info("User joining from phone.  meetingId=" + props.meetingProp.intId + " userId=" + msg.userId
+      + " extUserId=" + msg.externUserId)
 
     Users.getUserWithVoiceUserId(msg.voiceUserId, liveMeeting.users) match {
       case Some(user) => {
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/models/RegisteredUsers.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/models/RegisteredUsers.scala
index 3c3874ccd8a78c6fdfeb1df4df5afe49835289a4..81f14bf67227b65f13200925272a2993e11cdc31 100755
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/models/RegisteredUsers.scala
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/models/RegisteredUsers.scala
@@ -63,14 +63,7 @@ class RegisteredUsers {
   }
 }
 
-case class RegisteredUser(
-  id: String,
-  externId: String,
-  name: String,
-  role: String,
-  authToken: String,
-  avatarURL: String,
-  guest: Boolean,
-  authed: Boolean,
-  waitingForAcceptance: Boolean)
+case class RegisteredUser(id: String, externId: String, name: String, role: String,
+  authToken: String, avatarURL: String, guest: Boolean,
+  authed: Boolean, waitingForAcceptance: Boolean)
 
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/models/UsersStatus.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/models/UsersStatus.scala
new file mode 100755
index 0000000000000000000000000000000000000000..64a2e8558e40b61d6a102be1d01b1a1a680d8c65
--- /dev/null
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/models/UsersStatus.scala
@@ -0,0 +1,65 @@
+package org.bigbluebutton.core.models
+
+import com.softwaremill.quicklens.modify
+
+object UsersStatus {
+  def findWithId(users: UsersStatus, userId: String): Option[UserStatus] = users.toVector.find(u => u.id == userId)
+  def findModerators(users: UsersStatus): Vector[UserStatus] = users.toVector.filter(u => u.role == Roles.MODERATOR_ROLE)
+  def findPresenters(users: UsersStatus): Vector[UserStatus] = users.toVector.filter(u => u.role == Roles.PRESENTER_ROLE)
+  def findViewers(users: UsersStatus): Vector[UserStatus] = users.toVector.filter(u => u.role == Roles.VIEWER_ROLE)
+  def hasModerator(users: UsersStatus): Boolean = users.toVector.filter(u => u.role == Roles.MODERATOR_ROLE).length > 0
+  def hasPresenter(users: UsersStatus): Boolean = users.toVector.filter(u => u.role == Roles.PRESENTER_ROLE).length > 0
+  def hasNoPresenter(users: UsersStatus): Boolean = users.toVector.filter(u => u.role == Roles.PRESENTER_ROLE).length == 0
+
+  def hasUserWithId(users: UsersStatus, id: String): Boolean = {
+    findWithId(users, id) match {
+      case Some(u) => true
+      case None => false
+    }
+  }
+  def numUsers(users: UsersStatus): Int = users.toVector.size
+
+  def usersWhoAreNotPresenter(users: UsersStatus): Vector[UserStatus] = users.toVector filter (u => u.presenter == false)
+
+  def unbecomePresenter(users: UsersStatus, userId: String) = {
+    for {
+      u <- findWithId(users, userId)
+      user = modify(u)(_.presenter).setTo(false)
+    } yield users.save(user)
+  }
+
+  def becomePresenter(users: UsersStatus, userId: String) = {
+    for {
+      u <- findWithId(users, userId)
+      user = modify(u)(_.presenter).setTo(true)
+    } yield users.save(user)
+  }
+
+  def isModerator(id: String, users: Users): Boolean = {
+    Users.findWithId(id, users) match {
+      case Some(user) => return user.role == Roles.MODERATOR_ROLE && !user.waitingForAcceptance
+      case None => return false
+    }
+  }
+}
+
+class UsersStatus {
+  private var usersStatus: collection.immutable.HashMap[String, UserStatus] = new collection.immutable.HashMap[String, UserStatus]
+
+  private def toVector: Vector[UserStatus] = usersStatus.values.toVector
+
+  private def save(user: UserStatus): UserStatus = {
+    usersStatus += user.id -> user
+    user
+  }
+
+  private def remove(id: String): Option[UserStatus] = {
+    val user = usersStatus.get(id)
+    user foreach (u => usersStatus -= id)
+    user
+  }
+}
+
+case class UserStatus(id: String, externalId: String, name: String, role: String,
+  guest: Boolean, authed: Boolean, waitingForAcceptance: Boolean, emoji: String,
+  presenter: Boolean, avatar: String)
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/models/VoiceUsers.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/models/VoiceUsers.scala
new file mode 100755
index 0000000000000000000000000000000000000000..f15fa1ddf30aa022eed1ea921433db55d476a8e4
--- /dev/null
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/models/VoiceUsers.scala
@@ -0,0 +1,28 @@
+package org.bigbluebutton.core.models
+
+object VoiceUsers {
+  def findUserWithVoiceUserId(users: VoiceUsers, voiceUserId: String): Option[VoiceUser2x] = {
+    users.toVector find (u => u.id == voiceUserId)
+  }
+
+}
+
+class VoiceUsers {
+  private var users: collection.immutable.HashMap[String, VoiceUser2x] =
+    new collection.immutable.HashMap[String, VoiceUser2x]
+
+  private def toVector: Vector[VoiceUser2x] = users.values.toVector
+
+  private def save(user: VoiceUser2x): VoiceUser2x = {
+    users += user.id -> user
+    user
+  }
+
+  private def remove(id: String): Option[VoiceUser2x] = {
+    val user = users.get(id)
+    user foreach (u => users -= id)
+    user
+  }
+}
+
+case class VoiceUser2x(id: String, voiceUserId: String)
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/models/VoiceUsersStatus.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/models/VoiceUsersStatus.scala
new file mode 100755
index 0000000000000000000000000000000000000000..7b4a9893ca8ab6409c76267060439ffc43a66ae1
--- /dev/null
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/models/VoiceUsersStatus.scala
@@ -0,0 +1,63 @@
+package org.bigbluebutton.core.models
+
+import com.softwaremill.quicklens._
+
+object VoiceUsersStatus {
+  def findWithId(users: VoiceUsersStatus, userId: String): Option[VoiceStatus] = users.toVector.find(u => u.id == userId)
+
+  def joinedVoiceListenOnly(users: VoiceUsersStatus, userId: String): Option[VoiceStatus] = {
+    for {
+      u <- findWithId(users, userId)
+      vu = u.modify(_.talking).setTo(false)
+        .modify(_.listenOnly).setTo(true)
+    } yield {
+      users.save(vu)
+      vu
+    }
+  }
+
+  def leftVoiceListenOnly(users: VoiceUsersStatus, userId: String): Option[VoiceStatus] = {
+    for {
+      u <- findWithId(users, userId)
+      vu = u.modify(_.talking).setTo(false)
+        .modify(_.listenOnly).setTo(false)
+    } yield {
+      users.save(vu)
+      vu
+    }
+  }
+
+  def setUserTalking(users: VoiceUsersStatus, user: VoiceStatus, talking: Boolean): VoiceStatus = {
+    val nv = user.modify(_.talking).setTo(talking)
+    users.save(nv)
+    nv
+  }
+
+  def setUserMuted(users: VoiceUsersStatus, user: VoiceStatus, muted: Boolean): VoiceStatus = {
+    val talking: Boolean = if (muted) false else user.talking
+    val nv = user.modify(_.muted).setTo(muted).modify(_.talking).setTo(talking)
+    users.save(nv)
+    nv
+  }
+}
+
+class VoiceUsersStatus {
+  private var users: collection.immutable.HashMap[String, VoiceStatus] = new collection.immutable.HashMap[String, VoiceStatus]
+
+  private def toVector: Vector[VoiceStatus] = users.values.toVector
+
+  private def save(user: VoiceStatus): VoiceStatus = {
+    users += user.id -> user
+    user
+  }
+
+  private def remove(id: String): Option[VoiceStatus] = {
+    val user = users.get(id)
+    user foreach (u => users -= id)
+    user
+  }
+}
+
+case class VoiceStatus(id: String, voiceUserId: String, callUsing: String, callerName: String,
+  callerNum: String, muted: Boolean,
+  talking: Boolean, listenOnly: Boolean)
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/models/Webcams.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/models/Webcams.scala
index 4ae5197ee88caa1a62c1c370e16fc104b0236686..e1b2d9d50d79fbbb29b2293631bf8f9d2014055c 100755
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/models/Webcams.scala
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/models/Webcams.scala
@@ -1,5 +1,7 @@
 package org.bigbluebutton.core.models
 
+import org.bigbluebutton.core.models.Users.findWithId
+
 object Webcams {
   def findWithStreamId(webcams: Webcams, streamId: String): Option[WebcamStream] = {
     webcams.toVector.find(w => w.stream.id == streamId)
@@ -9,6 +11,38 @@ object Webcams {
     webcams.toVector.filter(w => w.userId == userId)
   }
 
+  def userSharedWebcam(userId: String, webcams: Webcams, streamId: String): Option[UserVO] = {
+    /*
+    for {
+      u <- findWithId(userId, users)
+      streams = u.webcamStreams + streamId
+      uvo = u.modify(_.hasStream).setTo(true).modify(_.webcamStreams).setTo(streams)
+    } yield {
+      users.save(uvo)
+      uvo
+    }
+    */
+    None
+  }
+
+  def userUnsharedWebcam(userId: String, webcams: Webcams, streamId: String): Option[UserVO] = {
+    /*
+    def findWebcamStream(streams: Set[String], stream: String): Option[String] = {
+      streams find (w => w == stream)
+    }
+
+    for {
+      u <- findWebcamsForUser(webcams, userId)
+      streamName <- findWebcamStream(u.stream, streamId)
+      streams = u.webcamStreams - streamName
+      uvo = u.modify(_.hasStream).setTo(!streams.isEmpty).modify(_.webcamStreams).setTo(streams)
+    } yield {
+      users.save(uvo)
+      uvo
+    }
+    */
+    None
+  }
 }
 
 class Webcams {
diff --git a/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/pubsub/receivers/RedisMessageReceiver.java b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/pubsub/receivers/RedisMessageReceiver.java
new file mode 100755
index 0000000000000000000000000000000000000000..0e694e05f3279be7fe329c033568dc8376b7a1f5
--- /dev/null
+++ b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/pubsub/receivers/RedisMessageReceiver.java
@@ -0,0 +1,139 @@
+package org.bigbluebutton.freeswitch.pubsub.receivers;
+
+import org.bigbluebutton.common.messages.EjectAllUsersFromVoiceConfRequestMessage;
+import org.bigbluebutton.common.messages.EjectUserFromVoiceConfRequestMessage;
+import org.bigbluebutton.common.messages.GetUsersFromVoiceConfRequestMessage;
+import org.bigbluebutton.common.messages.MuteUserInVoiceConfRequestMessage;
+import org.bigbluebutton.common.messages.StartRecordingVoiceConfRequestMessage;
+import org.bigbluebutton.common.messages.StopRecordingVoiceConfRequestMessage;
+import org.bigbluebutton.common.messages.TransferUserToVoiceConfRequestMessage;
+import org.bigbluebutton.common.messages.DeskShareStartRTMPBroadcastEventMessage;
+import org.bigbluebutton.common.messages.DeskShareStopRTMPBroadcastEventMessage;
+import org.bigbluebutton.common.messages.DeskShareHangUpEventMessage;
+import org.bigbluebutton.freeswitch.voice.freeswitch.FreeswitchApplication;
+
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+
+public class RedisMessageReceiver {
+
+	public static final String TO_VOICE_CONF_CHANNEL = "bigbluebutton:to-voice-conf";
+	public static final String TO_VOICE_CONF_PATTERN = TO_VOICE_CONF_CHANNEL
+			+ ":*";
+	public static final String TO_VOICE_CONF_SYSTEM_CHAN = TO_VOICE_CONF_CHANNEL
+			+ ":system";
+
+	private final FreeswitchApplication fsApp;
+
+	public RedisMessageReceiver(FreeswitchApplication fsApp) {
+		this.fsApp = fsApp;
+	}
+
+	public void handleMessage(String pattern, String channel, String message) {
+		if (channel.equalsIgnoreCase(TO_VOICE_CONF_SYSTEM_CHAN)) {
+			JsonParser parser = new JsonParser();
+			JsonObject obj = (JsonObject) parser.parse(message);
+
+			if (obj.has("header") && obj.has("payload")) {
+				JsonObject header = (JsonObject) obj.get("header");
+
+				if (header.has("name")) {
+					String messageName = header.get("name").getAsString();
+					switch (messageName) {
+					case EjectAllUsersFromVoiceConfRequestMessage.EJECT_ALL_VOICE_USERS_REQUEST:
+						processEjectAllVoiceUsersRequestMessage(message);
+						break;
+					case EjectUserFromVoiceConfRequestMessage.EJECT_VOICE_USER_REQUEST:
+						processEjectVoiceUserRequestMessage(message);
+						break;
+					case GetUsersFromVoiceConfRequestMessage.GET_VOICE_USERS_REQUEST:
+						processGetVoiceUsersRequestMessage(message);
+						break;
+					case MuteUserInVoiceConfRequestMessage.MUTE_VOICE_USER_REQUEST:
+						processMuteVoiceUserRequestMessage(message);
+						break;
+					case TransferUserToVoiceConfRequestMessage.TRANSFER_USER_TO_VOICE_CONF_REQUEST:
+						processTransferUserToVoiceConfRequestMessage(message);
+						break;
+					case StartRecordingVoiceConfRequestMessage.START_RECORD_VOICE_CONF_REQUEST:
+						processStartRecordingVoiceConfRequestMessage(message);
+						break;
+					case StopRecordingVoiceConfRequestMessage.STOP_RECORD_VOICE_CONF_REQUEST:
+						processStopRecordingVoiceConfRequestMessage(message);
+						break;
+					  case DeskShareStartRTMPBroadcastEventMessage.DESKSHARE_START_RTMP_BROADCAST_MESSAGE:
+						  System.out.println("RedisMessageReceiver got DESKSHARE_START_RTMP_BROADCAST_MESSAGE");
+						  processDeskShareStartRTMPBroadcastEventMessage(message);
+					  break;
+					  case DeskShareStopRTMPBroadcastEventMessage.DESKSHARE_STOP_RTMP_BROADCAST_MESSAGE:
+						  System.out.println("RedisMessageReceiver got DESKSHARE_STOP_RTMP_BROADCAST_MESSAGE");
+						  processDeskShareStopRTMPBroadcastEventMessage(message);
+					  break;
+					  case DeskShareHangUpEventMessage.DESKSHARE_HANG_UP_MESSAGE:
+						  System.out.println("RedisMessageReceiver got DESKSHARE_HANG_UP_MESSAGE");
+						  processDeskShareHangUpEventMessage(message);
+					  break;
+					}
+				}
+			}
+		}
+	}
+
+	private void processDeskShareStartRTMPBroadcastEventMessage(String json) {
+		DeskShareStartRTMPBroadcastEventMessage msg = DeskShareStartRTMPBroadcastEventMessage.fromJson(json);
+		fsApp.deskShareBroadcastRTMP(msg.conferenceName, msg.streamUrl, msg.timestamp, true);
+	}
+
+	private void processDeskShareStopRTMPBroadcastEventMessage(String json) {
+		DeskShareStopRTMPBroadcastEventMessage msg = DeskShareStopRTMPBroadcastEventMessage.fromJson(json);
+		fsApp.deskShareBroadcastRTMP(msg.conferenceName, msg.streamUrl, msg.timestamp, false);
+	}
+
+	private void processDeskShareHangUpEventMessage(String json) {
+		DeskShareHangUpEventMessage msg = DeskShareHangUpEventMessage.fromJson(json);
+		fsApp.deskShareHangUp(msg.conferenceName, msg.fsConferenceName, msg.timestamp);
+	}
+
+	private void processEjectAllVoiceUsersRequestMessage(String json) {
+		EjectAllUsersFromVoiceConfRequestMessage msg = EjectAllUsersFromVoiceConfRequestMessage
+				.fromJson(json);
+		fsApp.ejectAll(msg.voiceConfId);
+	}
+
+	private void processEjectVoiceUserRequestMessage(String json) {
+		EjectUserFromVoiceConfRequestMessage msg = EjectUserFromVoiceConfRequestMessage
+				.fromJson(json);
+		fsApp.eject(msg.voiceConfId, msg.voiceUserId);
+	}
+
+	private void processGetVoiceUsersRequestMessage(String json) {
+		GetUsersFromVoiceConfRequestMessage msg = GetUsersFromVoiceConfRequestMessage
+				.fromJson(json);
+		fsApp.getAllUsers(msg.voiceConfId);
+	}
+
+	private void processMuteVoiceUserRequestMessage(String json) {
+		MuteUserInVoiceConfRequestMessage msg = MuteUserInVoiceConfRequestMessage
+				.fromJson(json);
+		fsApp.muteUser(msg.voiceConfId, msg.voiceUserId, msg.mute);
+	}
+
+	private void processTransferUserToVoiceConfRequestMessage(String json) {
+		TransferUserToVoiceConfRequestMessage msg = TransferUserToVoiceConfRequestMessage
+				.fromJson(json);
+		fsApp.transferUserToMeeting(msg.voiceConfId, msg.targetVoiceConfId,
+				msg.voiceUserId);
+	}
+
+	private void processStartRecordingVoiceConfRequestMessage(String json) {
+		StartRecordingVoiceConfRequestMessage msg = StartRecordingVoiceConfRequestMessage
+				.fromJson(json);
+		fsApp.startRecording(msg.voiceConfId, msg.meetingId);
+	}
+
+	private void processStopRecordingVoiceConfRequestMessage(String json) {
+		StopRecordingVoiceConfRequestMessage msg = StopRecordingVoiceConfRequestMessage
+				.fromJson(json);
+		fsApp.stopRecording(msg.voiceConfId, msg.meetingId, msg.recordStream);
+	}
+}
diff --git a/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/ConferenceServerListener.java b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/ConferenceServerListener.java
new file mode 100755
index 0000000000000000000000000000000000000000..ed86e5bf5a6b2a8bf4e7626d7ee1bde18b18cc8a
--- /dev/null
+++ b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/ConferenceServerListener.java
@@ -0,0 +1,26 @@
+/**
+* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
+* 
+* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
+*
+* This program is free software; you can redistribute it and/or modify it under the
+* terms of the GNU Lesser General Public License as published by the Free Software
+* Foundation; either version 3.0 of the License, or (at your option) any later
+* version.
+* 
+* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
+* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License along
+* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
+*
+*/
+package org.bigbluebutton.freeswitch.voice;
+
+public interface ConferenceServerListener {
+	public void joined(String room, Integer participant, String name, Boolean muted, Boolean talking);
+	public void left(String room, Integer participant);
+	public void muted(String room, Integer participant, Boolean muted);
+	public void talking(String room, Integer participant, Boolean talking);	
+}
diff --git a/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/FreeswitchConferenceEventListener.java b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/FreeswitchConferenceEventListener.java
new file mode 100755
index 0000000000000000000000000000000000000000..7fd3d8f6e29759226603a08641a07e33ceb7d1dc
--- /dev/null
+++ b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/FreeswitchConferenceEventListener.java
@@ -0,0 +1,138 @@
+/**
+* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
+* 
+* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
+*
+* This program is free software; you can redistribute it and/or modify it under the
+* terms of the GNU Lesser General Public License as published by the Free Software
+* Foundation; either version 3.0 of the License, or (at your option) any later
+* version.
+* 
+* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
+* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License along
+* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
+*
+*/
+package org.bigbluebutton.freeswitch.voice;
+
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+
+import org.bigbluebutton.freeswitch.voice.events.DeskShareStartedEvent;
+import org.bigbluebutton.freeswitch.voice.events.DeskShareEndedEvent;
+import org.bigbluebutton.freeswitch.voice.events.ConferenceEventListener;
+import org.bigbluebutton.freeswitch.voice.events.DeskShareRTMPBroadcastEvent;
+import org.bigbluebutton.freeswitch.voice.events.VoiceConferenceEvent;
+import org.bigbluebutton.freeswitch.voice.events.VoiceStartRecordingEvent;
+import org.bigbluebutton.freeswitch.voice.events.VoiceUserJoinedEvent;
+import org.bigbluebutton.freeswitch.voice.events.VoiceUserLeftEvent;
+import org.bigbluebutton.freeswitch.voice.events.VoiceUserMutedEvent;
+import org.bigbluebutton.freeswitch.voice.events.VoiceUserTalkingEvent;
+
+public class FreeswitchConferenceEventListener implements ConferenceEventListener {
+	private static final int SENDERTHREADS = 1;
+	private static final Executor msgSenderExec = Executors.newFixedThreadPool(SENDERTHREADS);
+	private static final Executor runExec = Executors.newFixedThreadPool(SENDERTHREADS);
+	private BlockingQueue<VoiceConferenceEvent> messages = new LinkedBlockingQueue<VoiceConferenceEvent>();
+
+	private volatile boolean sendMessages = false;
+	private final IVoiceConferenceService vcs;
+	
+	public FreeswitchConferenceEventListener(IVoiceConferenceService vcs) {
+		this.vcs = vcs;
+	}
+	
+    private void queueMessage(VoiceConferenceEvent event) {
+    	try {
+			messages.offer(event, 5, TimeUnit.SECONDS);
+		} catch (InterruptedException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}
+    }
+    			
+	private void sendMessageToBigBlueButton(final VoiceConferenceEvent event) {
+		Runnable task = new Runnable() {
+			public void run() {
+				if (event instanceof VoiceUserJoinedEvent) {
+				System.out.println("************** FreeswitchConferenceEventListener received voiceUserJoined ");
+				VoiceUserJoinedEvent evt = (VoiceUserJoinedEvent) event;
+				vcs.userJoinedVoiceConf(evt.getRoom(), evt.getVoiceUserId(), evt.getUserId(), evt.getCallerIdName(), 
+						evt.getCallerIdNum(), evt.getMuted(), evt.getSpeaking(), evt.getAvatarURL());
+				} else if (event instanceof VoiceUserLeftEvent) {
+					System.out.println("************** FreeswitchConferenceEventListener received VoiceUserLeftEvent ");
+					VoiceUserLeftEvent evt = (VoiceUserLeftEvent) event;
+					vcs.userLeftVoiceConf(evt.getRoom(), evt.getUserId());
+				} else if (event instanceof VoiceUserMutedEvent) {
+					System.out.println("************** FreeswitchConferenceEventListener VoiceUserMutedEvent ");
+					VoiceUserMutedEvent evt = (VoiceUserMutedEvent) event;
+					vcs.userMutedInVoiceConf(evt.getRoom(), evt.getUserId(), evt.isMuted());
+				} else if (event instanceof VoiceUserTalkingEvent) {
+					System.out.println("************** FreeswitchConferenceEventListener VoiceUserTalkingEvent ");
+					VoiceUserTalkingEvent evt = (VoiceUserTalkingEvent) event;
+					vcs.userTalkingInVoiceConf(evt.getRoom(), evt.getUserId(), evt.isTalking());
+				} else if (event instanceof VoiceStartRecordingEvent) {
+					VoiceStartRecordingEvent evt = (VoiceStartRecordingEvent) event;
+					System.out.println("************** FreeswitchConferenceEventListener VoiceStartRecordingEvent recording=[" + evt.startRecord() + "]");
+					vcs.voiceConfRecordingStarted(evt.getRoom(), evt.getRecordingFilename(), evt.startRecord(), evt.getTimestamp());
+				} else if (event instanceof DeskShareStartedEvent) {
+					DeskShareStartedEvent evt = (DeskShareStartedEvent) event;
+					System.out.println("************** FreeswitchConferenceEventListener DeskShareStartedEvent");
+					vcs.deskShareStarted(evt.getRoom(), evt.getCallerIdNum(), evt.getCallerIdName());
+				} else if (event instanceof DeskShareEndedEvent) {
+					DeskShareEndedEvent evt = (DeskShareEndedEvent) event;
+					System.out.println("************** FreeswitchConferenceEventListener DeskShareEndedEvent");
+					vcs.deskShareEnded(evt.getRoom(), evt.getCallerIdNum(), evt.getCallerIdName());
+				} else if (event instanceof DeskShareRTMPBroadcastEvent) {
+					if (((DeskShareRTMPBroadcastEvent) event).getBroadcast()) {
+						DeskShareRTMPBroadcastEvent evt = (DeskShareRTMPBroadcastEvent) event;
+						System.out.println("************** FreeswitchConferenceEventListener DeskShareRTMPBroadcastStartedEvent");
+						vcs.deskShareRTMPBroadcastStarted(evt.getRoom(), evt.getBroadcastingStreamUrl(),
+								evt.getVideoWidth(), evt.getVideoHeight(), evt.getTimestamp());
+					} else {
+						DeskShareRTMPBroadcastEvent evt = (DeskShareRTMPBroadcastEvent) event;
+						System.out.println("************** FreeswitchConferenceEventListener DeskShareRTMPBroadcastStoppedEvent");
+						vcs.deskShareRTMPBroadcastStopped(evt.getRoom(), evt.getBroadcastingStreamUrl(),
+								evt.getVideoWidth(), evt.getVideoHeight(), evt.getTimestamp());
+					}
+				}
+			}
+		};
+
+		runExec.execute(task);
+	}
+
+	public void start() {
+		sendMessages = true;
+		Runnable sender = new Runnable() {
+			public void run() {
+				while (sendMessages) {
+					VoiceConferenceEvent message;
+					try {
+						message = messages.take();
+						sendMessageToBigBlueButton(message);	
+					} catch (InterruptedException e) {
+						// TODO Auto-generated catch block
+						e.printStackTrace();
+					}
+				}
+			}
+		};
+		msgSenderExec.execute(sender);		
+	}
+	
+	public void stop() {
+		sendMessages = false;
+	}
+	
+	public void handleConferenceEvent(VoiceConferenceEvent event) {
+		queueMessage(event);
+	}
+
+}
diff --git a/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/IVoiceConferenceService.java b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/IVoiceConferenceService.java
new file mode 100755
index 0000000000000000000000000000000000000000..0f0e2ab68736b2bfc8c1aac378db20b4eae602e6
--- /dev/null
+++ b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/IVoiceConferenceService.java
@@ -0,0 +1,16 @@
+package org.bigbluebutton.freeswitch.voice;
+
+public interface IVoiceConferenceService {
+	void voiceConfRecordingStarted(String voiceConfId, String recordStream, Boolean recording, String timestamp);	
+	void userJoinedVoiceConf(String voiceConfId, String voiceUserId, String userId, String callerIdName, 
+			String callerIdNum, Boolean muted, Boolean speaking, String avatarURL);
+	void userLeftVoiceConf(String voiceConfId, String voiceUserId);
+	void userLockedInVoiceConf(String voiceConfId, String voiceUserId, Boolean locked);
+	void userMutedInVoiceConf(String voiceConfId, String voiceUserId, Boolean muted);
+	void userTalkingInVoiceConf(String voiceConfId, String voiceUserId, Boolean talking);
+	void deskShareStarted(String voiceConfId, String callerIdNum, String callerIdName);
+	void deskShareEnded(String voiceConfId, String callerIdNum, String callerIdName);
+	void deskShareRTMPBroadcastStarted(String room, String streamname, Integer videoWidth, Integer videoHeight, String timestamp);
+	void deskShareRTMPBroadcastStopped(String room, String streamname, Integer videoWidth, Integer videoHeight, String timestamp);
+
+}
diff --git a/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/commands/ConferenceCommand.java b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/commands/ConferenceCommand.java
new file mode 100755
index 0000000000000000000000000000000000000000..e4b93d716eaf74915ce68ac024927a69edb5ce7d
--- /dev/null
+++ b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/commands/ConferenceCommand.java
@@ -0,0 +1,40 @@
+/**
+* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
+* 
+* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
+*
+* This program is free software; you can redistribute it and/or modify it under the
+* terms of the GNU Lesser General Public License as published by the Free Software
+* Foundation; either version 3.0 of the License, or (at your option) any later
+* version.
+* 
+* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
+* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License along
+* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
+*
+*/
+package org.bigbluebutton.freeswitch.voice.commands;
+
+public abstract class ConferenceCommand {
+
+	private final String room;
+	private final Integer requesterId;
+	
+	public ConferenceCommand(String room, Integer requesterId) {
+		this.room = room;
+		this.requesterId = requesterId;
+	}
+
+	public String getRoom() {
+		return room;
+	}
+
+	public Integer getRequesterId() {
+		return requesterId;
+	}
+	
+	
+}
diff --git a/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/commands/ConferenceCommandResult.java b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/commands/ConferenceCommandResult.java
new file mode 100755
index 0000000000000000000000000000000000000000..ab7e12c09fcfaca4c8b3286f80b2012c2b48e57f
--- /dev/null
+++ b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/commands/ConferenceCommandResult.java
@@ -0,0 +1,56 @@
+/**
+* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
+* 
+* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
+*
+* This program is free software; you can redistribute it and/or modify it under the
+* terms of the GNU Lesser General Public License as published by the Free Software
+* Foundation; either version 3.0 of the License, or (at your option) any later
+* version.
+* 
+* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
+* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License along
+* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
+*
+*/
+package org.bigbluebutton.freeswitch.voice.commands;
+
+public class ConferenceCommandResult {
+
+	private final String room;
+	private final Integer requesterId;
+	private boolean success = false;
+	private String message = "";
+	
+	public ConferenceCommandResult(String room, Integer requesterId) {
+		this.room = room;
+		this.requesterId = requesterId;
+	}
+
+	public boolean isSuccess() {
+		return success;
+	}
+
+	public void setSuccess(boolean success) {
+		this.success = success;
+	}
+
+	public String getRoom() {
+		return room;
+	}
+
+	public String getMessage() {
+		return message;
+	}
+
+	public void setMessage(String message) {
+		this.message = message;
+	}
+
+	public Integer getRequesterId() {
+		return requesterId;
+	}
+}
diff --git a/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/commands/EjectUserCommand.java b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/commands/EjectUserCommand.java
new file mode 100755
index 0000000000000000000000000000000000000000..3c29e2b63cb32816122c5163d242e0d2aa7dd946
--- /dev/null
+++ b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/commands/EjectUserCommand.java
@@ -0,0 +1,34 @@
+/**
+* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
+* 
+* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
+*
+* This program is free software; you can redistribute it and/or modify it under the
+* terms of the GNU Lesser General Public License as published by the Free Software
+* Foundation; either version 3.0 of the License, or (at your option) any later
+* version.
+* 
+* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
+* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License along
+* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
+*
+*/
+package org.bigbluebutton.freeswitch.voice.commands;
+
+public class EjectUserCommand extends ConferenceCommand {
+
+	private final Integer participantId;
+	
+	public EjectUserCommand(String room, Integer requesterId, Integer participantId) {
+		super(room, requesterId);
+		this.participantId = participantId;
+	}
+
+	public Integer getParticipantId() {
+		return participantId;
+	}
+
+}
diff --git a/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/commands/GetUsersCommand.java b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/commands/GetUsersCommand.java
new file mode 100755
index 0000000000000000000000000000000000000000..13d21a4fb01e12c120779d3ad19f57e22900ce17
--- /dev/null
+++ b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/commands/GetUsersCommand.java
@@ -0,0 +1,27 @@
+/**
+* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
+* 
+* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
+*
+* This program is free software; you can redistribute it and/or modify it under the
+* terms of the GNU Lesser General Public License as published by the Free Software
+* Foundation; either version 3.0 of the License, or (at your option) any later
+* version.
+* 
+* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
+* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License along
+* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
+*
+*/
+package org.bigbluebutton.freeswitch.voice.commands;
+
+public class GetUsersCommand extends ConferenceCommand {
+
+	public GetUsersCommand(String room, Integer requesterId) {
+		super(room, requesterId);
+	}
+
+}
diff --git a/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/commands/MuteUserCommand.java b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/commands/MuteUserCommand.java
new file mode 100755
index 0000000000000000000000000000000000000000..62d2ece84c67079530da2fd55f74d9e0feb3435e
--- /dev/null
+++ b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/commands/MuteUserCommand.java
@@ -0,0 +1,40 @@
+/**
+* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
+* 
+* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
+*
+* This program is free software; you can redistribute it and/or modify it under the
+* terms of the GNU Lesser General Public License as published by the Free Software
+* Foundation; either version 3.0 of the License, or (at your option) any later
+* version.
+* 
+* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
+* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License along
+* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
+*
+*/
+package org.bigbluebutton.freeswitch.voice.commands;
+
+public class MuteUserCommand extends ConferenceCommand {
+
+	private final Integer participantId;
+	private final boolean mute;
+	
+	public MuteUserCommand(String room, Integer requesterId, Integer participantId, boolean mute) {
+		super(room, requesterId);
+		this.participantId = participantId;
+		this.mute = mute;
+	}
+
+	public Integer getParticipantId() {
+		return participantId;
+	}
+
+	public boolean isMute() {
+		return mute;
+	}
+
+}
diff --git a/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/commands/RecordCommand.java b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/commands/RecordCommand.java
new file mode 100755
index 0000000000000000000000000000000000000000..bb60598dae0955413fc0f5a3172ec96e3420d960
--- /dev/null
+++ b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/commands/RecordCommand.java
@@ -0,0 +1,27 @@
+/**
+* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
+* 
+* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
+*
+* This program is free software; you can redistribute it and/or modify it under the
+* terms of the GNU Lesser General Public License as published by the Free Software
+* Foundation; either version 3.0 of the License, or (at your option) any later
+* version.
+* 
+* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
+* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License along
+* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
+*
+*/
+package org.bigbluebutton.freeswitch.voice.commands;
+
+public class RecordCommand extends ConferenceCommand {
+
+	public RecordCommand(String room, Integer requesterId) {
+		super(room, requesterId);
+	}
+
+}
diff --git a/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/events/ConferenceEventListener.java b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/events/ConferenceEventListener.java
new file mode 100755
index 0000000000000000000000000000000000000000..f277d8c4ebaf2a170336d1c489338d745a933abf
--- /dev/null
+++ b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/events/ConferenceEventListener.java
@@ -0,0 +1,25 @@
+/**
+* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
+* 
+* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
+*
+* This program is free software; you can redistribute it and/or modify it under the
+* terms of the GNU Lesser General Public License as published by the Free Software
+* Foundation; either version 3.0 of the License, or (at your option) any later
+* version.
+* 
+* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
+* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License along
+* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
+*
+*/
+package org.bigbluebutton.freeswitch.voice.events;
+
+
+public interface ConferenceEventListener {
+	public void handleConferenceEvent(VoiceConferenceEvent event);
+	
+}
diff --git a/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/events/DeskShareEndedEvent.java b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/events/DeskShareEndedEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..ea5e543e8e8709ca962ebf0d1a3b8951295b145e
--- /dev/null
+++ b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/events/DeskShareEndedEvent.java
@@ -0,0 +1,39 @@
+/**
+* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
+* 
+* Copyright (c) 2015 BigBlueButton Inc. and by respective authors (see below).
+*
+* This program is free software; you can redistribute it and/or modify it under the
+* terms of the GNU Lesser General Public License as published by the Free Software
+* Foundation; either version 3.0 of the License, or (at your option) any later
+* version.
+* 
+* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
+* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License along
+* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
+*
+*/
+package org.bigbluebutton.freeswitch.voice.events;
+
+public class DeskShareEndedEvent extends VoiceConferenceEvent {
+
+	private final String callerIdNum;
+	private final String callerIdName;
+	
+	public DeskShareEndedEvent(String room, String callerIdNum, String callerIdName) {
+		super(room);
+		this.callerIdName = callerIdName;
+		this.callerIdNum = callerIdNum;
+	}
+
+	public String getCallerIdNum() {
+		return callerIdNum;
+	}
+
+	public String getCallerIdName() {
+		return callerIdName;
+	}
+}
diff --git a/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/events/DeskShareRTMPBroadcastEvent.java b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/events/DeskShareRTMPBroadcastEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..b939bc1dd371ffbbd02250bbb38ea08fb7737978
--- /dev/null
+++ b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/events/DeskShareRTMPBroadcastEvent.java
@@ -0,0 +1,68 @@
+/**
+* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
+* 
+* Copyright (c) 2015 BigBlueButton Inc. and by respective authors (see below).
+*
+* This program is free software; you can redistribute it and/or modify it under the
+* terms of the GNU Lesser General Public License as published by the Free Software
+* Foundation; either version 3.0 of the License, or (at your option) any later
+* version.
+* 
+* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
+* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License along
+* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
+*
+*/
+package org.bigbluebutton.freeswitch.voice.events;
+
+public class DeskShareRTMPBroadcastEvent extends VoiceConferenceEvent {
+
+	private String timestamp;
+	private boolean broadcast;
+	private String streamUrl;
+	private Integer vw;
+	private Integer vh;
+
+	private final String DESKSHARE_SUFFIX = "-DESKSHARE";
+
+
+	public DeskShareRTMPBroadcastEvent(String room, boolean broadcast) {
+		super(room);
+		this.broadcast = broadcast;
+	}
+
+	public void setTimestamp(String timestamp) {
+		this.timestamp = timestamp;
+	}
+
+	public void setBroadcastingStreamUrl(String streamUrl) {
+		this.streamUrl = streamUrl;
+	}
+
+	public void setVideoWidth(Integer vw) {this.vw = vw;}
+
+	public void setVideoHeight(Integer vh) {this.vh = vh;}
+
+	public Integer getVideoHeight() {return vh;}
+
+	public Integer getVideoWidth() {return vw;}
+
+	public String getTimestamp() {
+		return timestamp;
+	}
+
+	public String getBroadcastingStreamUrl()
+	{
+		if (streamUrl.endsWith(DESKSHARE_SUFFIX)) {
+			streamUrl = streamUrl.replace(DESKSHARE_SUFFIX, "");
+		}
+		return streamUrl;
+	}
+
+	public boolean getBroadcast() {
+		return broadcast;
+	}
+}
diff --git a/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/events/DeskShareStartedEvent.java b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/events/DeskShareStartedEvent.java
new file mode 100644
index 0000000000000000000000000000000000000000..9cb325ca8df14f2180482c0fc3e87a6e47af57a8
--- /dev/null
+++ b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/events/DeskShareStartedEvent.java
@@ -0,0 +1,39 @@
+/**
+* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
+* 
+* Copyright (c) 2015 BigBlueButton Inc. and by respective authors (see below).
+*
+* This program is free software; you can redistribute it and/or modify it under the
+* terms of the GNU Lesser General Public License as published by the Free Software
+* Foundation; either version 3.0 of the License, or (at your option) any later
+* version.
+* 
+* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
+* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License along
+* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
+*
+*/
+package org.bigbluebutton.freeswitch.voice.events;
+
+public class DeskShareStartedEvent extends VoiceConferenceEvent {
+
+	private final String callerIdNum;
+	private final String callerIdName;
+	
+	public DeskShareStartedEvent(String room, String callerIdNum, String callerIdName) {
+		super(room);
+		this.callerIdName = callerIdName;
+		this.callerIdNum = callerIdNum;
+	}
+
+	public String getCallerIdNum() {
+		return callerIdNum;
+	}
+
+	public String getCallerIdName() {
+		return callerIdName;
+	}
+}
diff --git a/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/events/UnknownConferenceEvent.java b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/events/UnknownConferenceEvent.java
new file mode 100755
index 0000000000000000000000000000000000000000..af959fad11130e01c6607a73e063fa47bbae84d7
--- /dev/null
+++ b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/events/UnknownConferenceEvent.java
@@ -0,0 +1,27 @@
+/**
+* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
+* 
+* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
+*
+* This program is free software; you can redistribute it and/or modify it under the
+* terms of the GNU Lesser General Public License as published by the Free Software
+* Foundation; either version 3.0 of the License, or (at your option) any later
+* version.
+* 
+* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
+* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License along
+* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
+*
+*/
+package org.bigbluebutton.freeswitch.voice.events;
+
+public class UnknownConferenceEvent extends VoiceConferenceEvent {
+
+	public UnknownConferenceEvent(String participantId, String room) {
+		super(room);
+	}
+
+}
diff --git a/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/events/VoiceConferenceEvent.java b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/events/VoiceConferenceEvent.java
new file mode 100755
index 0000000000000000000000000000000000000000..cf8bd96cfb9684b024eb5f8dd43459ef7fbeebb6
--- /dev/null
+++ b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/events/VoiceConferenceEvent.java
@@ -0,0 +1,32 @@
+/**
+* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
+* 
+* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
+*
+* This program is free software; you can redistribute it and/or modify it under the
+* terms of the GNU Lesser General Public License as published by the Free Software
+* Foundation; either version 3.0 of the License, or (at your option) any later
+* version.
+* 
+* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
+* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License along
+* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
+*
+*/
+package org.bigbluebutton.freeswitch.voice.events;
+
+public abstract class VoiceConferenceEvent {
+	private final String room;
+	
+	public VoiceConferenceEvent(String room) {
+		this.room = room;
+	}
+
+	public String getRoom() {
+		return room;
+	}
+	
+}
diff --git a/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/events/VoiceStartRecordingEvent.java b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/events/VoiceStartRecordingEvent.java
new file mode 100755
index 0000000000000000000000000000000000000000..91bbc1dbab149f3fbeb12504d85c7e5db4cc7fbe
--- /dev/null
+++ b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/events/VoiceStartRecordingEvent.java
@@ -0,0 +1,51 @@
+/**
+* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
+* 
+* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
+*
+* This program is free software; you can redistribute it and/or modify it under the
+* terms of the GNU Lesser General Public License as published by the Free Software
+* Foundation; either version 3.0 of the License, or (at your option) any later
+* version.
+* 
+* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
+* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License along
+* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
+*
+*/
+package org.bigbluebutton.freeswitch.voice.events;
+
+public class VoiceStartRecordingEvent extends VoiceConferenceEvent {
+
+	private String timestamp;
+	private String filename;
+	private boolean record;
+	
+	public VoiceStartRecordingEvent(String room, boolean record) {
+		super(room);
+		this.record =  record;
+	}
+	
+	public void setTimestamp(String timestamp) {
+		this.timestamp = timestamp;
+	}
+
+	public void setRecordingFilename(String filename) {
+		this.filename = filename;
+	}
+	
+	public String getTimestamp() {
+		return timestamp;
+	}
+	
+	public String getRecordingFilename() {
+		return filename;
+	}
+	
+	public boolean startRecord() {
+		return record;
+	}
+}
diff --git a/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/events/VoiceUserJoinedEvent.java b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/events/VoiceUserJoinedEvent.java
new file mode 100755
index 0000000000000000000000000000000000000000..7ac8f398e7d277346d6d7c0f1e6b18b814c5723c
--- /dev/null
+++ b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/events/VoiceUserJoinedEvent.java
@@ -0,0 +1,76 @@
+/**
+* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
+* 
+* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
+*
+* This program is free software; you can redistribute it and/or modify it under the
+* terms of the GNU Lesser General Public License as published by the Free Software
+* Foundation; either version 3.0 of the License, or (at your option) any later
+* version.
+* 
+* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
+* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License along
+* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
+*
+*/
+package org.bigbluebutton.freeswitch.voice.events;
+
+public class VoiceUserJoinedEvent extends VoiceConferenceEvent {
+
+	private final String voiceUserId;
+	private final String callerIdNum;
+	private final String callerIdName;
+	private final Boolean muted;
+	private final Boolean speaking;
+	private final Boolean locked = false;
+	private final String userId;
+	private final String avatarURL;
+	
+	public VoiceUserJoinedEvent(String userId, String voiceUserId, String room, 
+								String callerIdNum, String callerIdName,
+								Boolean muted, Boolean speaking, String avatarURL) {
+		super(room);
+		this.userId = userId;
+		this.voiceUserId = voiceUserId;
+		this.callerIdName = callerIdName;
+		this.callerIdNum = callerIdNum;
+		this.muted = muted;
+		this.speaking = speaking;
+		this.avatarURL = avatarURL;
+	}
+
+	public String getUserId() {
+		return userId;
+	}
+	
+	public String getVoiceUserId() {
+		return voiceUserId;
+	}
+	
+	public String getCallerIdNum() {
+		return callerIdNum;
+	}
+
+	public String getCallerIdName() {
+		return callerIdName;
+	}
+
+	public Boolean getMuted() {
+		return muted;
+	}
+
+	public Boolean getSpeaking() {
+		return speaking;
+	}
+	
+	public Boolean isLocked() {
+		return locked;
+	}
+
+	public String getAvatarURL() {
+		return avatarURL;
+	}
+}
diff --git a/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/events/VoiceUserLeftEvent.java b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/events/VoiceUserLeftEvent.java
new file mode 100755
index 0000000000000000000000000000000000000000..7591db0153a99726e853eef0060a6aff3985be7a
--- /dev/null
+++ b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/events/VoiceUserLeftEvent.java
@@ -0,0 +1,33 @@
+/**
+* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
+* 
+* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
+*
+* This program is free software; you can redistribute it and/or modify it under the
+* terms of the GNU Lesser General Public License as published by the Free Software
+* Foundation; either version 3.0 of the License, or (at your option) any later
+* version.
+* 
+* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
+* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License along
+* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
+*
+*/
+package org.bigbluebutton.freeswitch.voice.events;
+
+public class VoiceUserLeftEvent extends VoiceConferenceEvent {
+
+	private final String userId;
+	
+	public VoiceUserLeftEvent(String userId, String room) {
+		super(room);
+		this.userId = userId;
+	}
+	
+	public String getUserId() {
+		return userId;
+	}
+}
diff --git a/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/events/VoiceUserLockedEvent.java b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/events/VoiceUserLockedEvent.java
new file mode 100755
index 0000000000000000000000000000000000000000..0cfc456dfedc2b5a68270b0511cf8f47b980fa2c
--- /dev/null
+++ b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/events/VoiceUserLockedEvent.java
@@ -0,0 +1,40 @@
+/**
+* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
+* 
+* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
+*
+* This program is free software; you can redistribute it and/or modify it under the
+* terms of the GNU Lesser General Public License as published by the Free Software
+* Foundation; either version 3.0 of the License, or (at your option) any later
+* version.
+* 
+* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
+* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License along
+* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
+*
+*/
+package org.bigbluebutton.freeswitch.voice.events;
+
+public class VoiceUserLockedEvent extends VoiceConferenceEvent {
+
+	private final boolean locked;
+	private final String userId;
+	
+	public VoiceUserLockedEvent(String userId, String room, boolean locked) {
+		super(room);
+		this.locked = locked;
+		this.userId = userId;
+	}
+
+	public String getUserId() {
+		return userId;
+	}
+	
+	public boolean isLocked() {
+		return locked;
+	}
+
+}
diff --git a/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/events/VoiceUserMutedEvent.java b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/events/VoiceUserMutedEvent.java
new file mode 100755
index 0000000000000000000000000000000000000000..003493b0f9c6020b82618d2a7228a915be71a5d6
--- /dev/null
+++ b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/events/VoiceUserMutedEvent.java
@@ -0,0 +1,40 @@
+/**
+* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
+* 
+* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
+*
+* This program is free software; you can redistribute it and/or modify it under the
+* terms of the GNU Lesser General Public License as published by the Free Software
+* Foundation; either version 3.0 of the License, or (at your option) any later
+* version.
+* 
+* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
+* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License along
+* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
+*
+*/
+package org.bigbluebutton.freeswitch.voice.events;
+
+public class VoiceUserMutedEvent extends VoiceConferenceEvent {
+
+	private final boolean muted;
+	private final String userId;
+	
+	public VoiceUserMutedEvent(String userId, String room, boolean muted) {
+		super(room);
+		this.muted = muted;
+		this.userId = userId;
+	}
+
+	public String getUserId() {
+		return userId;
+	}
+	
+	public boolean isMuted() {
+		return muted;
+	}
+
+}
diff --git a/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/events/VoiceUserTalkingEvent.java b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/events/VoiceUserTalkingEvent.java
new file mode 100755
index 0000000000000000000000000000000000000000..5bd778062e7130472ee483e52046cf3342ea0657
--- /dev/null
+++ b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/events/VoiceUserTalkingEvent.java
@@ -0,0 +1,40 @@
+/**
+* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
+* 
+* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
+*
+* This program is free software; you can redistribute it and/or modify it under the
+* terms of the GNU Lesser General Public License as published by the Free Software
+* Foundation; either version 3.0 of the License, or (at your option) any later
+* version.
+* 
+* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
+* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License along
+* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
+*
+*/
+package org.bigbluebutton.freeswitch.voice.events;
+
+public class VoiceUserTalkingEvent extends VoiceConferenceEvent {
+
+	private final boolean talking;
+	private final String userId;
+	
+	public VoiceUserTalkingEvent(String userId, String room, boolean talking) {
+		super(room);
+		this.talking = talking;
+		this.userId = userId;
+	}
+
+	public String getUserId() {
+		return userId;
+	}
+	
+	public boolean isTalking() {
+		return talking;
+	}
+
+}
diff --git a/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/ConnectionManager.java b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/ConnectionManager.java
new file mode 100755
index 0000000000000000000000000000000000000000..9e0ce5d5005cbe5a8fd45a39ba065c371cb4cd54
--- /dev/null
+++ b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/ConnectionManager.java
@@ -0,0 +1,178 @@
+/**
+ * BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
+ * 
+ * Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
+ *
+ * This program is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation; either version 3.0 of the License, or (at your option) any later
+ * version.
+ * 
+ * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along
+ * with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+package org.bigbluebutton.freeswitch.voice.freeswitch;
+
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+import org.bigbluebutton.freeswitch.voice.events.ConferenceEventListener;
+import org.bigbluebutton.freeswitch.voice.freeswitch.actions.BroadcastConferenceCommand;
+import org.bigbluebutton.freeswitch.voice.freeswitch.actions.EjectAllUsersCommand;
+import org.bigbluebutton.freeswitch.voice.freeswitch.actions.EjectUserCommand;
+import org.bigbluebutton.freeswitch.voice.freeswitch.actions.GetAllUsersCommand;
+import org.bigbluebutton.freeswitch.voice.freeswitch.actions.MuteUserCommand;
+import org.bigbluebutton.freeswitch.voice.freeswitch.actions.RecordConferenceCommand;
+import org.bigbluebutton.freeswitch.voice.freeswitch.actions.TransferUserToMeetingCommand;
+import org.bigbluebutton.freeswitch.voice.freeswitch.actions.*;
+import org.freeswitch.esl.client.inbound.Client;
+import org.freeswitch.esl.client.inbound.InboundConnectionFailure;
+import org.freeswitch.esl.client.manager.ManagerConnection;
+import org.freeswitch.esl.client.transport.message.EslMessage;
+
+public class ConnectionManager {
+
+	private static final String EVENT_NAME = "Event-Name";
+
+	private static final ScheduledExecutorService connExec = Executors
+			.newSingleThreadScheduledExecutor();
+
+	private final ManagerConnection manager;
+	private ScheduledFuture<ConnectThread> connectTask;
+
+	private volatile boolean subscribed = false;
+
+	private final ConferenceEventListener conferenceEventListener;
+	private final ESLEventListener eslEventListener;
+
+	public ConnectionManager(ManagerConnection connManager,
+			ESLEventListener eventListener, ConferenceEventListener confListener) {
+		this.manager = connManager;
+		this.eslEventListener = eventListener;
+		this.conferenceEventListener = confListener;
+	}
+
+	private void connect() {
+		try {
+			Client c = manager.getESLClient();
+			if (!c.canSend()) {
+				System.out.println("Attempting to connect to FreeSWITCH ESL");
+				subscribed = false;
+				manager.connect();
+			} else {
+				if (!subscribed) {
+					System.out.println("Subscribing for ESL events.");
+					c.cancelEventSubscriptions();
+					c.addEventListener(eslEventListener);
+					c.setEventSubscriptions("plain", "all");
+					c.addEventFilter(EVENT_NAME, "heartbeat");
+					c.addEventFilter(EVENT_NAME, "custom");
+					c.addEventFilter(EVENT_NAME, "background_job");
+					subscribed = true;
+				}
+			}
+		} catch (InboundConnectionFailure e) {
+			System.out.println("Failed to connect to ESL");
+		}
+	}
+
+	public void start() {
+		System.out.println("Starting FreeSWITCH ESL connection manager.");
+		ConnectThread connector = new ConnectThread();
+		connectTask = (ScheduledFuture<ConnectThread>) connExec
+				.scheduleAtFixedRate(connector, 5, 5, TimeUnit.SECONDS);
+	}
+
+	public void stop() {
+		if (connectTask != null) {
+			connectTask.cancel(true);
+		}
+	}
+
+	private class ConnectThread implements Runnable {
+		public void run() {
+			connect();
+		}
+	}
+
+	public void broadcast(BroadcastConferenceCommand rcc) {
+		Client c = manager.getESLClient();
+		if (c.canSend()) {
+			EslMessage response = c.sendSyncApiCommand(rcc.getCommand(),
+					rcc.getCommandArgs());
+			rcc.handleResponse(response, conferenceEventListener);
+		}
+	}
+
+	public void getUsers(GetAllUsersCommand prc) {
+		Client c = manager.getESLClient();
+		if (c.canSend()) {
+			EslMessage response = c.sendSyncApiCommand(prc.getCommand(),
+					prc.getCommandArgs());
+			prc.handleResponse(response, conferenceEventListener);
+		}
+	}
+
+	public void mute(MuteUserCommand mpc) {
+		System.out.println("Got mute request from FSApplication.");
+		Client c = manager.getESLClient();
+		if (c.canSend()) {
+			System.out.println("Issuing command to FS ESL.");
+			c.sendAsyncApiCommand(mpc.getCommand(), mpc.getCommandArgs());
+		}
+	}
+
+	public void tranfer(TransferUserToMeetingCommand tutmc) {
+		Client c = manager.getESLClient();
+		if (c.canSend()) {
+			c.sendAsyncApiCommand(tutmc.getCommand(), tutmc.getCommandArgs());
+		}
+	}
+
+	public void eject(EjectUserCommand mpc) {
+		Client c = manager.getESLClient();
+		if (c.canSend()) {
+			c.sendAsyncApiCommand(mpc.getCommand(), mpc.getCommandArgs());
+		}
+	}
+
+	public void ejectAll(EjectAllUsersCommand mpc) {
+		Client c = manager.getESLClient();
+		if (c.canSend()) {
+			c.sendAsyncApiCommand(mpc.getCommand(), mpc.getCommandArgs());
+		}
+	}
+
+	public void record(RecordConferenceCommand rcc) {
+		Client c = manager.getESLClient();
+		if (c.canSend()) {
+			EslMessage response = c.sendSyncApiCommand(rcc.getCommand(),
+					rcc.getCommandArgs());
+			rcc.handleResponse(response, conferenceEventListener);
+		}
+	}
+
+	public void broadcastRTMP(DeskShareBroadcastRTMPCommand rtmp) {
+		Client c = manager.getESLClient();
+		if (c.canSend()) {
+			System.out.println("ConnectionManager: send to FS: broadcastRTMP "  + rtmp.getCommandArgs());
+			EslMessage response = c.sendSyncApiCommand(rtmp.getCommand(), rtmp.getCommandArgs());
+			rtmp.handleResponse(response, conferenceEventListener);
+		}
+	}
+
+	public void hangUp(DeskShareHangUpCommand huCmd) {
+		Client c = manager.getESLClient();
+		if (c.canSend()) {
+			System.out.println("ConnectionManager: send to FS: hangUp " + huCmd.getCommandArgs());
+			EslMessage response = c.sendSyncApiCommand(huCmd.getCommand(), huCmd.getCommandArgs());
+			huCmd.handleResponse(response, conferenceEventListener);
+		}
+	}
+}
diff --git a/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/ESLEventListener.java b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/ESLEventListener.java
new file mode 100755
index 0000000000000000000000000000000000000000..9e90a4a0f7e88a42cb0a3ecabe4d1e185450f2e5
--- /dev/null
+++ b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/ESLEventListener.java
@@ -0,0 +1,300 @@
+package org.bigbluebutton.freeswitch.voice.freeswitch;
+
+
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.bigbluebutton.freeswitch.voice.events.ConferenceEventListener;
+import org.bigbluebutton.freeswitch.voice.events.DeskShareEndedEvent;
+import org.bigbluebutton.freeswitch.voice.events.DeskShareStartedEvent;
+import org.bigbluebutton.freeswitch.voice.events.DeskShareRTMPBroadcastEvent;
+import org.bigbluebutton.freeswitch.voice.events.VoiceConferenceEvent;
+import org.bigbluebutton.freeswitch.voice.events.VoiceStartRecordingEvent;
+import org.bigbluebutton.freeswitch.voice.events.VoiceUserJoinedEvent;
+import org.bigbluebutton.freeswitch.voice.events.VoiceUserLeftEvent;
+import org.bigbluebutton.freeswitch.voice.events.VoiceUserMutedEvent;
+import org.bigbluebutton.freeswitch.voice.events.VoiceUserTalkingEvent;
+import org.freeswitch.esl.client.IEslEventListener;
+import org.freeswitch.esl.client.transport.event.EslEvent;
+import org.jboss.netty.channel.ExceptionEvent;
+
+public class ESLEventListener implements IEslEventListener {
+
+    private static final String START_TALKING_EVENT = "start-talking";
+    private static final String STOP_TALKING_EVENT = "stop-talking";
+    private static final String START_RECORDING_EVENT = "start-recording";
+    private static final String STOP_RECORDING_EVENT = "stop-recording";
+
+    private static final String DESKSHARE_CONFERENCE_NAME_SUFFIX = "-DESKSHARE";
+
+    private final ConferenceEventListener conferenceEventListener;
+    
+    public ESLEventListener(ConferenceEventListener conferenceEventListener) {
+        this.conferenceEventListener = conferenceEventListener;
+    }
+    
+    @Override
+    public void conferenceEventPlayFile(String uniqueId, String confName, int confSize, EslEvent event) {
+        //Ignored, Noop
+    }
+
+    @Override
+    public void backgroundJobResultReceived(EslEvent event) {
+        System.out.println( "Background job result received [" + event + "]");
+    }
+
+    @Override
+    public void exceptionCaught(ExceptionEvent e) {
+//        setChanged();
+//        notifyObservers(e);
+    }
+
+    private static final Pattern GLOBAL_AUDION_PATTERN = Pattern.compile("(GLOBAL_AUDIO)_(.*)$");
+    private static final Pattern CALLERNAME_PATTERN = Pattern.compile("(.*)-bbbID-(.*)$");
+    
+    @Override
+    public void conferenceEventJoin(String uniqueId, String confName, int confSize, EslEvent event) {
+
+        Integer memberId = this.getMemberIdFromEvent(event);
+        Map<String, String> headers = event.getEventHeaders();
+        String callerId = this.getCallerIdFromEvent(event);
+        String callerIdName = this.getCallerIdNameFromEvent(event);
+        boolean muted = headers.get("Speak").equals("true") ? false : true; //Was inverted which was causing a State issue
+        boolean speaking = headers.get("Talking").equals("true") ? true : false;
+
+        String voiceUserId = callerIdName;
+
+        Matcher gapMatcher = GLOBAL_AUDION_PATTERN.matcher(callerIdName);
+        if (gapMatcher.matches()) {
+            System.out.println("Ignoring GLOBAL AUDIO USER [" + callerIdName + "]");
+            return;
+        }
+        
+        // (WebRTC) Deskstop sharing conferences' name is of the form ddddd-DESKSHARE
+        // Voice conferences' name is of the form ddddd
+        if (confName.endsWith(DESKSHARE_CONFERENCE_NAME_SUFFIX)) {
+            System.out.println("User joined deskshare conference, user=[" + callerIdName + "], " +
+                    "conf=[" + confName + "] callerId=[" + callerId + "]");
+            DeskShareStartedEvent dsStart = new DeskShareStartedEvent(confName, callerId, callerIdName);
+            conferenceEventListener.handleConferenceEvent(dsStart);
+        } else {
+            Matcher matcher = CALLERNAME_PATTERN.matcher(callerIdName);
+            if (matcher.matches()) {
+                voiceUserId = matcher.group(1).trim();
+                callerIdName = matcher.group(2).trim();
+            }
+
+            System.out.println("User joined voice conference, user=[" + callerIdName + "], conf=[" +
+                    confName + "] callerId=[" + callerId + "]");
+
+            VoiceUserJoinedEvent pj = new VoiceUserJoinedEvent(voiceUserId, memberId.toString(), confName, callerId, callerIdName, muted, speaking, "none");
+            conferenceEventListener.handleConferenceEvent(pj);
+        }
+    }
+
+    @Override
+    public void conferenceEventLeave(String uniqueId, String confName, int confSize, EslEvent event) {      
+        Integer memberId = this.getMemberIdFromEvent(event);
+        String callerId = this.getCallerIdFromEvent(event);
+        String callerIdName = this.getCallerIdNameFromEvent(event);
+
+        // (WebRTC) Deskstop sharing conferences' name is of the form ddddd-DESKSHARE
+        // Voice conferences' name is of the form ddddd
+        if (confName.endsWith(DESKSHARE_CONFERENCE_NAME_SUFFIX)) {
+            System.out.println("User left deskshare conference, user=[" + memberId.toString() +
+                    "], " + "conf=[" + confName + "]");
+            DeskShareEndedEvent dsEnd = new DeskShareEndedEvent(confName, callerId, callerIdName);
+            conferenceEventListener.handleConferenceEvent(dsEnd);
+        } else {
+            System.out.println("User left voice conference, user=[" + memberId.toString() + "], " +
+                    "conf=[" + confName + "]");
+            VoiceUserLeftEvent pl = new VoiceUserLeftEvent(memberId.toString(), confName);
+            conferenceEventListener.handleConferenceEvent(pl);
+        }
+    }
+
+    @Override
+    public void conferenceEventMute(String uniqueId, String confName, int confSize, EslEvent event) {
+        Integer memberId = this.getMemberIdFromEvent(event);
+        System.out.println("******************** Received Conference Muted Event from FreeSWITCH user[" + memberId.toString() + "]");
+        System.out.println("User muted voice conference, user=[" + memberId.toString() + "], conf=[" + confName + "]");
+        VoiceUserMutedEvent pm = new VoiceUserMutedEvent(memberId.toString(), confName, true);
+        conferenceEventListener.handleConferenceEvent(pm);
+    }
+
+    @Override
+    public void conferenceEventUnMute(String uniqueId, String confName, int confSize, EslEvent event) {
+        Integer memberId = this.getMemberIdFromEvent(event);
+        System.out.println("******************** Received ConferenceUnmuted Event from FreeSWITCH user[" + memberId.toString() + "]");
+        System.out.println("User unmuted voice conference, user=[" + memberId.toString() + "], conf=[" + confName + "]");
+        VoiceUserMutedEvent pm = new VoiceUserMutedEvent(memberId.toString(), confName, false);
+        conferenceEventListener.handleConferenceEvent(pm);
+    }
+
+    @Override
+    public void conferenceEventAction(String uniqueId, String confName, int confSize, String action, EslEvent event) {
+        Integer memberId = this.getMemberIdFromEvent(event);
+        VoiceUserTalkingEvent pt;
+        
+        System.out.println("******************** Receive conference Action [" + action + "]");
+        
+        if (action == null) {
+            return;
+        }
+
+        if (action.equals(START_TALKING_EVENT)) {
+            pt = new VoiceUserTalkingEvent(memberId.toString(), confName, true);
+            conferenceEventListener.handleConferenceEvent(pt);          
+        } else if (action.equals(STOP_TALKING_EVENT)) {
+            pt = new VoiceUserTalkingEvent(memberId.toString(), confName, false);
+            conferenceEventListener.handleConferenceEvent(pt);          
+        } else {
+            System.out.println("Unknown conference Action [" + action + "]");
+        }
+    }
+
+    @Override
+    public void conferenceEventTransfer(String uniqueId, String confName, int confSize, EslEvent event) {
+        //Ignored, Noop
+    }
+
+    @Override
+    public void conferenceEventThreadRun(String uniqueId, String confName, int confSize, EslEvent event) {
+        
+    }
+    
+    //@Override
+    public void conferenceEventRecord(String uniqueId, String confName, int confSize, EslEvent event) {
+        String action = event.getEventHeaders().get("Action");
+
+        if(action == null) {
+            return;
+        }
+
+        if (action.equals(START_RECORDING_EVENT)) {
+            if (confName.endsWith(DESKSHARE_CONFERENCE_NAME_SUFFIX)){
+                if (isRTMPStream(event)) {
+                    DeskShareRTMPBroadcastEvent rtmp = new DeskShareRTMPBroadcastEvent(confName, true);
+                    rtmp.setBroadcastingStreamUrl(getStreamUrl(event));
+                    rtmp.setVideoHeight(Integer.parseInt(getBroadcastParameter(event, "vh")));
+                    rtmp.setVideoWidth(Integer.parseInt(getBroadcastParameter(event, "vw")));
+                    rtmp.setTimestamp(genTimestamp().toString());
+
+                    System.out.println("DeskShare conference broadcast started. url=["
+                            + getStreamUrl(event) + "], conf=[" + confName + "]");
+                    conferenceEventListener.handleConferenceEvent(rtmp);
+                }
+            } else {
+                VoiceStartRecordingEvent sre = new VoiceStartRecordingEvent(confName, true);
+                sre.setRecordingFilename(getRecordFilenameFromEvent(event));
+                sre.setTimestamp(genTimestamp().toString());
+
+                System.out.println("Voice conference recording started. file=["
+                 + getRecordFilenameFromEvent(event) + "], conf=[" + confName + "]");
+                conferenceEventListener.handleConferenceEvent(sre);
+            }
+        } else if (action.equals(STOP_RECORDING_EVENT)) {
+            if (confName.endsWith(DESKSHARE_CONFERENCE_NAME_SUFFIX)){
+                if (isRTMPStream(event)) {
+                    DeskShareRTMPBroadcastEvent rtmp = new DeskShareRTMPBroadcastEvent(confName, false);
+                    rtmp.setBroadcastingStreamUrl(getStreamUrl(event));
+                    rtmp.setVideoHeight(Integer.parseInt(getBroadcastParameter(event, "vh")));
+                    rtmp.setVideoWidth(Integer.parseInt(getBroadcastParameter(event, "vw")));
+                    rtmp.setTimestamp(genTimestamp().toString());
+
+                    System.out.println("DeskShare conference broadcast stopped. url=["
+                            + getStreamUrl(event) + "], conf=[" + confName + "]");
+                    conferenceEventListener.handleConferenceEvent(rtmp);
+                }
+            } else {
+                VoiceStartRecordingEvent sre = new VoiceStartRecordingEvent(confName, false);
+                sre.setRecordingFilename(getRecordFilenameFromEvent(event));
+                sre.setTimestamp(genTimestamp().toString());
+                System.out.println("Voice conference recording stopped. file=["
+                 + getRecordFilenameFromEvent(event) + "], conf=[" + confName + "]");
+                conferenceEventListener.handleConferenceEvent(sre);
+            }
+        } 
+
+        else {
+            System.out.println("Processing UNKNOWN conference Action " + action + "]");
+        }
+    }
+
+    private Long genTimestamp() {
+        return TimeUnit.NANOSECONDS.toMillis(System.nanoTime());
+    }
+    
+    @Override
+    public void eventReceived(EslEvent event) {
+        System.out.println("ESL Event Listener received event=[" + event.getEventName() + "]" +
+                event.getEventHeaders().toString());
+//        if (event.getEventName().equals(FreeswitchHeartbeatMonitor.EVENT_HEARTBEAT)) {
+////           setChanged();
+//           notifyObservers(event);
+//           return; 
+//        }
+    }
+
+    private Integer getMemberIdFromEvent(EslEvent e) {
+        return new Integer(e.getEventHeaders().get("Member-ID"));
+    }
+
+    private String getCallerIdFromEvent(EslEvent e) {
+        return e.getEventHeaders().get("Caller-Caller-ID-Number");
+    }
+
+    private String getCallerIdNameFromEvent(EslEvent e) {
+        return e.getEventHeaders().get("Caller-Caller-ID-Name");
+    }
+
+    private String getRecordFilenameFromEvent(EslEvent e) {
+        return e.getEventHeaders().get("Path");
+    }
+
+    // Distinguish between recording to a file:
+    // /path/to/a/file.mp4
+    // and broadcasting a stream:
+    // {channels=2,samplerate=48000,vw=1920,vh=1080,fps=15.00}rtmp://192.168.0.109/live/abc/dev-test
+    private Boolean isRTMPStream(EslEvent e) {
+        String path = e.getEventHeaders().get("Path");
+
+        if (path.contains("rtmp") && path.contains("channels")
+                && path.contains("samplerate") && path.contains("vw")
+                && path.contains("vh") && path.contains("fps")) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    // returns a String so that we can parse to an int or double depending on the param
+    private String getBroadcastParameter(EslEvent e, String param) {
+        String path = e.getEventHeaders().get("Path");
+        if (isRTMPStream(e)) {
+            String temp = path.substring(path.indexOf("{") + 1, path.indexOf("}"));
+            String[] arr = temp.split(",");
+            for (int i = 0; i < 5; i++) {
+                if (arr[i].startsWith(param)) {
+                    return arr[i].substring(arr[i].indexOf('=') + 1);
+                }
+            }
+            return "0";
+        } else {
+            return "0";
+        }
+    }
+
+    // Obtain the rtmp url from the event (if any):
+    private String getStreamUrl(EslEvent e) {
+        String path = e.getEventHeaders().get("Path");
+        if (isRTMPStream(e)){
+            return path.substring(path.lastIndexOf("}") + 1);
+        } else {
+            return "";
+        }
+    }
+
+}
diff --git a/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/FreeswitchApplication.java b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/FreeswitchApplication.java
new file mode 100755
index 0000000000000000000000000000000000000000..d39365f7cd45b1add48bfea8b89bdc2541dff421
--- /dev/null
+++ b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/FreeswitchApplication.java
@@ -0,0 +1,183 @@
+/**
+ * BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
+ * <p>
+ * Copyright (c) 2015 BigBlueButton Inc. and by respective authors (see below).
+ * <p>
+ * This program is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation; either version 3.0 of the License, or (at your option) any later
+ * version.
+ * <p>
+ * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ * <p>
+ * You should have received a copy of the GNU Lesser General Public License along
+ * with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
+ */
+package org.bigbluebutton.freeswitch.voice.freeswitch;
+
+import java.io.File;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+
+import org.bigbluebutton.freeswitch.voice.freeswitch.actions.BroadcastConferenceCommand;
+import org.bigbluebutton.freeswitch.voice.freeswitch.actions.EjectAllUsersCommand;
+import org.bigbluebutton.freeswitch.voice.freeswitch.actions.EjectUserCommand;
+import org.bigbluebutton.freeswitch.voice.freeswitch.actions.FreeswitchCommand;
+import org.bigbluebutton.freeswitch.voice.freeswitch.actions.GetAllUsersCommand;
+import org.bigbluebutton.freeswitch.voice.freeswitch.actions.MuteUserCommand;
+import org.bigbluebutton.freeswitch.voice.freeswitch.actions.RecordConferenceCommand;
+import org.bigbluebutton.freeswitch.voice.freeswitch.actions.TransferUserToMeetingCommand;
+import org.bigbluebutton.freeswitch.voice.freeswitch.actions.*;
+
+public class FreeswitchApplication {
+
+  private static final int SENDERTHREADS = 1;
+  private static final Executor msgSenderExec = Executors.newFixedThreadPool(SENDERTHREADS);
+  private static final Executor runExec = Executors.newFixedThreadPool(SENDERTHREADS);
+  private BlockingQueue<FreeswitchCommand> messages = new LinkedBlockingQueue<FreeswitchCommand>();
+
+  private final ConnectionManager manager;
+
+  private final String USER = "0"; /* not used for now */
+
+  private volatile boolean sendMessages = false;
+
+  private final String audioProfile;
+
+  public FreeswitchApplication(ConnectionManager manager, String profile) {
+    this.manager = manager;
+    this.audioProfile = profile;
+  }
+
+  private void queueMessage(FreeswitchCommand command) {
+    try {
+      messages.offer(command, 5, TimeUnit.SECONDS);
+    } catch (InterruptedException e) {
+      // TODO Auto-generated catch block
+      e.printStackTrace();
+    }
+  }
+
+  public void transferUserToMeeting(String voiceConfId,
+                                    String targetVoiceConfId, String voiceUserId) {
+    TransferUserToMeetingCommand tutmc = new TransferUserToMeetingCommand(
+      voiceConfId, targetVoiceConfId, voiceUserId, this.audioProfile,
+      USER);
+    queueMessage(tutmc);
+  }
+
+  public void start() {
+    sendMessages = true;
+    Runnable sender = new Runnable() {
+      public void run() {
+        while (sendMessages) {
+          FreeswitchCommand message;
+          try {
+            message = messages.take();
+            sendMessageToFreeswitch(message);
+          } catch (InterruptedException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+          }
+        }
+      }
+    };
+    msgSenderExec.execute(sender);
+  }
+
+  public void getAllUsers(String voiceConfId) {
+    GetAllUsersCommand prc = new GetAllUsersCommand(voiceConfId, USER);
+    queueMessage(prc);
+  }
+
+  public void muteUser(String voiceConfId, String voiceUserId, Boolean mute) {
+    MuteUserCommand mpc = new MuteUserCommand(voiceConfId, voiceUserId, mute, USER);
+    queueMessage(mpc);
+  }
+
+  public void eject(String voiceConfId, String voiceUserId) {
+    EjectUserCommand mpc = new EjectUserCommand(voiceConfId, voiceUserId, USER);
+    queueMessage(mpc);
+  }
+
+  public void ejectAll(String voiceConfId) {
+    EjectAllUsersCommand mpc = new EjectAllUsersCommand(voiceConfId, USER);
+    queueMessage(mpc);
+  }
+
+  private Long genTimestamp() {
+    return TimeUnit.NANOSECONDS.toMillis(System.nanoTime());
+  }
+
+  public void startRecording(String voiceConfId, String meetingid) {
+    String RECORD_DIR = "/var/freeswitch/meetings";
+    String voicePath = RECORD_DIR + File.separatorChar + meetingid + "-" + genTimestamp() + ".wav";
+
+    RecordConferenceCommand rcc = new RecordConferenceCommand(voiceConfId, USER, true, voicePath);
+    queueMessage(rcc);
+  }
+
+  public void stopRecording(String voiceConfId, String meetingid, String voicePath) {
+    RecordConferenceCommand rcc = new RecordConferenceCommand(voiceConfId, USER, false, voicePath);
+    queueMessage(rcc);
+  }
+
+  public void deskShareBroadcastRTMP(String voiceConfId, String streamUrl, String timestamp, Boolean broadcast) {
+    DeskShareBroadcastRTMPCommand rtmp = new DeskShareBroadcastRTMPCommand(voiceConfId, USER, streamUrl, timestamp, broadcast);
+    queueMessage(rtmp);
+  }
+
+  public void deskShareHangUp(String voiceConfId, String fsConferenceName, String timestamp) {
+    DeskShareHangUpCommand huCmd = new DeskShareHangUpCommand(voiceConfId, fsConferenceName, USER, timestamp);
+    queueMessage(huCmd);
+  }
+
+  private void sendMessageToFreeswitch(final FreeswitchCommand command) {
+    Runnable task = new Runnable() {
+      public void run() {
+        if (command instanceof GetAllUsersCommand) {
+          GetAllUsersCommand cmd = (GetAllUsersCommand) command;
+          System.out.println("Sending PopulateRoomCommand for conference = [" + cmd.getRoom() + "]");
+          manager.getUsers(cmd);
+        } else if (command instanceof MuteUserCommand) {
+          MuteUserCommand cmd = (MuteUserCommand) command;
+          System.out.println("Sending MuteParticipantCommand for conference = [" + cmd.getRoom() + "]");
+          manager.mute(cmd);
+        } else if (command instanceof EjectUserCommand) {
+          EjectUserCommand cmd = (EjectUserCommand) command;
+          System.out.println("Sending EjectParticipantCommand for conference = [" + cmd.getRoom() + "]");
+          manager.eject(cmd);
+        } else if (command instanceof EjectAllUsersCommand) {
+          EjectAllUsersCommand cmd = (EjectAllUsersCommand) command;
+          System.out.println("Sending EjectAllUsersCommand for conference = [" + cmd.getRoom() + "]");
+          manager.ejectAll(cmd);
+        } else if (command instanceof TransferUserToMeetingCommand) {
+          TransferUserToMeetingCommand cmd = (TransferUserToMeetingCommand) command;
+          System.out.println("Sending TransferUsetToMeetingCommand for conference = ["
+            + cmd.getRoom() + "]");
+          manager.tranfer(cmd);
+        } else if (command instanceof RecordConferenceCommand) {
+          manager.record((RecordConferenceCommand) command);
+        } else if (command instanceof DeskShareBroadcastRTMPCommand) {
+          manager.broadcastRTMP((DeskShareBroadcastRTMPCommand) command);
+        } else if (command instanceof DeskShareHangUpCommand) {
+          DeskShareHangUpCommand cmd = (DeskShareHangUpCommand) command;
+          manager.hangUp(cmd);
+        } else if (command instanceof BroadcastConferenceCommand) {
+          manager.broadcast((BroadcastConferenceCommand) command);
+        }
+      }
+    };
+
+    runExec.execute(task);
+  }
+
+  public void stop() {
+    sendMessages = false;
+  }
+}
diff --git a/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/actions/BroadcastConferenceCommand.java b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/actions/BroadcastConferenceCommand.java
new file mode 100755
index 0000000000000000000000000000000000000000..45ef88764f558f057c764ee0d59f5b3911018d20
--- /dev/null
+++ b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/actions/BroadcastConferenceCommand.java
@@ -0,0 +1,50 @@
+/**
+* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
+* 
+* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
+*
+* This program is free software; you can redistribute it and/or modify it under the
+* terms of the GNU Lesser General Public License as published by the Free Software
+* Foundation; either version 3.0 of the License, or (at your option) any later
+* version.
+* 
+* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
+* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License along
+* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
+*
+*/
+package org.bigbluebutton.freeswitch.voice.freeswitch.actions;
+
+import org.bigbluebutton.freeswitch.voice.events.ConferenceEventListener;
+import org.freeswitch.esl.client.transport.message.EslMessage;
+
+public class BroadcastConferenceCommand extends FreeswitchCommand {
+	private boolean record;
+	private String icecastPath;
+	
+	public BroadcastConferenceCommand(String room, String requesterId, boolean record, String icecastPath){
+		super(room, requesterId);
+		this.record = record;
+		this.icecastPath = icecastPath;
+	}
+	
+
+	@Override
+	public String getCommandArgs() {
+		String action = "norecord";
+		if (record)
+			action = "record";
+		
+		return SPACE + getRoom() + SPACE + action + SPACE + icecastPath;
+	}
+
+	public void handleResponse(EslMessage response, ConferenceEventListener eventListener) {
+
+        //Test for Known Conference
+
+
+    }
+}
diff --git a/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/actions/DeskShareBroadcastRTMPCommand.java b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/actions/DeskShareBroadcastRTMPCommand.java
new file mode 100644
index 0000000000000000000000000000000000000000..67cd5130aa9696fc478d773f49349c0ff0049460
--- /dev/null
+++ b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/actions/DeskShareBroadcastRTMPCommand.java
@@ -0,0 +1,58 @@
+/**
+* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
+* 
+* Copyright (c) 2015 BigBlueButton Inc. and by respective authors (see below).
+*
+* This program is free software; you can redistribute it and/or modify it under the
+* terms of the GNU Lesser General Public License as published by the Free Software
+* Foundation; either version 3.0 of the License, or (at your option) any later
+* version.
+* 
+* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
+* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License along
+* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
+*
+*/
+package org.bigbluebutton.freeswitch.voice.freeswitch.actions;
+
+import org.bigbluebutton.freeswitch.voice.events.ConferenceEventListener;
+import org.freeswitch.esl.client.transport.message.EslMessage;
+
+public class DeskShareBroadcastRTMPCommand extends FreeswitchCommand {
+
+	private String broadcastPath;
+	private boolean broadcast;
+	private String timestamp;
+	private final String DESKSHARE_SUFFIX = "-DESKSHARE";
+
+	public DeskShareBroadcastRTMPCommand(String room, String requesterId, String broadcastPath, String timestamp, boolean broadcast){
+		super(room, requesterId);
+		this.broadcastPath = broadcastPath;
+		this.broadcast = broadcast;
+		this.timestamp = timestamp;
+	}
+
+
+	@Override
+	public String getCommandArgs() {
+		String action = "norecord";
+		if (broadcast) {
+			action = "record";
+		}
+
+		String room = getRoom();
+		if (!room.endsWith(DESKSHARE_SUFFIX)) {
+			room = room + DESKSHARE_SUFFIX;
+		}
+
+		return SPACE + room + SPACE + action + SPACE + broadcastPath;
+	}
+
+	public void handleResponse(EslMessage response, ConferenceEventListener eventListener) {
+		//Test for Known Conference
+		System.out.println("\nDeskShareBroadcastRTMPCommand\n");
+	}
+}
diff --git a/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/actions/DeskShareHangUpCommand.java b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/actions/DeskShareHangUpCommand.java
new file mode 100644
index 0000000000000000000000000000000000000000..7c2e5537bdf5ad516ca9f1a197a594a33a5b5810
--- /dev/null
+++ b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/actions/DeskShareHangUpCommand.java
@@ -0,0 +1,35 @@
+package org.bigbluebutton.freeswitch.voice.freeswitch.actions;
+
+import org.bigbluebutton.freeswitch.voice.events.ConferenceEventListener;
+import org.freeswitch.esl.client.transport.message.EslMessage;
+
+/**
+ * Created by anton on 07/01/16.
+ */
+public class DeskShareHangUpCommand  extends FreeswitchCommand {
+    private String timestamp;
+    private String fsConferenceName;
+    private final String DESKSHARE_SUFFIX = "-DESKSHARE";
+
+    public DeskShareHangUpCommand(String room, String fsConferenceName, String requesterId, String timestamp){
+        super(room, requesterId);
+        this.timestamp = timestamp;
+        this.fsConferenceName = fsConferenceName;
+    }
+
+
+    @Override
+    public String getCommandArgs() {
+        String action = "kick all";
+
+        if(!fsConferenceName.endsWith(DESKSHARE_SUFFIX)) {
+            fsConferenceName = fsConferenceName + DESKSHARE_SUFFIX;
+        }
+        return SPACE + fsConferenceName + SPACE + action;
+    }
+
+    public void handleResponse(EslMessage response, ConferenceEventListener eventListener) {
+        System.out.println("\nDeskShareHangUpCommand\n");
+    }
+}
+
diff --git a/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/actions/DeskShareRecordCommand.java b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/actions/DeskShareRecordCommand.java
new file mode 100644
index 0000000000000000000000000000000000000000..ff5e733558b8b8ba62375795f750ed6112cbbb42
--- /dev/null
+++ b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/actions/DeskShareRecordCommand.java
@@ -0,0 +1,50 @@
+/**
+* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
+* 
+* Copyright (c) 2015 BigBlueButton Inc. and by respective authors (see below).
+*
+* This program is free software; you can redistribute it and/or modify it under the
+* terms of the GNU Lesser General Public License as published by the Free Software
+* Foundation; either version 3.0 of the License, or (at your option) any later
+* version.
+* 
+* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
+* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License along
+* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
+*
+*/
+package org.bigbluebutton.freeswitch.voice.freeswitch.actions;
+
+import org.bigbluebutton.freeswitch.voice.events.ConferenceEventListener;
+import org.freeswitch.esl.client.transport.message.EslMessage;
+
+public class DeskShareRecordCommand extends FreeswitchCommand {
+
+	private String recordPath;
+	private boolean record;
+
+	public DeskShareRecordCommand(String room, String requesterId, boolean record, String recordPath){
+		super(room, requesterId);
+		this.recordPath = recordPath;
+		this.record = record;
+	}
+
+
+	@Override
+	public String getCommandArgs() {
+		String action = "norecord";
+		if (record)
+			action = "record";
+
+		System.out.println("\n\n\n\n\n DESKSHARE RECORD " + record + "\n\n\n\n");
+		return SPACE + getRoom() + SPACE + action + SPACE + recordPath;
+	}
+
+	public void handleResponse(EslMessage response, ConferenceEventListener eventListener) {
+		//Test for Known Conference
+		System.out.println("\n\n\n\n\nLALALALLALA\n\n\n\n");
+	}
+}
diff --git a/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/actions/EjectAllUsersCommand.java b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/actions/EjectAllUsersCommand.java
new file mode 100755
index 0000000000000000000000000000000000000000..4c24b28758e194176486cca1ba56181b4bb27304
--- /dev/null
+++ b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/actions/EjectAllUsersCommand.java
@@ -0,0 +1,31 @@
+/**
+* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
+* 
+* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
+*
+* This program is free software; you can redistribute it and/or modify it under the
+* terms of the GNU Lesser General Public License as published by the Free Software
+* Foundation; either version 3.0 of the License, or (at your option) any later
+* version.
+* 
+* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
+* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License along
+* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
+*
+*/
+package org.bigbluebutton.freeswitch.voice.freeswitch.actions;
+
+public class EjectAllUsersCommand extends FreeswitchCommand {
+    
+    public EjectAllUsersCommand(String room, String requesterId) {
+            super(room, requesterId);
+    }
+
+    @Override
+    public String getCommandArgs() {
+        return room + " kick all";
+    }
+}
diff --git a/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/actions/EjectUserCommand.java b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/actions/EjectUserCommand.java
new file mode 100755
index 0000000000000000000000000000000000000000..aa5315710f46092c0123423ebe9498258533fb5b
--- /dev/null
+++ b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/actions/EjectUserCommand.java
@@ -0,0 +1,34 @@
+/**
+* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
+* 
+* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
+*
+* This program is free software; you can redistribute it and/or modify it under the
+* terms of the GNU Lesser General Public License as published by the Free Software
+* Foundation; either version 3.0 of the License, or (at your option) any later
+* version.
+* 
+* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
+* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License along
+* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
+*
+*/
+package org.bigbluebutton.freeswitch.voice.freeswitch.actions;
+
+public class EjectUserCommand extends FreeswitchCommand {
+    
+    private final String participant;
+
+    public EjectUserCommand(String room, String participant, String requesterId) {
+            super(room, requesterId);
+            this.participant = participant;
+    }
+
+    @Override
+    public String getCommandArgs() {
+        return room + " kick " + participant;
+    }
+}
diff --git a/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/actions/FreeswitchCommand.java b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/actions/FreeswitchCommand.java
new file mode 100755
index 0000000000000000000000000000000000000000..4efd29f95eb8905896494bf257d348b842f4c1c0
--- /dev/null
+++ b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/actions/FreeswitchCommand.java
@@ -0,0 +1,45 @@
+/**
+* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
+* 
+* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
+*
+* This program is free software; you can redistribute it and/or modify it under the
+* terms of the GNU Lesser General Public License as published by the Free Software
+* Foundation; either version 3.0 of the License, or (at your option) any later
+* version.
+* 
+* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
+* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License along
+* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
+*
+*/
+package org.bigbluebutton.freeswitch.voice.freeswitch.actions;
+
+public abstract class FreeswitchCommand {
+    public static final String SPACE = " ";
+
+    protected final String room;
+    protected final String requesterId;
+
+    public FreeswitchCommand(String room, String requesterId) {
+            this.room = room;
+            this.requesterId = requesterId;
+    }
+
+    public String getCommand() {
+        return "conference"; //conference is default, override if needed.
+    }
+
+    public abstract String getCommandArgs();
+
+    public String getRoom() {
+            return room;
+    }
+
+    public String getRequesterId() {
+            return requesterId;
+    }
+}
diff --git a/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/actions/GetAllUsersCommand.java b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/actions/GetAllUsersCommand.java
new file mode 100755
index 0000000000000000000000000000000000000000..f4f1aab7a0452623823aeb13314734c5812c520c
--- /dev/null
+++ b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/actions/GetAllUsersCommand.java
@@ -0,0 +1,115 @@
+/**
+* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
+* 
+* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
+*
+* This program is free software; you can redistribute it and/or modify it under the
+* terms of the GNU Lesser General Public License as published by the Free Software
+* Foundation; either version 3.0 of the License, or (at your option) any later
+* version.
+* 
+* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
+* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License along
+* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
+*
+*/
+package org.bigbluebutton.freeswitch.voice.freeswitch.actions;
+
+import org.freeswitch.esl.client.transport.message.EslMessage;
+import org.apache.commons.lang3.StringUtils;
+import org.bigbluebutton.freeswitch.voice.events.ConferenceEventListener;
+import org.bigbluebutton.freeswitch.voice.events.VoiceUserJoinedEvent;
+import org.bigbluebutton.freeswitch.voice.freeswitch.response.ConferenceMember;
+import org.bigbluebutton.freeswitch.voice.freeswitch.response.XMLResponseConferenceListParser;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.xml.sax.SAXException;
+
+public class GetAllUsersCommand extends FreeswitchCommand {
+
+    public GetAllUsersCommand(String room, String requesterId) {
+            super(room, requesterId);
+    }
+    
+    @Override
+    public String getCommandArgs() {
+        return getRoom() + SPACE + "xml_list";
+    }
+
+    private static final Pattern CALLERNAME_PATTERN = Pattern.compile("(.*)-bbbID-(.*)$");
+    
+    public void handleResponse(EslMessage response, ConferenceEventListener eventListener) {
+
+        //Test for Known Conference
+
+        String firstLine = response.getBodyLines().get(0);
+
+        //E.g. Conference 85115 not found
+        
+        if(!firstLine.startsWith("<?xml")) {
+//            System.out.println("Not XML: [{}]", firstLine);
+            return;
+        }
+
+
+        XMLResponseConferenceListParser confXML = new XMLResponseConferenceListParser();
+
+        //get a factory
+        SAXParserFactory spf = SAXParserFactory.newInstance();
+        try {
+
+            //get a new instance of parser
+            SAXParser sp = spf.newSAXParser();
+
+            //Hack turning body lines back into string then to ByteStream.... BLAH!
+            
+            String responseBody = StringUtils.join(response.getBodyLines(), "\n");
+
+            //http://mark.koli.ch/2009/02/resolving-orgxmlsaxsaxparseexception-content-is-not-allowed-in-prolog.html
+            //This Sux!
+            responseBody = responseBody.trim().replaceFirst("^([\\W]+)<","<");
+
+            ByteArrayInputStream bs = new ByteArrayInputStream(responseBody.getBytes());
+            sp.parse(bs, confXML);
+
+            //Maybe move this to XMLResponseConferenceListParser, sendConfrenceEvents ?
+            VoiceUserJoinedEvent pj;
+
+            for(ConferenceMember member : confXML.getConferenceList()) {
+                //Foreach found member in conference create a JoinedEvent
+                String callerId = member.getCallerId();
+                String callerIdName = member.getCallerIdName();
+                String voiceUserId = callerIdName;
+                
+        		Matcher matcher = CALLERNAME_PATTERN.matcher(callerIdName);
+        		if (matcher.matches()) {			
+        			voiceUserId = matcher.group(1).trim();
+        			callerIdName = matcher.group(2).trim();
+        		} 
+        		
+                pj = new VoiceUserJoinedEvent(voiceUserId, member.getId().toString(), confXML.getConferenceRoom(),
+                		callerId, callerIdName, member.getMuted(), member.getSpeaking(), null);
+                eventListener.handleConferenceEvent(pj);
+            }
+
+        }catch(SAXException se) {
+//            System.out.println("Cannot parse repsonce. ", se);
+        }catch(ParserConfigurationException pce) {
+//            System.out.println("ParserConfigurationException. ", pce);
+        }catch (IOException ie) {
+//        	System.out.println("Cannot parse repsonce. IO Exception. ", ie);
+        }
+    }
+
+}
diff --git a/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/actions/MuteUserCommand.java b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/actions/MuteUserCommand.java
new file mode 100755
index 0000000000000000000000000000000000000000..e015535302b1db91db33e5467eb050c51ed9aa9c
--- /dev/null
+++ b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/actions/MuteUserCommand.java
@@ -0,0 +1,40 @@
+/**
+* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
+* 
+* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
+*
+* This program is free software; you can redistribute it and/or modify it under the
+* terms of the GNU Lesser General Public License as published by the Free Software
+* Foundation; either version 3.0 of the License, or (at your option) any later
+* version.
+* 
+* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
+* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License along
+* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
+*
+*/
+package org.bigbluebutton.freeswitch.voice.freeswitch.actions;
+
+public class MuteUserCommand extends FreeswitchCommand {
+	
+    private final String participant;
+    private final Boolean mute;
+
+    public MuteUserCommand(String room, String participant, Boolean mute, String requesterId) {
+            super(room, requesterId);
+            this.participant = participant;
+            this.mute = mute;
+    }
+
+    @Override
+    public String getCommandArgs() {
+            String action = "unmute";
+            if (mute) action = "mute";
+
+            return room + SPACE + action + SPACE + participant;
+    }
+
+}
diff --git a/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/actions/RecordConferenceCommand.java b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/actions/RecordConferenceCommand.java
new file mode 100755
index 0000000000000000000000000000000000000000..ab2bd64c1ca7bc8244c7eb2f4371a01e2fb5a6f0
--- /dev/null
+++ b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/actions/RecordConferenceCommand.java
@@ -0,0 +1,50 @@
+/**
+* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
+* 
+* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
+*
+* This program is free software; you can redistribute it and/or modify it under the
+* terms of the GNU Lesser General Public License as published by the Free Software
+* Foundation; either version 3.0 of the License, or (at your option) any later
+* version.
+* 
+* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
+* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License along
+* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
+*
+*/
+package org.bigbluebutton.freeswitch.voice.freeswitch.actions;
+
+import org.bigbluebutton.freeswitch.voice.events.ConferenceEventListener;
+import org.freeswitch.esl.client.transport.message.EslMessage;
+
+public class RecordConferenceCommand extends FreeswitchCommand {
+
+	private boolean record;
+	private String recordPath;
+	
+	public RecordConferenceCommand(String room, String requesterId, boolean record, String recordPath){
+		super(room, requesterId);
+		this.record = record;
+		this.recordPath = recordPath;
+	}
+	
+
+	@Override
+	public String getCommandArgs() {
+		String action = "norecord";
+		if (record)
+			action = "record";
+		
+		return SPACE + getRoom() + SPACE + action + SPACE + recordPath;
+	}
+
+	public void handleResponse(EslMessage response, ConferenceEventListener eventListener) {
+
+        //Test for Known Conference
+
+    }
+}
diff --git a/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/actions/TransferUserToMeetingCommand.java b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/actions/TransferUserToMeetingCommand.java
new file mode 100644
index 0000000000000000000000000000000000000000..c182dbc8ccc89f85e0b2f6672d14ab774a20e7fb
--- /dev/null
+++ b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/actions/TransferUserToMeetingCommand.java
@@ -0,0 +1,41 @@
+/**
+ * BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
+ * 
+ * Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
+ *
+ * This program is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation; either version 3.0 of the License, or (at your option) any later
+ * version.
+ * 
+ * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along
+ * with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+package org.bigbluebutton.freeswitch.voice.freeswitch.actions;
+
+public class TransferUserToMeetingCommand extends FreeswitchCommand {
+
+    private final String targetRoom;
+    private final String participant;
+    private final String audioProfile;
+
+    public TransferUserToMeetingCommand(String room, String targetRoom,
+            String participant, String profile, String requesterId) {
+        super(room, requesterId);
+        this.targetRoom = targetRoom;
+        this.participant = participant;
+        this.audioProfile = profile;
+    }
+
+    @Override
+    public String getCommandArgs() {
+        return room + SPACE + "transfer" + SPACE + targetRoom + "@"
+                + this.audioProfile + SPACE + participant;
+    }
+}
diff --git a/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/response/ConferenceMember.java b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/response/ConferenceMember.java
new file mode 100755
index 0000000000000000000000000000000000000000..915a265217c61fb67848443b6291bf64a57c2194
--- /dev/null
+++ b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/response/ConferenceMember.java
@@ -0,0 +1,88 @@
+/**
+* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
+* 
+* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
+*
+* This program is free software; you can redistribute it and/or modify it under the
+* terms of the GNU Lesser General Public License as published by the Free Software
+* Foundation; either version 3.0 of the License, or (at your option) any later
+* version.
+* 
+* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
+* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License along
+* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
+*
+*/
+
+package org.bigbluebutton.freeswitch.voice.freeswitch.response;
+
+/**
+ *
+ * @author leif
+ */
+public class ConferenceMember {
+
+    protected Integer memberId;
+    protected ConferenceMemberFlags flags;
+    protected String uuid;
+    protected String callerIdName;
+    protected String callerId;
+    protected Integer joinTime;
+    protected Integer lastTalking;
+
+    public Integer getId() {
+        return memberId;
+    }
+
+    public ConferenceMemberFlags getFlags() {
+        return flags;
+    }
+
+    public String getCallerId() {
+        return callerId;
+    }
+
+    public String getCallerIdName() {
+        return callerIdName;
+    }
+
+    public boolean getMuted() {
+        return flags.getIsMuted();
+    }
+
+    public boolean getSpeaking() {
+        return flags.getIsSpeaking();
+    }
+
+    public void setFlags(ConferenceMemberFlags flags) {
+        this.flags = flags;
+    }
+
+    public void setId(int parseInt) {
+        memberId = parseInt;
+    }
+
+    public void setUUID(String tempVal) {
+        this.uuid = tempVal;
+    }
+
+    public void setCallerIdName(String tempVal) {
+        this.callerIdName = tempVal;
+    }
+
+    public void setCallerId(String tempVal) {
+        this.callerId = tempVal;
+    }
+
+    public void setJoinTime(int parseInt) {
+        this.joinTime = parseInt;
+    }
+
+    void setLastTalking(int parseInt) {
+        this.lastTalking = parseInt;
+    }
+
+}
diff --git a/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/response/ConferenceMemberFlags.java b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/response/ConferenceMemberFlags.java
new file mode 100755
index 0000000000000000000000000000000000000000..f571f5da4fcf96bbad076b9c75d8a513f2773a9d
--- /dev/null
+++ b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/response/ConferenceMemberFlags.java
@@ -0,0 +1,54 @@
+/**
+* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
+* 
+* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
+*
+* This program is free software; you can redistribute it and/or modify it under the
+* terms of the GNU Lesser General Public License as published by the Free Software
+* Foundation; either version 3.0 of the License, or (at your option) any later
+* version.
+* 
+* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
+* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License along
+* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
+*
+*/
+
+package org.bigbluebutton.freeswitch.voice.freeswitch.response;
+
+/**
+ *
+ * @author leif
+ */
+public class ConferenceMemberFlags {
+    //private boolean canHear = false;
+    private boolean canSpeak = false;
+    private boolean talking = false;
+    //private boolean hasVideo = false;
+    //private boolean hasFloor = false;
+    //private boolean isModerator = false;
+    //private boolean endConference = false;
+
+    boolean getIsSpeaking() {
+        return talking;
+    }
+
+    boolean getIsMuted() {
+        if(canSpeak == true) {
+            return false;
+        }
+        return true;
+    }
+
+    void setCanSpeak(String tempVal) {
+        canSpeak = tempVal.equals("true") ? true : false;
+    }
+
+    void setTalking(String tempVal) {
+        talking = tempVal.equals("true") ? true : false;
+    }
+
+}
diff --git a/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/response/XMLResponseConferenceListParser.java b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/response/XMLResponseConferenceListParser.java
new file mode 100755
index 0000000000000000000000000000000000000000..397e7ce42ab764bc9eb105b59ad9745a44fb940f
--- /dev/null
+++ b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/freeswitch/response/XMLResponseConferenceListParser.java
@@ -0,0 +1,158 @@
+/**
+* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
+* 
+* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
+*
+* This program is free software; you can redistribute it and/or modify it under the
+* terms of the GNU Lesser General Public License as published by the Free Software
+* Foundation; either version 3.0 of the License, or (at your option) any later
+* version.
+* 
+* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
+* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License along
+* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
+*
+*/
+package org.bigbluebutton.freeswitch.voice.freeswitch.response;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+/**
+ *
+ * @author leif
+ */
+public class XMLResponseConferenceListParser extends DefaultHandler {
+    private List<ConferenceMember> myConfrenceMembers;
+    private String tempVal;
+    private ConferenceMember tempMember;
+    private ConferenceMemberFlags tempFlags;
+    private String room;
+    private boolean inFlags = false;
+    
+    public XMLResponseConferenceListParser() {
+        myConfrenceMembers = new ArrayList<ConferenceMember>();
+    }
+
+    public String getConferenceRoom() {
+        return room;
+    }
+
+    public void printConferneceMemebers() {
+        Iterator<ConferenceMember> it = myConfrenceMembers.iterator();
+        while(it.hasNext()) {
+            
+        }
+    }
+
+    public List<ConferenceMember> getConferenceList() {
+        return myConfrenceMembers;
+    }
+
+            /*
+<?xml version="1.0"?>
+<conferences>
+  <conference name="3001-192.168.1.10" member-count="1" rate="8000" running="true" answered="true" enforce_min="true" dynamic="true">
+    <members>
+      <member>
+        <id>6</id>
+        <flags>
+          <can_hear>true</can_hear>
+          <can_speak>true</can_speak>
+          <talking>false</talking>
+          <has_video>false</has_video>
+          <has_floor>true</has_floor>
+          <is_moderator>false</is_moderator>
+          <end_conference>false</end_conference>
+        </flags>
+        <uuid>3a16f061-0df6-45d5-b401-d8e977e08a5c</uuid>
+        <caller_id_name>1001</caller_id_name>
+        <caller_id_number>1001</caller_id_number>
+        <join_time>65</join_time>
+        <last_talking>4</last_talking>
+      </member>
+    </members>
+  </conference>
+</conferences>
+
+             */
+
+
+    //SAX Event Handlers
+    @Override
+    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
+        //reset
+        inFlags = false;
+        tempVal = "";
+        if(qName.equalsIgnoreCase("member")) {
+            //create a new instance of ConferenceMember
+            tempMember = new ConferenceMember();
+        }
+
+        if(qName.equalsIgnoreCase("flags")) {
+            //create a new instance of ConferenceMember
+            tempFlags = new ConferenceMemberFlags();
+            inFlags = true;
+        }
+
+        if(qName.equalsIgnoreCase("conference")) {
+            room = attributes.getValue("name");
+        }
+    }
+
+
+    @Override
+    public void characters(char[] ch, int start, int length) throws SAXException {
+        tempVal = new String(ch,start,length);
+    }
+
+    @Override
+    public void endElement(String uri, String localName, String qName) throws SAXException {
+
+        if(qName.equalsIgnoreCase("member")) {
+            //add it to the list
+            myConfrenceMembers.add(tempMember);
+        }else if(qName.equalsIgnoreCase("flags")) {
+            tempMember.setFlags(tempFlags);
+            inFlags = false;
+        }else if(inFlags) {
+            if (qName.equalsIgnoreCase("can_speak")) {
+                tempFlags.setCanSpeak(tempVal);
+            }else if (qName.equalsIgnoreCase("talking")) {
+                tempFlags.setTalking(tempVal);
+            }
+        }else if (qName.equalsIgnoreCase("id")) {
+            try {
+                tempMember.setId(Integer.parseInt(tempVal));
+            } catch(NumberFormatException nfe) {
+                
+            }
+        }else if (qName.equalsIgnoreCase("uuid")) {
+            tempMember.setUUID(tempVal);
+        }else if (qName.equalsIgnoreCase("caller_id_name")) {
+            tempMember.setCallerIdName(tempVal);
+        }else if (qName.equalsIgnoreCase("caller_id_number")) {
+            tempMember.setCallerId(tempVal);
+        }else if (qName.equalsIgnoreCase("join_time")) {
+            try {
+                tempMember.setJoinTime(Integer.parseInt(tempVal));
+            } catch(NumberFormatException nfe) {
+                
+            }
+        }else if (qName.equalsIgnoreCase("last_talking")) {
+            try {
+                tempMember.setLastTalking(Integer.parseInt(tempVal));
+            } catch(NumberFormatException nfe) {
+                
+            }
+        }
+
+    }
+}
diff --git a/akka-bbb-fsesl/src/main/scala/org/bigbluebutton/freeswitch/VoiceConferenceService.scala b/akka-bbb-fsesl/src/main/scala/org/bigbluebutton/freeswitch/VoiceConferenceService.scala
new file mode 100755
index 0000000000000000000000000000000000000000..42e63944c3c5e174951e8da61f3ce957ba28130c
--- /dev/null
+++ b/akka-bbb-fsesl/src/main/scala/org/bigbluebutton/freeswitch/VoiceConferenceService.scala
@@ -0,0 +1,115 @@
+package org.bigbluebutton.freeswitch
+
+import org.bigbluebutton.SystemConfiguration
+import org.bigbluebutton.freeswitch.voice.IVoiceConferenceService
+import org.bigbluebutton.endpoint.redis.RedisPublisher
+import org.bigbluebutton.common.messages.DeskShareStartedEventMessage
+import org.bigbluebutton.common.messages.DeskShareStoppedEventMessage
+import org.bigbluebutton.common.messages.DeskShareRTMPBroadcastStartedEventMessage
+import org.bigbluebutton.common.messages.DeskShareRTMPBroadcastStoppedEventMessage
+import org.bigbluebutton.common2.messages.{ BbbCommonEnvCoreMsg, BbbCoreEnvelope }
+import org.bigbluebutton.common2.messages.voiceconf._
+import org.bigbluebutton.common2.util.JsonUtil
+
+class VoiceConferenceService(sender: RedisPublisher) extends IVoiceConferenceService with SystemConfiguration {
+
+  def voiceConfRecordingStarted(voiceConfId: String, recordStream: String, recording: java.lang.Boolean, timestamp: String) {
+    val header = BbbCoreVoiceConfHeader(RecordingStartedVoiceConfEvtMsg.NAME, voiceConfId)
+    val body = RecordingStartedVoiceConfEvtMsgBody(voiceConfId, recordStream, recording.booleanValue(), timestamp)
+    val envelope = BbbCoreEnvelope(RecordingStartedVoiceConfEvtMsg.NAME, Map("voiceConf" -> voiceConfId))
+
+    val msg = new RecordingStartedVoiceConfEvtMsg(header, body)
+    val msgEvent = BbbCommonEnvCoreMsg(envelope, msg)
+
+    val json = JsonUtil.toJson(msgEvent)
+    sender.publish(fromVoiceConfRedisChannel, json)
+  }
+
+  def userJoinedVoiceConf(voiceConfId: String, voiceUserId: String, userId: String, callerIdName: String,
+    callerIdNum: String, muted: java.lang.Boolean, talking: java.lang.Boolean, avatarURL: String) {
+    println("******** FreeswitchConferenceService received voiceUserJoined vui=[" +
+      userId + "] wui=[" + voiceUserId + "]")
+
+    val header = BbbCoreVoiceConfHeader(UserJoinedVoiceConfEvtMsg.NAME, voiceConfId)
+    val body = UserJoinedVoiceConfEvtMsgBody(voiceConfId, voiceUserId, userId, callerIdName, callerIdNum,
+      muted.booleanValue(), talking.booleanValue(), avatarURL)
+    val envelope = BbbCoreEnvelope(UserJoinedVoiceConfEvtMsg.NAME, Map("voiceConf" -> voiceConfId))
+
+    val msg = new UserJoinedVoiceConfEvtMsg(header, body)
+    val msgEvent = BbbCommonEnvCoreMsg(envelope, msg)
+
+    val json = JsonUtil.toJson(msgEvent)
+    sender.publish(fromVoiceConfRedisChannel, json)
+  }
+
+  def userLeftVoiceConf(voiceConfId: String, voiceUserId: String) {
+    println("******** FreeswitchConferenceService received voiceUserLeft vui=[" + voiceUserId + "] conference=[" + voiceConfId + "]")
+
+    val header = BbbCoreVoiceConfHeader(UserLeftVoiceConfEvtMsg.NAME, voiceConfId)
+    val body = UserLeftVoiceConfEvtMsgBody(voiceConfId, voiceUserId)
+    val envelope = BbbCoreEnvelope(UserLeftVoiceConfEvtMsg.NAME, Map("voiceConf" -> voiceConfId))
+
+    val msg = new UserLeftVoiceConfEvtMsg(header, body)
+    val msgEvent = BbbCommonEnvCoreMsg(envelope, msg)
+
+    val json = JsonUtil.toJson(msgEvent)
+    sender.publish(fromVoiceConfRedisChannel, json)
+  }
+
+  def userLockedInVoiceConf(voiceConfId: String, voiceUserId: String, locked: java.lang.Boolean) {
+
+  }
+
+  def userMutedInVoiceConf(voiceConfId: String, voiceUserId: String, muted: java.lang.Boolean) {
+    println("******** FreeswitchConferenceService received voiceUserMuted vui=[" + voiceUserId + "] muted=[" + muted + "]")
+
+    val header = BbbCoreVoiceConfHeader(UserMutedInVoiceConfEvtMsg.NAME, voiceConfId)
+    val body = UserMutedInVoiceConfEvtMsgBody(voiceConfId, voiceUserId, muted.booleanValue())
+    val envelope = BbbCoreEnvelope(UserMutedInVoiceConfEvtMsg.NAME, Map("voiceConf" -> voiceConfId))
+
+    val msg = new UserMutedInVoiceConfEvtMsg(header, body)
+    val msgEvent = BbbCommonEnvCoreMsg(envelope, msg)
+
+    val json = JsonUtil.toJson(msgEvent)
+    sender.publish(fromVoiceConfRedisChannel, json)
+  }
+
+  def userTalkingInVoiceConf(voiceConfId: String, voiceUserId: String, talking: java.lang.Boolean) {
+    println("******** FreeswitchConferenceService received voiceUserTalking vui=[" + voiceUserId + "] talking=[" + talking + "]")
+
+    val header = BbbCoreVoiceConfHeader(UserTalkingInVoiceConfEvtMsg.NAME, voiceConfId)
+    val body = UserTalkingInVoiceConfEvtMsgBody(voiceConfId, voiceUserId, talking.booleanValue())
+    val envelope = BbbCoreEnvelope(UserTalkingInVoiceConfEvtMsg.NAME, Map("voiceConf" -> voiceConfId))
+
+    val msg = new UserTalkingInVoiceConfEvtMsg(header, body)
+    val msgEvent = BbbCommonEnvCoreMsg(envelope, msg)
+
+    val json = JsonUtil.toJson(msgEvent)
+    sender.publish(fromVoiceConfRedisChannel, json)
+  }
+
+  def deskShareStarted(voiceConfId: String, callerIdNum: String, callerIdName: String) {
+    println("******** FreeswitchConferenceService send deskShareStarted to BBB " + voiceConfId)
+    val msg = new DeskShareStartedEventMessage(voiceConfId, callerIdNum, callerIdName)
+    sender.publish(fromVoiceConfRedisChannel, msg.toJson())
+  }
+
+  def deskShareEnded(voiceConfId: String, callerIdNum: String, callerIdName: String) {
+    println("******** FreeswitchConferenceService send deskShareStopped to BBB " + voiceConfId)
+    val msg = new DeskShareStoppedEventMessage(voiceConfId, callerIdNum, callerIdName)
+    sender.publish(fromVoiceConfRedisChannel, msg.toJson())
+  }
+
+  def deskShareRTMPBroadcastStarted(voiceConfId: String, streamname: String, vw: java.lang.Integer, vh: java.lang.Integer, timestamp: String) {
+    println("******** FreeswitchConferenceService send deskShareRTMPBroadcastStarted to BBB " + voiceConfId)
+    val msg = new DeskShareRTMPBroadcastStartedEventMessage(voiceConfId, streamname, vw, vh, timestamp)
+    sender.publish(fromVoiceConfRedisChannel, msg.toJson())
+  }
+
+  def deskShareRTMPBroadcastStopped(voiceConfId: String, streamname: String, vw: java.lang.Integer, vh: java.lang.Integer, timestamp: String) {
+    println("******** FreeswitchConferenceService send deskShareRTMPBroadcastStopped to BBB " + voiceConfId)
+    val msg = new DeskShareRTMPBroadcastStoppedEventMessage(voiceConfId, streamname, vw, vh, timestamp)
+    sender.publish(fromVoiceConfRedisChannel, msg.toJson())
+  }
+
+}