From c14a9460410a53d1b63429ef6516baf4ce024c27 Mon Sep 17 00:00:00 2001
From: Richard Alam <ritzalam@gmail.com>
Date: Thu, 26 Oct 2017 14:07:22 -0700
Subject: [PATCH]  - generate recording path in akka-apps for audio

---
 .../src/main/resources/application.conf       |  4 ++++
 .../bigbluebutton/SystemConfiguration.scala   |  2 ++
 .../voice/UserJoinedVoiceConfEvtMsgHdlr.scala | 12 +++++++----
 .../core/apps/voice/VoiceApp.scala            | 15 ++++++++++++--
 .../senders/ReceivedJsonMsgHandlerActor.scala |  2 ++
 .../core/record/events/RecordEvent.scala      |  4 +++-
 .../core/running/MeetingActor.scala           |  7 +++++--
 .../core/running/MeetingActorAudit.scala      |  4 ++++
 .../core2/message/senders/MsgBuilder.scala    |  4 ++--
 .../core2/voiceconf/VoiceConfActor.scala      | 20 +++++++++++++++++++
 .../freeswitch/FreeswitchApplication.java     |  5 +----
 .../freeswitch/RxJsonMsgDeserializer.scala    |  2 +-
 .../common2/msgs/VoiceConfMsgs.scala          |  2 +-
 13 files changed, 66 insertions(+), 17 deletions(-)
 create mode 100755 akka-bbb-apps/src/main/scala/org/bigbluebutton/core2/voiceconf/VoiceConfActor.scala

