Merge pull request #3388 from jfederico/extension_preview_for_thumbnails_on_recordings
Extension preview for thumbnails on recordings
This commit is contained in:
commit
ce4ef05c21
@ -865,6 +865,7 @@ class ApiController {
|
|||||||
for (m in mtgs) {
|
for (m in mtgs) {
|
||||||
meeting {
|
meeting {
|
||||||
meetingID() { mkp.yield(m.getExternalId()) }
|
meetingID() { mkp.yield(m.getExternalId()) }
|
||||||
|
internalMeetingID() { mkp.yield(m.getInternalId()) }
|
||||||
isBreakout() { mkp.yield(m.isBreakout()) }
|
isBreakout() { mkp.yield(m.isBreakout()) }
|
||||||
meetingName() { mkp.yield(m.getName()) }
|
meetingName() { mkp.yield(m.getName()) }
|
||||||
createTime(m.getCreateTime())
|
createTime(m.getCreateTime())
|
||||||
@ -2192,6 +2193,7 @@ class ApiController {
|
|||||||
response() {
|
response() {
|
||||||
returncode(RESP_CODE_SUCCESS)
|
returncode(RESP_CODE_SUCCESS)
|
||||||
meetingID() { mkp.yield(meeting.getExternalId()) }
|
meetingID() { mkp.yield(meeting.getExternalId()) }
|
||||||
|
internalMeetingID() { mkp.yield(meeting.getInternalId()) }
|
||||||
attendeePW() { mkp.yield(meeting.getViewerPassword()) }
|
attendeePW() { mkp.yield(meeting.getViewerPassword()) }
|
||||||
moderatorPW() { mkp.yield(meeting.getModeratorPassword()) }
|
moderatorPW() { mkp.yield(meeting.getModeratorPassword()) }
|
||||||
createTime(meeting.getCreateTime())
|
createTime(meeting.getCreateTime())
|
||||||
|
@ -19,12 +19,18 @@
|
|||||||
|
|
||||||
package org.bigbluebutton.api;
|
package org.bigbluebutton.api;
|
||||||
|
|
||||||
|
import groovy.json.JsonBuilder;
|
||||||
import groovy.util.XmlSlurper;
|
import groovy.util.XmlSlurper;
|
||||||
|
import groovy.util.slurpersupport.Attributes;
|
||||||
import groovy.util.slurpersupport.GPathResult;
|
import groovy.util.slurpersupport.GPathResult;
|
||||||
|
import groovy.xml.MarkupBuilder;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.bigbluebutton.api.domain.Extension;
|
||||||
import org.bigbluebutton.api.domain.Recording;
|
import org.bigbluebutton.api.domain.Recording;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@ -44,7 +50,15 @@ public class RecordingServiceHelperImp implements RecordingServiceHelper {
|
|||||||
<processing_time>5429</processing_time>
|
<processing_time>5429</processing_time>
|
||||||
<duration>101014</duration>
|
<duration>101014</duration>
|
||||||
<extension>
|
<extension>
|
||||||
... Any XML element, to be passed through into playback format element.
|
<!-- Any XML element, to be passed through into playback format element. -->
|
||||||
|
<preview> <!-- The first level is the name of the extension -->
|
||||||
|
<text>Instrument Flying</text>
|
||||||
|
<images>
|
||||||
|
<image width="176" height="136" alt="Instrument Flying">http://bbb-server/.../thumb-1.png</image>
|
||||||
|
<image width="176" height="136" alt="Course Structure">http://bbb-server/.../thumb-2.png</image>
|
||||||
|
<image width="176" height="136" alt="Requirements">http://bbb-server/.../thumb-3.png</image>
|
||||||
|
</images>
|
||||||
|
</preview>
|
||||||
</extension>
|
</extension>
|
||||||
</playback>
|
</playback>
|
||||||
<meta>
|
<meta>
|
||||||
@ -59,7 +73,7 @@ public class RecordingServiceHelperImp implements RecordingServiceHelper {
|
|||||||
public void writeRecordingInfo(String path, Recording info) {
|
public void writeRecordingInfo(String path, Recording info) {
|
||||||
def writer = new StringWriter()
|
def writer = new StringWriter()
|
||||||
def builder = new groovy.xml.MarkupBuilder(writer)
|
def builder = new groovy.xml.MarkupBuilder(writer)
|
||||||
def metadataXml = builder.recording {
|
builder.recording {
|
||||||
builder.id(info.getId())
|
builder.id(info.getId())
|
||||||
builder.state(info.getState())
|
builder.state(info.getState())
|
||||||
builder.published(info.isPublished())
|
builder.published(info.isPublished())
|
||||||
@ -72,7 +86,17 @@ public class RecordingServiceHelperImp implements RecordingServiceHelper {
|
|||||||
builder.format(info.getPlaybackFormat())
|
builder.format(info.getPlaybackFormat())
|
||||||
builder.link(info.getPlaybackLink())
|
builder.link(info.getPlaybackLink())
|
||||||
builder.duration(info.getPlaybackDuration())
|
builder.duration(info.getPlaybackDuration())
|
||||||
builder.extension(info.getPlaybackExtensions())
|
def extensions = info.getPlaybackExtensions()
|
||||||
|
if ( !extensions.isEmpty() ) {
|
||||||
|
builder.extensions {
|
||||||
|
extensions.each { extension ->
|
||||||
|
def extensionType = extension.getType()
|
||||||
|
builder."${extensionType}"{
|
||||||
|
extensionPropertiesToXML(builder, extension.getProperties())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Map<String,String> metainfo = info.getMetadata();
|
Map<String,String> metainfo = info.getMetadata();
|
||||||
@ -92,7 +116,7 @@ public class RecordingServiceHelperImp implements RecordingServiceHelper {
|
|||||||
File file = new File(dir.getPath() + File.separatorChar + "metadata.xml");
|
File file = new File(dir.getPath() + File.separatorChar + "metadata.xml");
|
||||||
if ( file ) {
|
if ( file ) {
|
||||||
def recording = new XmlSlurper().parse(file);
|
def recording = new XmlSlurper().parse(file);
|
||||||
return getInfo(recording);
|
return getInfo(recording);
|
||||||
}
|
}
|
||||||
} catch ( FileNotFoundException e) {
|
} catch ( FileNotFoundException e) {
|
||||||
// Do nothing, just return null
|
// Do nothing, just return null
|
||||||
@ -105,6 +129,7 @@ public class RecordingServiceHelperImp implements RecordingServiceHelper {
|
|||||||
|
|
||||||
private Recording getInfo(GPathResult rec) {
|
private Recording getInfo(GPathResult rec) {
|
||||||
Recording r = new Recording();
|
Recording r = new Recording();
|
||||||
|
//Add basic information
|
||||||
r.setId(rec.id.text());
|
r.setId(rec.id.text());
|
||||||
r.setState(rec.state.text());
|
r.setState(rec.state.text());
|
||||||
r.setPublished(Boolean.parseBoolean(rec.published.text()));
|
r.setPublished(Boolean.parseBoolean(rec.published.text()));
|
||||||
@ -116,11 +141,14 @@ public class RecordingServiceHelperImp implements RecordingServiceHelper {
|
|||||||
r.setPlaybackDuration(rec.playback.duration.text());
|
r.setPlaybackDuration(rec.playback.duration.text());
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
//Add extensions
|
||||||
Commenting this out to see if this is causing memory to hang around resulting in
|
List<Extension> extensions = new ArrayList<Extension>()
|
||||||
OOM in tomcat7 (ralam july 23, 2015)
|
rec.playback.extensions.children().each { extension ->
|
||||||
r.setPlaybackExtensions(rec.playback.extension.children());
|
extensions.add( new Extension(extension.name(), extensionPropertiesToMap(extension)) )
|
||||||
*/
|
}
|
||||||
|
r.setPlaybackExtensions(extensions)
|
||||||
|
|
||||||
|
//Add metadata
|
||||||
Map<String, String> meta = new HashMap<String, String>();
|
Map<String, String> meta = new HashMap<String, String>();
|
||||||
rec.meta.children().each { anode ->
|
rec.meta.children().each { anode ->
|
||||||
meta.put(anode.name().toString(), anode.text().toString());
|
meta.put(anode.name().toString(), anode.text().toString());
|
||||||
@ -129,4 +157,93 @@ public class RecordingServiceHelperImp implements RecordingServiceHelper {
|
|||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Map<String, ?> processNode( Map<String, ?> map, node) {
|
||||||
|
if ( !map[node.name()] ) {
|
||||||
|
map[node.name()] = map.getClass().newInstance()
|
||||||
|
}
|
||||||
|
Map<String, ?> nodeMap = map[node.name()]
|
||||||
|
node.children().each { it ->
|
||||||
|
if (it.children().size() == 0) {
|
||||||
|
processLeaf( nodeMap, it)
|
||||||
|
} else {
|
||||||
|
processNode( nodeMap, it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nodeMap
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, ?> processLeaf(Map<String, ?> map, node) {
|
||||||
|
//Initialize map for node content
|
||||||
|
Map<String, ?> nodeContent = [ : ]
|
||||||
|
//Assign node content text
|
||||||
|
nodeContent["text"] = node.text()
|
||||||
|
//Assign node content attributes (if any)
|
||||||
|
Map attributes = node.attributes()
|
||||||
|
if( attributes.size() > 0 ) {
|
||||||
|
nodeContent["attributes"] = [ : ]
|
||||||
|
attributes.each { attribute ->
|
||||||
|
nodeContent["attributes"][attribute.getKey()] = attribute.getValue()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//Add content to the node
|
||||||
|
if ( map[node.name()] == null ) {
|
||||||
|
map[node.name()] = nodeContent
|
||||||
|
} else {
|
||||||
|
if ( ! (map[node.name()] instanceof List) ) {
|
||||||
|
map[node.name()] = [ map[node.name()] ]
|
||||||
|
}
|
||||||
|
map[node.name()] << nodeContent
|
||||||
|
}
|
||||||
|
map
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, ?> extensionPropertiesToMap(GPathResult xml) {
|
||||||
|
Map<String, ?> map = [ : ]
|
||||||
|
xml.children().each {
|
||||||
|
if ( it.children().size() == 0 ) {
|
||||||
|
processLeaf(map, it)
|
||||||
|
} else {
|
||||||
|
processNode(map, it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
map
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processMap(builder, node) {
|
||||||
|
node.each { key, value ->
|
||||||
|
if ( value instanceof Collection ) {
|
||||||
|
processCollection(builder, key, value)
|
||||||
|
} else if ( value instanceof Map ) {
|
||||||
|
if ( value.containsKey("text") && value.containsKey("attributes") ) {
|
||||||
|
builder."${key}"(value["attributes"], value["text"])
|
||||||
|
} else {
|
||||||
|
builder."${key}" {
|
||||||
|
processMap(builder, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
builder."${key}"(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processCollection(builder, nodesKey, nodes) {
|
||||||
|
nodes.each { node ->
|
||||||
|
processMap(builder, [ "${nodesKey}" : node ])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void extensionPropertiesToXML(builder, properties) {
|
||||||
|
properties.each { propertyKey, propertyValue ->
|
||||||
|
if ( propertyValue instanceof Collection ) {
|
||||||
|
builder."${propertyKey}" {
|
||||||
|
processCollection(builder, propertyKey, propertyValue)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
builder."${propertyKey}" {
|
||||||
|
processMap(builder, propertyValue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -401,10 +401,8 @@ public class MeetingService implements MessageListener {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, Recording> getRecordings(List<String> idList,
|
public Map<String, Recording> getRecordings(List<String> idList, List<String> states) {
|
||||||
List<String> states) {
|
List<Recording> recsList = recordingService.getRecordings(idList, states);
|
||||||
List<Recording> recsList = recordingService.getRecordings(idList,
|
|
||||||
states);
|
|
||||||
Map<String, Recording> recs = reorderRecordings(recsList);
|
Map<String, Recording> recs = reorderRecordings(recsList);
|
||||||
return recs;
|
return recs;
|
||||||
}
|
}
|
||||||
@ -412,8 +410,7 @@ public class MeetingService implements MessageListener {
|
|||||||
public Map<String, Recording> filterRecordingsByMetadata(
|
public Map<String, Recording> filterRecordingsByMetadata(
|
||||||
Map<String, Recording> recordings,
|
Map<String, Recording> recordings,
|
||||||
Map<String, String> metadataFilters) {
|
Map<String, String> metadataFilters) {
|
||||||
return recordingService.filterRecordingsByMetadata(recordings,
|
return recordingService.filterRecordingsByMetadata(recordings, metadataFilters);
|
||||||
metadataFilters);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, Recording> reorderRecordings(List<Recording> olds) {
|
public Map<String, Recording> reorderRecordings(List<Recording> olds) {
|
||||||
@ -430,9 +427,8 @@ public class MeetingService implements MessageListener {
|
|||||||
List<Playback> plays = new ArrayList<Playback>();
|
List<Playback> plays = new ArrayList<Playback>();
|
||||||
|
|
||||||
if (r.getPlaybackFormat() != null) {
|
if (r.getPlaybackFormat() != null) {
|
||||||
plays.add(new Playback(r.getPlaybackFormat(), r
|
plays.add(new Playback(r.getPlaybackFormat(), r.getPlaybackLink(),
|
||||||
.getPlaybackLink(), getDurationRecording(
|
getDurationRecording(r.getPlaybackDuration(), r.getEndTime(),
|
||||||
r.getPlaybackDuration(), r.getEndTime(),
|
|
||||||
r.getStartTime()), r.getPlaybackExtensions()));
|
r.getStartTime()), r.getPlaybackExtensions()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -440,12 +436,9 @@ public class MeetingService implements MessageListener {
|
|||||||
map.put(r.getId(), r);
|
map.put(r.getId(), r);
|
||||||
} else {
|
} else {
|
||||||
Recording rec = map.get(r.getId());
|
Recording rec = map.get(r.getId());
|
||||||
rec.getPlaybacks().add(
|
rec.getPlaybacks().add(new Playback(r.getPlaybackFormat(), r.getPlaybackLink(),
|
||||||
new Playback(r.getPlaybackFormat(),
|
getDurationRecording(r.getPlaybackDuration(), r.getEndTime(),
|
||||||
r.getPlaybackLink(), getDurationRecording(
|
r.getStartTime()), r.getPlaybackExtensions()));
|
||||||
r.getPlaybackDuration(),
|
|
||||||
r.getEndTime(), r.getStartTime()), r
|
|
||||||
.getPlaybackExtensions()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,44 @@
|
|||||||
|
/**
|
||||||
|
* 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.api.domain;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class Extension {
|
||||||
|
private String type;
|
||||||
|
private Map<String,Object> properties;
|
||||||
|
|
||||||
|
public Extension(String type, Map<String,Object> properties) {
|
||||||
|
this.type = type;
|
||||||
|
this.properties = properties;
|
||||||
|
}
|
||||||
|
public String getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
public void setType(String type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
public Map<String,Object> getProperties() {
|
||||||
|
return properties;
|
||||||
|
}
|
||||||
|
public void setProperties(Map<String,Object> properties) {
|
||||||
|
this.properties = properties;
|
||||||
|
}
|
||||||
|
}
|
@ -18,15 +18,16 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
package org.bigbluebutton.api.domain;
|
package org.bigbluebutton.api.domain;
|
||||||
import groovy.util.slurpersupport.GPathResult;
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public class Playback {
|
public class Playback {
|
||||||
private String format;
|
private String format;
|
||||||
private String url;
|
private String url;
|
||||||
private int length;
|
private int length;
|
||||||
private GPathResult extensions;
|
private List<Extension> extensions;
|
||||||
|
|
||||||
public Playback(String format, String url, int length, GPathResult extensions) {
|
public Playback(String format, String url, int length, List<Extension> extensions) {
|
||||||
this.format = format;
|
this.format = format;
|
||||||
this.url = url;
|
this.url = url;
|
||||||
this.length = length;
|
this.length = length;
|
||||||
@ -50,11 +51,10 @@ public class Playback {
|
|||||||
public void setLength(int length) {
|
public void setLength(int length) {
|
||||||
this.length = length;
|
this.length = length;
|
||||||
}
|
}
|
||||||
public GPathResult getExtensions() {
|
public List<Extension> getExtensions() {
|
||||||
return extensions;
|
return extensions;
|
||||||
}
|
}
|
||||||
public void setExtensions(GPathResult extensions) {
|
public void setExtensions(List<Extension> extensions) {
|
||||||
this.extensions = extensions;
|
this.extensions = extensions;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -27,8 +27,6 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
|
|
||||||
import groovy.util.slurpersupport.GPathResult;
|
|
||||||
|
|
||||||
public class Recording {
|
public class Recording {
|
||||||
private String id;
|
private String id;
|
||||||
private String meetingID;
|
private String meetingID;
|
||||||
@ -44,16 +42,16 @@ public class Recording {
|
|||||||
private String playbackLink;
|
private String playbackLink;
|
||||||
private String playbackFormat;
|
private String playbackFormat;
|
||||||
private String playbackDuration;
|
private String playbackDuration;
|
||||||
private GPathResult playbackExtensions;
|
private List<Extension> playbackExtensions;
|
||||||
|
|
||||||
public static final String STATE_PROCESSING = "processing";
|
public static final String STATE_PROCESSING = "processing";
|
||||||
public static final String STATE_PROCESSED = "processed";
|
public static final String STATE_PROCESSED = "processed";
|
||||||
public static final String STATE_PUBLISING = "publishing";
|
public static final String STATE_PUBLISING = "publishing";
|
||||||
public static final String STATE_PUBLISHED = "published";
|
public static final String STATE_PUBLISHED = "published";
|
||||||
public static final String STATE_UNPUBLISING = "unpublishing";
|
public static final String STATE_UNPUBLISING = "unpublishing";
|
||||||
public static final String STATE_UNPUBLISHED = "unpublished";
|
public static final String STATE_UNPUBLISHED = "unpublished";
|
||||||
public static final String STATE_DELETING = "deleting";
|
public static final String STATE_DELETING = "deleting";
|
||||||
public static final String STATE_DELETED = "deleted";
|
public static final String STATE_DELETED = "deleted";
|
||||||
|
|
||||||
public String getId() {
|
public String getId() {
|
||||||
return id;
|
return id;
|
||||||
@ -123,11 +121,11 @@ public class Recording {
|
|||||||
this.playbackDuration = playbackDuration;
|
this.playbackDuration = playbackDuration;
|
||||||
}
|
}
|
||||||
|
|
||||||
public GPathResult getPlaybackExtensions() {
|
public List<Extension> getPlaybackExtensions() {
|
||||||
return playbackExtensions;
|
return playbackExtensions;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPlaybackExtensions(GPathResult playbackExtensions) {
|
public void setPlaybackExtensions(List<Extension> playbackExtensions) {
|
||||||
this.playbackExtensions = playbackExtensions;
|
this.playbackExtensions = playbackExtensions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,7 +28,31 @@
|
|||||||
<type>${p.getFormat()}</type>
|
<type>${p.getFormat()}</type>
|
||||||
<url>${p.getUrl()}</url>
|
<url>${p.getUrl()}</url>
|
||||||
<length>${p.getLength()}</length>
|
<length>${p.getLength()}</length>
|
||||||
<#-- Missing p.getExtensions() -->
|
<#if p.getExtensions()??>
|
||||||
|
<#list p.getExtensions() as extension>
|
||||||
|
<${extension.getType()}>
|
||||||
|
<#assign properties = extension.getProperties()>
|
||||||
|
<#if extension.getType() == "preview">
|
||||||
|
<#list properties?keys as property>
|
||||||
|
<#if property == "images">
|
||||||
|
<${property}>
|
||||||
|
<#if properties[property]["image"]?? && properties[property]["image"]?is_hash>
|
||||||
|
<#assign image = properties[property]["image"]>
|
||||||
|
<image <#if image["attributes"]?? && image["attributes"]["width"]??>width="${image["attributes"]["width"]}"</#if> <#if image["attributes"]?? && image["attributes"]["height"]??>height="${image["attributes"]["height"]}"</#if> <#if image["attributes"]?? && image["attributes"]["alt"]??>alt="${image["attributes"]["alt"]}"</#if>>${image["text"]}</image>
|
||||||
|
<#elseif properties[property]["image"]?is_enumerable>
|
||||||
|
<#list properties[property]["image"] as image>
|
||||||
|
<image <#if image["attributes"]?? && image["attributes"]["width"]??>width="${image["attributes"]["width"]}"</#if> <#if image["attributes"]?? && image["attributes"]["height"]??>height="${image["attributes"]["height"]}"</#if> <#if image["attributes"]?? && image["attributes"]["alt"]??>alt="${image["attributes"]["alt"]}"</#if>>${image["text"]}</image>
|
||||||
|
</#list>
|
||||||
|
</#if>
|
||||||
|
</${property}>
|
||||||
|
<#else>
|
||||||
|
<${property} />
|
||||||
|
</#if>
|
||||||
|
</#list>
|
||||||
|
</#if>
|
||||||
|
</${extension.getType()}>
|
||||||
|
</#list>
|
||||||
|
</#if>
|
||||||
</format>
|
</format>
|
||||||
</#if>
|
</#if>
|
||||||
</#list>
|
</#list>
|
||||||
|
@ -67,12 +67,51 @@ module BigBlueButton
|
|||||||
self.extract_png_page_from_pdf(1, pdf_page, png_out, '800x600')
|
self.extract_png_page_from_pdf(1, pdf_page, png_out, '800x600')
|
||||||
end
|
end
|
||||||
|
|
||||||
#Convert an image to a png
|
# Convert an image to a png
|
||||||
def self.convert_image_to_png(image, png_image, resize = '800x600')
|
def self.convert_image_to_png(image, png_image, resize = '800x600')
|
||||||
BigBlueButton.logger.info("Task: Converting image to .png")
|
BigBlueButton.logger.info("Task: Converting image to .png")
|
||||||
command = "convert #{image} -resize #{resize} -background white -flatten #{png_image}"
|
command = "convert #{image} -resize #{resize} -background white -flatten #{png_image}"
|
||||||
BigBlueButton.execute(command)
|
BigBlueButton.execute(command)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Gathers the text from the slide
|
||||||
|
def self.get_text_from_slide(textfiles_dir, slide_num)
|
||||||
|
text_from_slide = nil
|
||||||
|
if File.file?("#{textfiles_dir}/slide-#{slide_num}.txt")
|
||||||
|
text_from_slide = File.open("#{textfiles_dir}/slide-#{slide_num}.txt") {|f| f.readline}
|
||||||
|
unless text_from_slide == nil
|
||||||
|
text_from_slide = text_from_slide.strip
|
||||||
|
end
|
||||||
|
end
|
||||||
|
text_from_slide
|
||||||
|
end
|
||||||
|
|
||||||
|
# Get from events the presentation that will be used for preview.
|
||||||
|
def self.get_presentation_for_preview(process_dir)
|
||||||
|
events_xml = "#{process_dir}/events.xml"
|
||||||
|
BigBlueButton.logger.info("Task: Getting from events the presentation to be used for preview")
|
||||||
|
presentation = {}
|
||||||
|
doc = Nokogiri::XML(File.open(events_xml))
|
||||||
|
doc.xpath("//event[@eventname='SharePresentationEvent']").each do |presentation_event|
|
||||||
|
# Extract presentation data from events
|
||||||
|
presentation_id = presentation_event.xpath("presentationName").text
|
||||||
|
presentation_filename = presentation_event.xpath("originalFilename").text
|
||||||
|
# Set textfile directory
|
||||||
|
textfiles_dir = "#{process_dir}/presentation/#{presentation_id}/textfiles"
|
||||||
|
# Set presentation hashmap to be returned
|
||||||
|
presentation[:id] = presentation_id
|
||||||
|
presentation[:filename] = presentation_filename
|
||||||
|
presentation[:slides] = {}
|
||||||
|
presentation[:slides][1] = { :alt => self.get_text_from_slide(textfiles_dir, 1) }
|
||||||
|
unless presentation_filename == "default.pdf"
|
||||||
|
presentation[:slides][2] = { :alt => self.get_text_from_slide(textfiles_dir, 2) } if File.file?("#{textfiles_dir}/slide-2.txt")
|
||||||
|
presentation[:slides][3] = { :alt => self.get_text_from_slide(textfiles_dir, 3) } if File.file?("#{textfiles_dir}/slide-3.txt")
|
||||||
|
# Break because something else than default.pdf was found
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
presentation
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
@ -165,6 +165,9 @@ if not FileTest.directory?(target_dir)
|
|||||||
command="convert #{images[0]} -resize 1600x1200 -background white -flatten #{target_pres_dir}/slide-1.png"
|
command="convert #{images[0]} -resize 1600x1200 -background white -flatten #{target_pres_dir}/slide-1.png"
|
||||||
BigBlueButton.execute(command)
|
BigBlueButton.execute(command)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Copy thumbnails from raw files
|
||||||
|
FileUtils.cp_r("#{pres_dir}/thumbnails", "#{target_pres_dir}/thumbnails")
|
||||||
end
|
end
|
||||||
|
|
||||||
BigBlueButton.logger.info("Generating closed captions")
|
BigBlueButton.logger.info("Generating closed captions")
|
||||||
|
@ -1022,12 +1022,25 @@ begin
|
|||||||
playback.remove
|
playback.remove
|
||||||
end
|
end
|
||||||
## Add the actual playback
|
## Add the actual playback
|
||||||
|
presentation = BigBlueButton::Presentation.get_presentation_for_preview("#{$process_dir}")
|
||||||
metadata_with_playback = Nokogiri::XML::Builder.with(metadata.at('recording')) do |xml|
|
metadata_with_playback = Nokogiri::XML::Builder.with(metadata.at('recording')) do |xml|
|
||||||
xml.playback {
|
xml.playback {
|
||||||
xml.format("presentation")
|
xml.format("presentation")
|
||||||
xml.link("#{playback_protocol}://#{playback_host}/playback/presentation/0.9.0/playback.html?meetingId=#{$meeting_id}")
|
xml.link("#{playback_protocol}://#{playback_host}/playback/presentation/0.9.0/playback.html?meetingId=#{$meeting_id}")
|
||||||
xml.processing_time("#{processing_time}")
|
xml.processing_time("#{processing_time}")
|
||||||
xml.duration("#{recording_time}")
|
xml.duration("#{recording_time}")
|
||||||
|
unless presentation.empty?
|
||||||
|
xml.extensions {
|
||||||
|
xml.preview {
|
||||||
|
xml.images {
|
||||||
|
presentation[:slides].each do |key,val|
|
||||||
|
attributes = {:width => "176", :height => "136", :alt => (val[:alt] != nil)? "#{val[:alt]}": ""}
|
||||||
|
xml.image(attributes){ xml.text("#{playback_protocol}://#{playback_host}/presentation/#{$meeting_id}/presentation/#{presentation[:id]}/thumbnails/thumb-#{key}.png") }
|
||||||
|
end
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
## Write the new metadata.xml
|
## Write the new metadata.xml
|
||||||
|
Loading…
Reference in New Issue
Block a user