Merge pull request #5449 from pedrobmarin/multiple-playbacks

Grouping playbacks inside the same recording
This commit is contained in:
Fred Dixon 2018-05-04 17:52:56 -04:00 committed by GitHub
commit 00efd4770a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 155 additions and 3 deletions

View File

@ -1,6 +1,7 @@
package org.bigbluebutton.api2.domain
import scala.collection.JavaConverters._
import scala.collection.mutable.ListBuffer
import java.util.Map
import scala.xml.{Elem, NodeSeq}
@ -368,6 +369,27 @@ case class RecMetaPlayback(format: String, link: String, processingTime: Int,
<playback>{buffer}</playback>
}
// Merged playback formats when responding to get recordings API call
def toFormatXml(): Elem = {
val buffer = new scala.xml.NodeBuffer
val formatElem = <type>{format}</type>
val urlElem = <url>{link}</url>
val processTimeElem = <processingTime>{processingTime}</processingTime>
val lengthElem = <length>{duration / 60000}</length>
buffer += formatElem
buffer += urlElem
buffer += processTimeElem
buffer += lengthElem
extensions foreach {ext =>
ext.head.child foreach {child =>
buffer += child
}
}
<format>{buffer}</format>
}
}
@ -390,3 +412,92 @@ case class RecMetaBreakout(parentId: String, sequence: Int, meetingId: String) {
<breakout parentMeetingId={parentId} sequence={sequence.toString} meetingId={meetingId}/>
}
}
// A simple mask to merge multiple playback formats of the same recording
case class RecMetaResponse(
id: String,
meetingId: String,
internalMeetingId: Option[String],
meetingName: String,
state: String,
published: Boolean,
startTime: Long,
endTime: Long,
participants: Int,
rawSize: Long,
isBreakout: Boolean,
meeting: Option[RecMetaMeeting],
meta: Option[collection.immutable.Map[String, String]],
playbacks: ListBuffer[RecMetaPlayback],
breakout: Option[RecMetaBreakout],
breakoutRooms: Vector[String]) {
// Link a new playback if it exists
def updateRecMeta(r: RecMeta): RecMetaResponse = {
r.playback match {
case Some(p) => this.playbacks += p
case None =>
}
this
}
def toXml(): Elem = {
def metaToElem(map: scala.collection.immutable.Map[String, String]): Elem = {
val buffer = new scala.xml.NodeBuffer
map.foreach {case (key, value) =>
// Need to escape value otherwise loadString would choke.
val m = "<" + key + ">" + xml.Utility.escape(value) + "</" + key + ">"
buffer += scala.xml.XML.loadString(m)
}
<metadata>{buffer}</metadata>
}
def breakoutRoomsToElem(rooms: Vector[String]): Elem = {
val buffer = new scala.xml.NodeBuffer
rooms foreach(r => buffer += <breakoutRoom>{r}</breakoutRoom>)
<breakoutRooms>{buffer}</breakoutRooms>
}
val recordIdElem = <recordID>{id}</recordID>
val meetingIdElem = <meetingID>{meetingId}</meetingID>
val meetingNameElem = <name>{meetingName}</name>
val internalId = internalMeetingId match {
case Some(intId) => Some(<internalMeetingID>{intId}</internalMeetingID>)
case None => None
}
val isBreakoutElem = <isBreakout>{isBreakout}</isBreakout>
val publishedElem = <published>{published}</published>
val stateElem = <state>{state}</state>
val startTimeElem = <startTime>{startTime}</startTime>
val endTimeElem = <endTime>{endTime}</endTime>
val participantsElem = <participants>{participants}</participants>
val buffer = new scala.xml.NodeBuffer
buffer += recordIdElem
buffer += meetingIdElem
internalId foreach(intId => buffer += intId)
buffer += meetingNameElem
buffer += isBreakoutElem
buffer += publishedElem
buffer += stateElem
buffer += startTimeElem
buffer += endTimeElem
buffer += participantsElem
meta foreach (m => buffer += metaToElem(m))
breakout foreach (b => buffer += b.toXml())
if (breakoutRooms.nonEmpty) {
buffer += breakoutRoomsToElem(breakoutRooms)
}
// Iterate over all formats before include the playback tag
val formats = new scala.xml.NodeBuffer
playbacks foreach(p => formats += p.toFormatXml())
val playbackElem = <playback>{formats}</playback>
buffer += playbackElem
<recording>{buffer}</recording>
}
}

View File

@ -6,10 +6,12 @@ import java.util
import org.bigbluebutton.api.domain.RecordingMetadata
import org.bigbluebutton.api2.RecordingServiceGW
import org.bigbluebutton.api2.domain.RecMeta
import org.bigbluebutton.api2.domain.{RecMeta, RecMetaResponse}
import scala.xml.{Elem, PrettyPrinter, XML}
import scala.collection.JavaConverters._
import scala.collection.mutable.{Buffer, ListBuffer, Map}
import scala.collection.Iterable
class RecMetaXmlHelper extends RecordingServiceGW with LogHelper {
@ -79,7 +81,7 @@ class RecMetaXmlHelper extends RecordingServiceGW with LogHelper {
def getRecordings2x(recs: util.ArrayList[RecordingMetadata]): String = {
def toXml(rec: RecMeta): Option[Elem] = {
def toXml(rec: RecMetaResponse): Option[Elem] = {
try {
Some(rec.toXml())
} catch {
@ -90,6 +92,44 @@ class RecMetaXmlHelper extends RecordingServiceGW with LogHelper {
}
}
// Translate a RecMeta to a RecMetaResponse
def createRecMetaResponse(recMeta: RecMeta): RecMetaResponse = {
val recMetaResponse = new RecMetaResponse(
recMeta.id,
recMeta.meetingId,
recMeta.internalMeetingId,
recMeta.meetingName,
recMeta.state,
recMeta.published,
recMeta.startTime,
recMeta.endTime,
recMeta.participants,
recMeta.rawSize,
recMeta.isBreakout,
recMeta.meeting,
recMeta.meta,
recMeta.playback match {
case Some(p) => ListBuffer(p)
case None => ListBuffer()
},
recMeta.breakout,
recMeta.breakoutRooms
)
recMetaResponse
}
// Group up recordings with the same id
def mergeRecMeta(recMeta: Buffer[RecMeta]): Iterable[RecMetaResponse] = {
val resp = Map[String, RecMetaResponse]()
recMeta foreach { rm =>
resp(rm.id) = resp.get(rm.id) match {
case Some(recMetaResponse) => recMetaResponse.updateRecMeta(rm)
case None => createRecMetaResponse(rm)
}
}
resp.values
}
val recMeta = recs.asScala map(r => r.getRecMeta)
if (recMeta.isEmpty) {
val resp =
@ -102,7 +142,8 @@ class RecMetaXmlHelper extends RecordingServiceGW with LogHelper {
resp.toString
} else {
val buffer = new scala.xml.NodeBuffer
recMeta foreach { rm =>
val recMetaResponse = mergeRecMeta(recMeta)
recMetaResponse foreach { rm =>
toXml(rm) foreach (r => buffer += r)
}
val resp =