From e01692c40b1a07949835717fba203db72120119d Mon Sep 17 00:00:00 2001
From: Richard Alam <ritzalam@gmail.com>
Date: Thu, 19 Oct 2017 17:18:50 -0700
Subject: [PATCH]  - send voice conf started and destroyed message

---
 .../core/apps/voice/VoiceApp2x.scala          |   3 +-
 .../voice/VoiceConfRunningEvtMsgHdlr.scala    |  15 ++
 .../senders/ReceivedJsonMsgHandlerActor.scala |   2 +
 .../core/running/MeetingActor.scala           |   1 +
 .../FreeswitchConferenceEventListener.java    | 217 +++++++++---------
 .../voice/IVoiceConferenceService.java        |  33 ++-
 .../voice/events/VoiceConfRunningEvent.java   |  32 +++
 .../voice/freeswitch/ESLEventListener.java    |  17 +-
 .../freeswitch/VoiceConferenceService.scala   |  13 ++
 .../common2/msgs/VoiceConfMsgs.scala          |  11 +-
 .../freeswitch/esl/client/inbound/Client.java |  53 +++--
 11 files changed, 250 insertions(+), 147 deletions(-)
 create mode 100755 akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/voice/VoiceConfRunningEvtMsgHdlr.scala
 create mode 100755 akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/events/VoiceConfRunningEvent.java

diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/voice/VoiceApp2x.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/voice/VoiceApp2x.scala
index 15aff65510..a7f07a4c0a 100755
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/voice/VoiceApp2x.scala
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/voice/VoiceApp2x.scala
@@ -8,7 +8,8 @@ trait VoiceApp2x extends UserJoinedVoiceConfEvtMsgHdlr
     with UserLeftVoiceConfEvtMsgHdlr
     with UserMutedInVoiceConfEvtMsgHdlr
     with UserTalkingInVoiceConfEvtMsgHdlr