diff --git a/akka-bbb-apps/src/main/resources/application.conf b/akka-bbb-apps/src/main/resources/application.conf
index d7c9e9de65..4de5614cf6 100755
--- a/akka-bbb-apps/src/main/resources/application.conf
+++ b/akka-bbb-apps/src/main/resources/application.conf
@@ -82,4 +82,8 @@ services {
 
 apps {
   checkPermissions = true
+}
+
+voiceConf {
+  recordPath = "/var/freeswitch/meetings"
 }
\ No newline at end of file
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/SystemConfiguration.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/SystemConfiguration.scala
index fc33700250..840843e845 100755
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/SystemConfiguration.scala
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/SystemConfiguration.scala
@@ -61,4 +61,6 @@ trait SystemConfiguration {
   lazy val telizePort = Try(config.getInt("services.telizePort")).getOrElse(80)
 
   lazy val applyPermissionCheck = Try(config.getBoolean("apps.checkPermissions")).getOrElse(false)
+
+  lazy val voiceConfRecordPath = Try(config.getString("voiceConf.recordPath")).getOrElse("/var/freeswitch/meetings")
 }
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/voice/UserJoinedVoiceConfEvtMsgHdlr.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/voice/UserJoinedVoiceConfEvtMsgHdlr.scala
index 7c262c2bc7..8b1c4cdf49 100755
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/voice/UserJoinedVoiceConfEvtMsgHdlr.scala
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/voice/UserJoinedVoiceConfEvtMsgHdlr.scala
@@ -1,13 +1,15 @@
 package org.bigbluebutton.core.apps.voice
 
+import org.bigbluebutton.SystemConfiguration
 import org.bigbluebutton.common2.msgs._
 import org.bigbluebutton.core.apps.breakout.BreakoutHdlrHelpers
 import org.bigbluebutton.core.models.{ VoiceUserState, VoiceUsers }
 import org.bigbluebutton.core.running.{ BaseMeetingActor, LiveMeeting, OutMsgRouter }
+import org.bigbluebutton.core.util.TimeUtil
 import org.bigbluebutton.core2.MeetingStatus2x
 import org.bigbluebutton.core2.message.senders.MsgBuilder
 
-trait UserJoinedVoiceConfEvtMsgHdlr extends BreakoutHdlrHelpers {
+trait UserJoinedVoiceConfEvtMsgHdlr extends BreakoutHdlrHelpers with SystemConfiguration {
   this: BaseMeetingActor =>
 
   val liveMeeting: LiveMeeting
@@ -62,9 +64,11 @@ trait UserJoinedVoiceConfEvtMsgHdlr extends BreakoutHdlrHelpers {
       liveMeeting.props.recordProp.record &&
       !MeetingStatus2x.isVoiceRecording(liveMeeting.status)) {
 
-      log.info("Send START RECORDING voice conf. meetingId=" + liveMeeting.props.meetingProp.intId
-        + " voice conf=" + liveMeeting.props.voiceProp.voiceConf)
-      VoiceApp.startRecordingVoiceConference(liveMeeting, outGW)
+      val meetingId = liveMeeting.props.meetingProp.intId
+      val recordFile = VoiceApp.genRecordPath(voiceConfRecordPath, meetingId, TimeUtil.timeNowInMs())
+      log.info("Send START RECORDING voice conf. meetingId=" + meetingId + " voice conf=" + liveMeeting.props.voiceProp.voiceConf)
+
+      VoiceApp.startRecordingVoiceConference(liveMeeting, outGW, recordFile)
     } else {
       log.info("Not recording audio as numVoiceUsers={} and isRecording={} and recordProp={}", numVoiceUsers,
         MeetingStatus2x.isVoiceRecording(liveMeeting.status), liveMeeting.props.recordProp.record)
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/voice/VoiceApp.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/voice/VoiceApp.scala
index 2d4dc81352..bc56c5163e 100755
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/voice/VoiceApp.scala
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/apps/voice/VoiceApp.scala
@@ -1,16 +1,27 @@
 package org.bigbluebutton.core.apps.voice
 
+import java.io.File
+
 import org.bigbluebutton.core.running.{ LiveMeeting, OutMsgRouter }
 import org.bigbluebutton.core2.MeetingStatus2x
 import org.bigbluebutton.core2.message.senders.MsgBuilder
 
 object VoiceApp {
 
-  def startRecordingVoiceConference(liveMeeting: LiveMeeting, outGW: OutMsgRouter): Unit = {
+  def genRecordPath(recordDir: String, meetingId: String, timestamp: Long): String = {
+    if (recordDir.endsWith("/")) {
+      recordDir.concat(meetingId).concat("-").concat(timestamp.toString).concat(".wav")
+    } else {
+      recordDir.concat("/").concat(meetingId).concat("-").concat(timestamp.toString).concat(".wav")
+    }
+  }
+
+  def startRecordingVoiceConference(liveMeeting: LiveMeeting, outGW: OutMsgRouter, stream: String): Unit = {
     MeetingStatus2x.startRecordingVoice(liveMeeting.status)
     val event = MsgBuilder.buildStartRecordingVoiceConfSysMsg(
       liveMeeting.props.meetingProp.intId,
-      liveMeeting.props.voiceProp.voiceConf
+      liveMeeting.props.voiceProp.voiceConf,
+      stream
     )
     outGW.send(event)
   }
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 26c19d2110..0d79d2ab79 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
@@ -136,6 +136,8 @@ class ReceivedJsonMsgHandlerActor(
         routeVoiceMsg[UserDisconnectedFromGlobalAudioMsg](envelope, jsonNode)
       case MuteMeetingCmdMsg.NAME =>
         routeGenericMsg[MuteMeetingCmdMsg](envelope, jsonNode)
+      case VoiceConfRunningEvtMsg.NAME =>
+        routeVoiceMsg[VoiceConfRunningEvtMsg](envelope, jsonNode)
 
       // Breakout rooms
       case BreakoutRoomsListMsg.NAME =>
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/record/events/RecordEvent.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/record/events/RecordEvent.scala
index eb85c6584b..e9057b505f 100755
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/record/events/RecordEvent.scala
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/record/events/RecordEvent.scala
@@ -19,6 +19,7 @@
 
 package org.bigbluebutton.core.record.events
 
+import java.text.SimpleDateFormat
 import java.util.Date
 
 import scala.collection.mutable.HashMap
@@ -34,7 +35,8 @@ trait RecordEvent {
 
   final def timestampUTC(utc: Long): Unit = {
     eventMap.put(TIMESTAMP_UTC, utc.toString)
-    eventMap.put(DATE, (new Date(utc)).toString)
+    val sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX")
+    eventMap.put(DATE, sdf.format(utc))
   }
 
   /**
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 e8d02e70a5..77886b2181 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
@@ -412,14 +412,17 @@ class MeetingActor(
     val now = TimeUtil.timeNowInMs()
     val elapsedInMs = now - lastRecBreakSentOn
     val elapsedInMin = TimeUtil.millisToMinutes(elapsedInMs)
-    println("******************* ElapsedInMS=" + elapsedInMs + ", elapsedInMIN=" + elapsedInMin)
+
     if (elapsedInMin > 1) {
       lastRecBreakSentOn = now
       val event = MsgBuilder.buildRecordingChapterBreakSysMsg(props.meetingProp.intId, TimeUtil.timeNowInMs())
       outGW.send(event)
 
       VoiceApp.stopRecordingVoiceConference(liveMeeting, outGW)
-      VoiceApp.startRecordingVoiceConference(liveMeeting, outGW)
+
+      val meetingId = liveMeeting.props.meetingProp.intId
+      val recordFile = VoiceApp.genRecordPath(voiceConfRecordPath, meetingId, now)
+      VoiceApp.startRecordingVoiceConference(liveMeeting, outGW, recordFile)
 
     }
 
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/MeetingActorAudit.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/MeetingActorAudit.scala
index 64e41437b0..f92d8f5b7e 100755
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/MeetingActorAudit.scala
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core/running/MeetingActorAudit.scala
@@ -1,17 +1,21 @@
 package org.bigbluebutton.core.running
 
 import java.io.{ PrintWriter, StringWriter }
+import java.text.SimpleDateFormat
+import java.util.Date
 
 import akka.actor.Actor
 import akka.actor.ActorLogging
 import akka.actor.Props
 import akka.actor.OneForOneStrategy
 import akka.actor.SupervisorStrategy.Resume
+
 import scala.concurrent.duration._
 import org.bigbluebutton.SystemConfiguration
 import org.bigbluebutton.common2.domain.DefaultProps
 import org.bigbluebutton.core.api._
 import org.bigbluebutton.core.bus.{ BigBlueButtonEvent, InternalEventBus }
+
 import scala.concurrent.ExecutionContext.Implicits.global
 
 object MeetingActorAudit {
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core2/message/senders/MsgBuilder.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core2/message/senders/MsgBuilder.scala
index 39ae45662f..8ddf5eb3bd 100755
--- a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core2/message/senders/MsgBuilder.scala
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core2/message/senders/MsgBuilder.scala
@@ -258,11 +258,11 @@ object MsgBuilder {
     BbbCommonEnvCoreMsg(envelope, event)
   }
 
-  def buildStartRecordingVoiceConfSysMsg(meetingId: String, voiceConf: String): BbbCommonEnvCoreMsg = {
+  def buildStartRecordingVoiceConfSysMsg(meetingId: String, voiceConf: String, stream: String): BbbCommonEnvCoreMsg = {
     val routing = collection.immutable.HashMap("sender" -> "bbb-apps-akka")
     val envelope = BbbCoreEnvelope(StartRecordingVoiceConfSysMsg.NAME, routing)
     val header = BbbCoreHeaderWithMeetingId(StartRecordingVoiceConfSysMsg.NAME, meetingId)
-    val body = StartRecordingVoiceConfSysMsgBody(voiceConf, meetingId)
+    val body = StartRecordingVoiceConfSysMsgBody(voiceConf, meetingId, stream)
     val event = StartRecordingVoiceConfSysMsg(header, body)
     BbbCommonEnvCoreMsg(envelope, event)
   }
diff --git a/akka-bbb-apps/src/main/scala/org/bigbluebutton/core2/voiceconf/VoiceConfActor.scala b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core2/voiceconf/VoiceConfActor.scala
new file mode 100755
index 0000000000..a7349f270e
--- /dev/null
+++ b/akka-bbb-apps/src/main/scala/org/bigbluebutton/core2/voiceconf/VoiceConfActor.scala
@@ -0,0 +1,20 @@
+package org.bigbluebutton.core2.voiceconf
+
+import akka.actor.{ Actor, ActorLogging, FSM }
+import org.bigbluebutton.SystemConfiguration
+
+sealed trait VoiceConfState
+case object VoiceConfStarted extends VoiceConfState
+case object StartRecording extends VoiceConfState
+case object RecordingStarted extends VoiceConfState
+case object StopRecording extends VoiceConfState
+case object RecordingStopped extends VoiceConfState
+case object VoiceConfStopped extends VoiceConfState
+
+case class VoiceConfData(record: Boolean, numUsers: Int, streams: Vector[RecordStream])
+case class RecordStream(stream: String, started: Boolean)
+
+class VoiceConfActor extends Actor with ActorLogging with FSM[VoiceConfState, VoiceConfData] with SystemConfiguration {
+
+}
+
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
index dcfc6274f1..f8eaf52bc8 100755
--- 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
@@ -114,10 +114,7 @@ public class FreeswitchApplication {
     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";
-
+  public void startRecording(String voiceConfId, String meetingid, String voicePath) {
     RecordConferenceCommand rcc = new RecordConferenceCommand(voiceConfId, USER, true, voicePath);
     queueMessage(rcc);
   }
diff --git a/akka-bbb-fsesl/src/main/scala/org/bigbluebutton/freeswitch/RxJsonMsgDeserializer.scala b/akka-bbb-fsesl/src/main/scala/org/bigbluebutton/freeswitch/RxJsonMsgDeserializer.scala
index 67e34b23df..7e69fdbdc1 100755
--- a/akka-bbb-fsesl/src/main/scala/org/bigbluebutton/freeswitch/RxJsonMsgDeserializer.scala
+++ b/akka-bbb-fsesl/src/main/scala/org/bigbluebutton/freeswitch/RxJsonMsgDeserializer.scala
@@ -149,7 +149,7 @@ trait RxJsonMsgDeserializer {
     for {
       m <- deserialize(jsonNode)
     } yield {
-      fsApp.startRecording(m.body.voiceConf, m.body.meetingId)
+      fsApp.startRecording(m.body.voiceConf, m.body.meetingId, m.body.stream)
     }
   }
 
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 9521dad5fd..69565b9eed 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
@@ -191,7 +191,7 @@ case class MeetingMutedEvtMsgBody(muted: Boolean, mutedBy: String)
   object StartRecordingVoiceConfSysMsg { val NAME = "StartRecordingVoiceConfSysMsg" }
   case class StartRecordingVoiceConfSysMsg(header: BbbCoreHeaderWithMeetingId,
                                         body: StartRecordingVoiceConfSysMsgBody) extends BbbCoreMsg
-  case class StartRecordingVoiceConfSysMsgBody(voiceConf: String, meetingId: String)
+  case class StartRecordingVoiceConfSysMsgBody(voiceConf: String, meetingId: String, stream: String)
 
 /**
   * Sent to FS to stop recording voice conference.
-- 
GitLab