-    with RecordingStartedVoiceConfEvtMsgHdlr {
+    with RecordingStartedVoiceConfEvtMsgHdlr
+    with VoiceConfRunningEvtMsgHdlr {
 
   this: MeetingActor =>
 }
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/voice/VoiceConfRunningEvtMsgHdlr.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/voice/VoiceConfRunningEvtMsgHdlr.scala
new file mode 100755
index 0000000000..6ab49fc36d
--- /dev/null
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/voice/VoiceConfRunningEvtMsgHdlr.scala
@@ -0,0 +1,15 @@
+package org.bigbluebutton.core.apps.voice
+
+import org.bigbluebutton.common2.msgs.VoiceConfRunningEvtMsg
+import org.bigbluebutton.core.running.{ BaseMeetingActor, LiveMeeting, OutMsgRouter }
+
+trait VoiceConfRunningEvtMsgHdlr {
+  this: BaseMeetingActor =>
+
+  val liveMeeting: LiveMeeting
+  val outGW: OutMsgRouter
+
+  def handleVoiceConfRunningEvtMsg(msg: VoiceConfRunningEvtMsg): Unit = {
+    log.info("Received VoiceConfRunningEvtMsg " + msg.body.running)
+  }
+}
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/pubsub/senders/ReceivedJsonMsgHandlerActor.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/pubsub/senders/ReceivedJsonMsgHandlerActor.scala
index 90c2bb537f..0a12204f2d 100755
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/pubsub/senders/ReceivedJsonMsgHandlerActor.scala
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/pubsub/senders/ReceivedJsonMsgHandlerActor.scala
@@ -107,6 +107,8 @@ class ReceivedJsonMsgHandlerActor(
       // Voice
       case RecordingStartedVoiceConfEvtMsg.NAME =>
         routeVoiceMsg[RecordingStartedVoiceConfEvtMsg](envelope, jsonNode)
+      case VoiceConfRunningEvtMsg.NAME =>
+        routeVoiceMsg[VoiceConfRunningEvtMsg](envelope, jsonNode)
       case UserJoinedVoiceConfEvtMsg.NAME =>
         routeVoiceMsg[UserJoinedVoiceConfEvtMsg](envelope, jsonNode)
       case UserLeftVoiceConfEvtMsg.NAME =>
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/MeetingActor.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/MeetingActor.scala
index a444195df9..674e72e312 100755
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/MeetingActor.scala
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/MeetingActor.scala
@@ -246,6 +246,7 @@ class MeetingActor(
       case m: MuteMeetingCmdMsg => handleMuteMeetingCmdMsg(m)
       case m: UserConnectedToGlobalAudioMsg => handleUserConnectedToGlobalAudioMsg(m)
       case m: UserDisconnectedFromGlobalAudioMsg => handleUserDisconnectedFromGlobalAudioMsg(m)
+      case m: VoiceConfRunningEvtMsg => handleVoiceConfRunningEvtMsg(m)
 
       // Layout
       case m: GetCurrentLayoutReqMsg => handleGetCurrentLayoutReqMsg(m)
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
index 6bdb81c4a4..00e4ad6a24 100755
--- 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
@@ -1,21 +1,20 @@
 /**
-* 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/>.
-*
-*/
+ * BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
+ * <p>
+ * Copyright (c) 2012 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;
 
 import java.util.concurrent.BlockingQueue;
@@ -24,106 +23,100 @@ import java.util.concurrent.Executors;
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.TimeUnit;
 
-import org.bigbluebutton.freeswitch.voice.events.ScreenshareStartedEvent;
-import org.bigbluebutton.freeswitch.voice.events.DeskShareEndedEvent;
-import org.bigbluebutton.freeswitch.voice.events.ConferenceEventListener;
-import org.bigbluebutton.freeswitch.voice.events.ScreenshareRTMPBroadcastEvent;
-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.bigbluebutton.freeswitch.voice.events.*;
 
 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 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 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) {
-				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) {
-					VoiceUserLeftEvent evt = (VoiceUserLeftEvent) event;
-					vcs.userLeftVoiceConf(evt.getRoom(), evt.getUserId());
-				} else if (event instanceof VoiceUserMutedEvent) {
-					VoiceUserMutedEvent evt = (VoiceUserMutedEvent) event;
-					vcs.userMutedInVoiceConf(evt.getRoom(), evt.getUserId(), evt.isMuted());
-				} else if (event instanceof VoiceUserTalkingEvent) {
-					VoiceUserTalkingEvent evt = (VoiceUserTalkingEvent) event;
-					vcs.userTalkingInVoiceConf(evt.getRoom(), evt.getUserId(), evt.isTalking());
-				} else if (event instanceof VoiceStartRecordingEvent) {
-					VoiceStartRecordingEvent evt = (VoiceStartRecordingEvent) event;
-					vcs.voiceConfRecordingStarted(evt.getRoom(), evt.getRecordingFilename(), evt.startRecord(), evt.getTimestamp());
-				} else if (event instanceof ScreenshareStartedEvent) {
-					ScreenshareStartedEvent evt = (ScreenshareStartedEvent) event;
-					vcs.deskShareStarted(evt.getRoom(), evt.getCallerIdNum(), evt.getCallerIdName());
-				} else if (event instanceof DeskShareEndedEvent) {
-					DeskShareEndedEvent evt = (DeskShareEndedEvent) event;
-					vcs.deskShareEnded(evt.getRoom(), evt.getCallerIdNum(), evt.getCallerIdName());
-				} else if (event instanceof ScreenshareRTMPBroadcastEvent) {
-					if (((ScreenshareRTMPBroadcastEvent) event).getBroadcast()) {
-						ScreenshareRTMPBroadcastEvent evt = (ScreenshareRTMPBroadcastEvent) event;
-						vcs.deskShareRTMPBroadcastStarted(evt.getRoom(), evt.getBroadcastingStreamUrl(),
-								evt.getVideoWidth(), evt.getVideoHeight(), evt.getTimestamp());
-					} else {
-                                                ScreenshareRTMPBroadcastEvent evt = (ScreenshareRTMPBroadcastEvent) event;
-						vcs.deskShareRTMPBroadcastStopped(evt.getRoom(), evt.getBroadcastingStreamUrl(),
-								evt.getVideoWidth(), evt.getVideoHeight(), evt.getTimestamp());
-					}
-				}
-			}
-		};
+  }
+
+  private void sendMessageToBigBlueButton(final VoiceConferenceEvent event) {
+    Runnable task = new Runnable() {
+      public void run() {
+        if (event instanceof VoiceUserJoinedEvent) {
+          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 VoiceConfRunningEvent) {
+          VoiceConfRunningEvent evt = (VoiceConfRunningEvent) event;
+          vcs.voiceConfRunning(evt.getRoom(), evt.isRunning());
+        } else if (event instanceof VoiceUserLeftEvent) {
+          VoiceUserLeftEvent evt = (VoiceUserLeftEvent) event;
+          vcs.userLeftVoiceConf(evt.getRoom(), evt.getUserId());
+        } else if (event instanceof VoiceUserMutedEvent) {
+          VoiceUserMutedEvent evt = (VoiceUserMutedEvent) event;
+          vcs.userMutedInVoiceConf(evt.getRoom(), evt.getUserId(), evt.isMuted());
+        } else if (event instanceof VoiceUserTalkingEvent) {
+          VoiceUserTalkingEvent evt = (VoiceUserTalkingEvent) event;
+          vcs.userTalkingInVoiceConf(evt.getRoom(), evt.getUserId(), evt.isTalking());
+        } else if (event instanceof VoiceStartRecordingEvent) {
+          VoiceStartRecordingEvent evt = (VoiceStartRecordingEvent) event;
+          vcs.voiceConfRecordingStarted(evt.getRoom(), evt.getRecordingFilename(), evt.startRecord(), evt.getTimestamp());
+        } else if (event instanceof ScreenshareStartedEvent) {
+          ScreenshareStartedEvent evt = (ScreenshareStartedEvent) event;
+          vcs.deskShareStarted(evt.getRoom(), evt.getCallerIdNum(), evt.getCallerIdName());
+        } else if (event instanceof DeskShareEndedEvent) {
+          DeskShareEndedEvent evt = (DeskShareEndedEvent) event;
+          vcs.deskShareEnded(evt.getRoom(), evt.getCallerIdNum(), evt.getCallerIdName());
+        } else if (event instanceof ScreenshareRTMPBroadcastEvent) {
+          if (((ScreenshareRTMPBroadcastEvent) event).getBroadcast()) {
+            ScreenshareRTMPBroadcastEvent evt = (ScreenshareRTMPBroadcastEvent) event;
+            vcs.deskShareRTMPBroadcastStarted(evt.getRoom(), evt.getBroadcastingStreamUrl(),
+              evt.getVideoWidth(), evt.getVideoHeight(), evt.getTimestamp());
+          } else {
+            ScreenshareRTMPBroadcastEvent evt = (ScreenshareRTMPBroadcastEvent) event;
+            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);
+  }
 
-		runExec.execute(task);
-	}
+  public void stop() {
+    sendMessages = false;
+  }
 
-	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);
-	}
+  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
index 0f0e2ab687..dd7fb1d13e 100755
--- 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
@@ -1,16 +1,27 @@
 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);
+  void voiceConfRecordingStarted(String voiceConfId, String recordStream, Boolean recording, String timestamp);
+
+  void voiceConfRunning(String voiceConfId, Boolean running);
+
+  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/events/VoiceConfRunningEvent.java b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/events/VoiceConfRunningEvent.java
new file mode 100755
index 0000000000..1bdfe45572
--- /dev/null
+++ b/akka-bbb-fsesl/src/main/java/org/bigbluebutton/freeswitch/voice/events/VoiceConfRunningEvent.java
@@ -0,0 +1,32 @@
+/**
+ * BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
+ * <p>
+ * Copyright (c) 2012 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.events;
+
+public class VoiceConfRunningEvent extends VoiceConferenceEvent {
+
+  private boolean running;
+
+  public VoiceConfRunningEvent(String room, boolean running) {
+    super(room);
+    this.running = running;
+  }
+
+  public boolean isRunning() {
+    return running;
+  }
+}
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
index b3ef985beb..87f2aad2e6 100755
--- 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
@@ -18,6 +18,8 @@ public class ESLEventListener implements IEslEventListener {
     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 CONFERENCE_CREATED_EVENT = "conference-create";
+    private static final String CONFERENCE_DESTROYED_EVENT = "conference-destroy";
 
     private static final String SCREENSHARE_CONFERENCE_NAME_SUFFIX = "-SCREENSHARE";
 
@@ -119,19 +121,24 @@ public class ESLEventListener implements IEslEventListener {
 
     @Override
     public void conferenceEventAction(String uniqueId, String confName, int confSize, String action, EslEvent event) {
-        Integer memberId = this.getMemberIdFromEvent(event);
-        VoiceUserTalkingEvent pt;
-        
         if (action == null) {
             return;
         }
 
         if (action.equals(START_TALKING_EVENT)) {
-            pt = new VoiceUserTalkingEvent(memberId.toString(), confName, true);
+            Integer memberId = this.getMemberIdFromEvent(event);
+            VoiceUserTalkingEvent pt = new VoiceUserTalkingEvent(memberId.toString(), confName, true);
             conferenceEventListener.handleConferenceEvent(pt);          
         } else if (action.equals(STOP_TALKING_EVENT)) {
-            pt = new VoiceUserTalkingEvent(memberId.toString(), confName, false);
+            Integer memberId = this.getMemberIdFromEvent(event);
+            VoiceUserTalkingEvent pt = new VoiceUserTalkingEvent(memberId.toString(), confName, false);
             conferenceEventListener.handleConferenceEvent(pt);          
+        } else if (action.equals(CONFERENCE_CREATED_EVENT)) {
+            VoiceConfRunningEvent pt = new VoiceConfRunningEvent(confName, true);
+            conferenceEventListener.handleConferenceEvent(pt);
+        } else if (action.equals(CONFERENCE_DESTROYED_EVENT)) {
+            VoiceConfRunningEvent pt = new VoiceConfRunningEvent(confName, false);
+            conferenceEventListener.handleConferenceEvent(pt);
         } else {
             System.out.println("Unknown conference Action [" + action + "]");
         }
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
index b00b3acea2..909c25a4c2 100755
--- a/akka-bbb-fsesl/src/main/scala/org/bigbluebutton/freeswitch/VoiceConferenceService.scala
+++ b/akka-bbb-fsesl/src/main/scala/org/bigbluebutton/freeswitch/VoiceConferenceService.scala
@@ -23,6 +23,19 @@ class VoiceConferenceService(sender: RedisPublisher) extends IVoiceConferenceSer
 
   }
 
+  def voiceConfRunning(voiceConfId: String, running: java.lang.Boolean): Unit = {
+    println("*************######## Conference voiceConfId=" + voiceConfId + " running=" + running)
+    val header = BbbCoreVoiceConfHeader(VoiceConfRunningEvtMsg.NAME, voiceConfId)
+    val body = VoiceConfRunningEvtMsgBody(voiceConfId, running.booleanValue())
+    val envelope = BbbCoreEnvelope(VoiceConfRunningEvtMsg.NAME, Map("voiceConf" -> voiceConfId))
+
+    val msg = new VoiceConfRunningEvtMsg(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) {
 
diff --git a/bbb-common-message/src/main/scala/org/bigbluebutton/common2/msgs/VoiceConfMsgs.scala b/bbb-common-message/src/main/scala/org/bigbluebutton/common2/msgs/VoiceConfMsgs.scala
index d2de5ec711..9521dad5fd 100755
--- a/bbb-common-message/src/main/scala/org/bigbluebutton/common2/msgs/VoiceConfMsgs.scala
+++ b/bbb-common-message/src/main/scala/org/bigbluebutton/common2/msgs/VoiceConfMsgs.scala
@@ -228,6 +228,15 @@ case class MeetingMutedEvtMsgBody(muted: Boolean, mutedBy: String)
                                                    callerNum: String, muted: Boolean,
                                                    talking: Boolean, callingWith: String, listenOnly: Boolean)
 
+/**
+  * Received from FS about the conference is running (created, destroyed).
+  */
+object VoiceConfRunningEvtMsg { val NAME = "VoiceConfRunningEvtMsg" }
+case class VoiceConfRunningEvtMsg(header: BbbCoreVoiceConfHeader,
+                                     body: VoiceConfRunningEvtMsgBody) extends VoiceStandardMsg
+case class VoiceConfRunningEvtMsgBody(voiceConf: String, running: Boolean)
+
+
 /**
   * Received from FS that user has left the voice conference.
   */
@@ -305,4 +314,4 @@ case class UserConnectedToGlobalAudioMsgBody(userId: String, name: String)
 object UserDisconnectedFromGlobalAudioMsg { val NAME = "UserDisconnectedFromGlobalAudioMsg" }
 case class UserDisconnectedFromGlobalAudioMsg(header: BbbCoreVoiceConfHeader,
                                               body: UserDisconnectedFromGlobalAudioMsgBody) extends VoiceStandardMsg
-case class UserDisconnectedFromGlobalAudioMsgBody(userId: String, name: String)
\ No newline at end of file
+case class UserDisconnectedFromGlobalAudioMsgBody(userId: String, name: String)
diff --git a/bbb-fsesl-client/src/main/java/org/freeswitch/esl/client/inbound/Client.java b/bbb-fsesl-client/src/main/java/org/freeswitch/esl/client/inbound/Client.java
index 577aa36f64..482067ed8e 100755
--- a/bbb-fsesl-client/src/main/java/org/freeswitch/esl/client/inbound/Client.java
+++ b/bbb-fsesl-client/src/main/java/org/freeswitch/esl/client/inbound/Client.java
@@ -25,7 +25,7 @@ import java.util.concurrent.ThreadFactory;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
-
+import java.util.Iterator;
 import org.freeswitch.esl.client.IEslEventListener;
 import org.freeswitch.esl.client.internal.IEslProtocolListener;
 import org.freeswitch.esl.client.transport.CommandResponse;
@@ -461,18 +461,36 @@ public class Client
                                     String eventFunc = eventHeaders.get("Event-Calling-Function");
                                     String uniqueId = eventHeaders.get("Caller-Unique-ID");
                                     String confName = eventHeaders.get("Conference-Name");
+                                    String eventAction = eventHeaders.get("Action");
                                     int confSize = Integer.parseInt(eventHeaders.get("Conference-Size"));
+/**
+                                    StringBuilder sb = new StringBuilder("");
+                                    sb.append("\n");
+                                    for (Iterator it = eventHeaders.entrySet().iterator(); it.hasNext(); ) {
+                                        Map.Entry entry = (Map.Entry)it.next();
+                                        sb.append(entry.getKey());
+                                        sb.append(" => '");
+                                        sb.append(entry.getValue());
+                                        sb.append("'\n");
+                                    }
 
-                                    //FIXME: all by Action eventHeader really.... maybe?
-                                    // But this way we filter whole sections of Action events
-                                    if (eventFunc == null) {
+                                    System.out.println("##### Received Event for " + confName);
+                                    System.out.println("##### " + sb.toString());
+**/
+                                    if (eventFunc == null || eventAction == null) {
                                         //Noop...
+                                    } else if (eventAction.equals("conference-create")) {
+                                        listener.conferenceEventAction(uniqueId, confName, confSize, eventAction, event);
+                                        return;
+                                    } else if (eventAction.equals("conference-destroy")) {
+                                        listener.conferenceEventAction(uniqueId, confName, confSize, eventAction, event);
+                                        return;
                                     } else if (eventFunc.equals("conference_thread_run")) {
-                                    	System.out.println("##### Client conference_thread_run");
+                                        System.out.println("##### Client conference_thread_run");
                                         listener.conferenceEventThreadRun(uniqueId, confName, confSize, event);
                                         return;
                                     } else if (eventFunc.equals("member_add_file_data")) {
-                                    	System.out.println("##### Client member_add_file_data");
+                                        System.out.println("##### Client member_add_file_data");
                                         listener.conferenceEventPlayFile(uniqueId, confName, confSize, event);
                                         return;
                                     } else if (eventFunc.equals("conf_api_sub_transfer") || eventFunc.equals("conference_api_sub_transfer")) {
@@ -480,11 +498,11 @@ public class Client
                                         listener.conferenceEventTransfer(uniqueId, confName, confSize, event);
                                         return;
                                     } else if (eventFunc.equals("conference_add_member") || eventFunc.equals("conference_member_add")) {
-                                    	System.out.println("##### Client conference_add_member");
+                                        System.out.println("##### Client conference_add_member");
                                         listener.conferenceEventJoin(uniqueId, confName, confSize, event);
                                         return;
                                     } else if (eventFunc.equals("conference_del_member") || eventFunc.equals("conference_member_del")) {
-                                    	System.out.println("##### Client conference_del_member");
+                                        System.out.println("##### Client conference_del_member");
                                         listener.conferenceEventLeave(uniqueId, confName, confSize, event);
                                         return;
                                     } else if (eventFunc.equals("conf_api_sub_mute") || eventFunc.equals("conference_api_sub_mute")) {
@@ -494,19 +512,20 @@ public class Client
                                         listener.conferenceEventUnMute(uniqueId, confName, confSize, event);
                                         return;
                                     } else if (eventFunc.equals("conference_record_thread_run")) {
-                                    	System.out.println("##### Client conference_record_thread_run");
+                                        System.out.println("##### Client conference_record_thread_run");
                                         listener.conferenceEventRecord(uniqueId, confName, confSize, event);
                                         return;
                                     } else if (eventFunc.equals("conference_loop_input")) {
-                                        listener.conferenceEventAction(uniqueId, confName, confSize, eventHeaders.get("Action"), event);
+                                        listener.conferenceEventAction(uniqueId, confName, confSize, eventAction, event);
                                         return;
                                     } else if (eventFunc.equals("stop_talking_handler")) {
-                                        listener.conferenceEventAction(uniqueId, confName, confSize, eventHeaders.get("Action"), event);
+                                        listener.conferenceEventAction(uniqueId, confName, confSize, eventAction, event);
                                         return;
-                                    } else {
-                        /*              StringBuilder sb = new StringBuilder("");
+                                    }  else {
+                                        /**
+                                      StringBuilder sb = new StringBuilder("");
                                         sb.append("\n");
-                                        for (Iterator it=eventHeaders.entrySet().iterator(); it.hasNext(); ) {
+                                        for (Iterator it = eventHeaders.entrySet().iterator(); it.hasNext(); ) {
                                             Map.Entry entry = (Map.Entry)it.next();
                                             sb.append(entry.getKey());
                                             sb.append(" => '");
@@ -514,11 +533,11 @@ public class Client
                                             sb.append("'\n");
                                         }
                                         log.info ("Unknown Conference Event [{}] [{}]", confName, sb.toString());
-                         */
+                                        System.out.println("##### unhandled Event for " + confName);
+                                        System.out.println("##### " + sb.toString());
+                                         **/
                                     }
                                 }
-
-
                                 listener.eventReceived( event );
                             } catch ( Throwable t ) {
                                 log.error( "Error caught notifying listener of event [" + event + ']', t );
-- 
GitLab