From 4a6b6c6eec60cac19d09590e6592d067c401240c Mon Sep 17 00:00:00 2001 From: jfederico Date: Thu, 15 Sep 2016 14:03:28 -0400 Subject: [PATCH 01/20] bbb-web Modified domain for adding support to Extensions in recordings --- .../api/RecordingServiceHelperImp.groovy | 65 +++++++++++++++++-- .../org/bigbluebutton/api/MeetingService.java | 23 +++---- .../bigbluebutton/api/domain/Extension.java | 44 +++++++++++++ .../bigbluebutton/api/domain/Playback.java | 12 ++-- .../bigbluebutton/api/domain/Recording.java | 24 ++++--- .../WEB-INF/freemarker/get-recordings.ftl | 23 ++++++- 6 files changed, 150 insertions(+), 41 deletions(-) create mode 100644 bigbluebutton-web/src/java/org/bigbluebutton/api/domain/Extension.java diff --git a/bigbluebutton-web/src/groovy/org/bigbluebutton/api/RecordingServiceHelperImp.groovy b/bigbluebutton-web/src/groovy/org/bigbluebutton/api/RecordingServiceHelperImp.groovy index 55f419f7f9..ff76ae4526 100755 --- a/bigbluebutton-web/src/groovy/org/bigbluebutton/api/RecordingServiceHelperImp.groovy +++ b/bigbluebutton-web/src/groovy/org/bigbluebutton/api/RecordingServiceHelperImp.groovy @@ -20,11 +20,15 @@ package org.bigbluebutton.api; import groovy.util.XmlSlurper; +import groovy.util.slurpersupport.Attributes; import groovy.util.slurpersupport.GPathResult; + import java.io.File; import java.io.FileNotFoundException; import java.util.ArrayList; +import java.util.List; +import org.bigbluebutton.api.domain.Extension; import org.bigbluebutton.api.domain.Recording; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -44,7 +48,18 @@ public class RecordingServiceHelperImp implements RecordingServiceHelper { 5429 101014 - ... Any XML element, to be passed through into playback format element. + + + Introduction to Unit 1 Professor Jones Office Hours are Wedn + + http://example.com/f000057.jpg + http://example.com/f001032.jpg + http://example.com/f002103.jpg + + + + en + @@ -116,11 +131,11 @@ public class RecordingServiceHelperImp implements RecordingServiceHelper { r.setPlaybackDuration(rec.playback.duration.text()); } -/* - Commenting this out to see if this is causing memory to hang around resulting in - OOM in tomcat7 (ralam july 23, 2015) - r.setPlaybackExtensions(rec.playback.extension.children()); -*/ + List extensions = new ArrayList() + rec.playback.extensions.children().each { extension -> + extensions.add( new Extension(extension.name(),parse(extension)) ) + } + r.setPlaybackExtensions(extensions) Map meta = new HashMap(); rec.meta.children().each { anode -> meta.put(anode.name().toString(), anode.text().toString()); @@ -129,4 +144,42 @@ public class RecordingServiceHelperImp implements RecordingServiceHelper { return r; } + private Map processNode( Map map, node) { + if ( !map[node.name()] ) { + map[node.name()] = map.getClass().newInstance() + } + Map nodeMap = map[node.name()] + node.children().each { it -> + if (it.children().size() == 0) { + processLeaf( nodeMap, it) + } else { + processNode( nodeMap, it) + } + } + nodeMap + } + + private Map processLeaf(Map map, node) { + if ( map[node.name()] == null) { + map[node.name()] = node.text() + } else { + if ( ! (map[node.name()] instanceof List) ) { + map[node.name()] = [ map[node.name()] ] + } + map[node.name()] << node.text() + } + map + } + + private Map parse(GPathResult xml) { + Map map = [ : ] + xml.children().each { + if ( it.children().size() == 0 ) { + processLeaf(map, it) + } else { + processNode(map, it) + } + } + map + } } diff --git a/bigbluebutton-web/src/java/org/bigbluebutton/api/MeetingService.java b/bigbluebutton-web/src/java/org/bigbluebutton/api/MeetingService.java index 9864fa4a2f..40ba0af0e1 100755 --- a/bigbluebutton-web/src/java/org/bigbluebutton/api/MeetingService.java +++ b/bigbluebutton-web/src/java/org/bigbluebutton/api/MeetingService.java @@ -394,10 +394,8 @@ public class MeetingService implements MessageListener { return null; } - public Map getRecordings(List idList, - List states) { - List recsList = recordingService.getRecordings(idList, - states); + public Map getRecordings(List idList, List states) { + List recsList = recordingService.getRecordings(idList, states); Map recs = reorderRecordings(recsList); return recs; } @@ -405,8 +403,7 @@ public class MeetingService implements MessageListener { public Map filterRecordingsByMetadata( Map recordings, Map metadataFilters) { - return recordingService.filterRecordingsByMetadata(recordings, - metadataFilters); + return recordingService.filterRecordingsByMetadata(recordings, metadataFilters); } public Map reorderRecordings(List olds) { @@ -423,9 +420,8 @@ public class MeetingService implements MessageListener { List plays = new ArrayList(); if (r.getPlaybackFormat() != null) { - plays.add(new Playback(r.getPlaybackFormat(), r - .getPlaybackLink(), getDurationRecording( - r.getPlaybackDuration(), r.getEndTime(), + plays.add(new Playback(r.getPlaybackFormat(), r.getPlaybackLink(), + getDurationRecording(r.getPlaybackDuration(), r.getEndTime(), r.getStartTime()), r.getPlaybackExtensions())); } @@ -433,12 +429,9 @@ public class MeetingService implements MessageListener { map.put(r.getId(), r); } else { Recording rec = map.get(r.getId()); - rec.getPlaybacks().add( - new Playback(r.getPlaybackFormat(), - r.getPlaybackLink(), getDurationRecording( - r.getPlaybackDuration(), - r.getEndTime(), r.getStartTime()), r - .getPlaybackExtensions())); + rec.getPlaybacks().add(new Playback(r.getPlaybackFormat(), r.getPlaybackLink(), + getDurationRecording(r.getPlaybackDuration(), r.getEndTime(), + r.getStartTime()), r.getPlaybackExtensions())); } } diff --git a/bigbluebutton-web/src/java/org/bigbluebutton/api/domain/Extension.java b/bigbluebutton-web/src/java/org/bigbluebutton/api/domain/Extension.java new file mode 100644 index 0000000000..d16302a3ae --- /dev/null +++ b/bigbluebutton-web/src/java/org/bigbluebutton/api/domain/Extension.java @@ -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 . +* +*/ + +package org.bigbluebutton.api.domain; + +import java.util.Map; + +public class Extension { + private String type; + private Map attributes; + + public Extension(String type, Map attributes) { + this.type = type; + this.attributes = attributes; + } + public String getType() { + return type; + } + public void setType(String type) { + this.type = type; + } + public Map getAttributes() { + return attributes; + } + public void setAttributes(Map attributes) { + this.attributes = attributes; + } +} diff --git a/bigbluebutton-web/src/java/org/bigbluebutton/api/domain/Playback.java b/bigbluebutton-web/src/java/org/bigbluebutton/api/domain/Playback.java index f847464fe6..73f281ef38 100755 --- a/bigbluebutton-web/src/java/org/bigbluebutton/api/domain/Playback.java +++ b/bigbluebutton-web/src/java/org/bigbluebutton/api/domain/Playback.java @@ -18,15 +18,16 @@ */ package org.bigbluebutton.api.domain; -import groovy.util.slurpersupport.GPathResult; + +import java.util.List; public class Playback { private String format; private String url; private int length; - private GPathResult extensions; + private List extensions; - public Playback(String format, String url, int length, GPathResult extensions) { + public Playback(String format, String url, int length, List extensions) { this.format = format; this.url = url; this.length = length; @@ -50,11 +51,10 @@ public class Playback { public void setLength(int length) { this.length = length; } - public GPathResult getExtensions() { + public List getExtensions() { return extensions; } - public void setExtensions(GPathResult extensions) { + public void setExtensions(List extensions) { this.extensions = extensions; } - } diff --git a/bigbluebutton-web/src/java/org/bigbluebutton/api/domain/Recording.java b/bigbluebutton-web/src/java/org/bigbluebutton/api/domain/Recording.java index 00677818b4..a406111da0 100755 --- a/bigbluebutton-web/src/java/org/bigbluebutton/api/domain/Recording.java +++ b/bigbluebutton-web/src/java/org/bigbluebutton/api/domain/Recording.java @@ -27,8 +27,6 @@ import java.util.List; import java.util.Map; import java.util.TreeMap; -import groovy.util.slurpersupport.GPathResult; - public class Recording { private String id; private String meetingID; @@ -44,16 +42,16 @@ public class Recording { private String playbackLink; private String playbackFormat; private String playbackDuration; - private GPathResult playbackExtensions; + private List playbackExtensions; - public static final String STATE_PROCESSING = "processing"; - public static final String STATE_PROCESSED = "processed"; - public static final String STATE_PUBLISING = "publishing"; - public static final String STATE_PUBLISHED = "published"; - public static final String STATE_UNPUBLISING = "unpublishing"; - public static final String STATE_UNPUBLISHED = "unpublished"; - public static final String STATE_DELETING = "deleting"; - public static final String STATE_DELETED = "deleted"; + public static final String STATE_PROCESSING = "processing"; + public static final String STATE_PROCESSED = "processed"; + public static final String STATE_PUBLISING = "publishing"; + public static final String STATE_PUBLISHED = "published"; + public static final String STATE_UNPUBLISING = "unpublishing"; + public static final String STATE_UNPUBLISHED = "unpublished"; + public static final String STATE_DELETING = "deleting"; + public static final String STATE_DELETED = "deleted"; public String getId() { return id; @@ -123,11 +121,11 @@ public class Recording { this.playbackDuration = playbackDuration; } - public GPathResult getPlaybackExtensions() { + public List getPlaybackExtensions() { return playbackExtensions; } - public void setPlaybackExtensions(GPathResult playbackExtensions) { + public void setPlaybackExtensions(List playbackExtensions) { this.playbackExtensions = playbackExtensions; } diff --git a/bigbluebutton-web/web-app/WEB-INF/freemarker/get-recordings.ftl b/bigbluebutton-web/web-app/WEB-INF/freemarker/get-recordings.ftl index 875267ff44..3fabb55a87 100644 --- a/bigbluebutton-web/web-app/WEB-INF/freemarker/get-recordings.ftl +++ b/bigbluebutton-web/web-app/WEB-INF/freemarker/get-recordings.ftl @@ -28,7 +28,28 @@ ${p.getFormat()} ${p.getUrl()} ${p.getLength()} - <#-- Missing p.getExtensions() --> + <#if p.getExtensions()??> + <#list p.getExtensions() as extension> + <${extension.getType()}> + <#assign attributes = extension.getAttributes()> + <#if extension.getType() == "preview"> + <#list attributes?keys as attribute> + <${attribute}> + <#if attribute == "text"> + ${attributes[attribute]} + <#elseif attribute == "images"> + <#list attributes[attribute]?keys as images> + <#list attributes[attribute][images] as image> + ${image} + + + + + + + + + From 1e092eaff9dbb57aebb20830866129252bd27060 Mon Sep 17 00:00:00 2001 From: jfederico Date: Fri, 16 Sep 2016 12:20:30 -0400 Subject: [PATCH 02/20] Adjusted freemaker template and parser to support attributes on preview extension --- .../api/RecordingServiceHelperImp.groovy | 18 ++++++++++++++++-- .../WEB-INF/freemarker/get-recordings.ftl | 4 ++-- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/bigbluebutton-web/src/groovy/org/bigbluebutton/api/RecordingServiceHelperImp.groovy b/bigbluebutton-web/src/groovy/org/bigbluebutton/api/RecordingServiceHelperImp.groovy index ff76ae4526..43ed9a6345 100755 --- a/bigbluebutton-web/src/groovy/org/bigbluebutton/api/RecordingServiceHelperImp.groovy +++ b/bigbluebutton-web/src/groovy/org/bigbluebutton/api/RecordingServiceHelperImp.groovy @@ -160,13 +160,26 @@ public class RecordingServiceHelperImp implements RecordingServiceHelper { } private Map processLeaf(Map map, node) { + //Initialize map for node content + Map 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()] = node.text() + map[node.name()] = nodeContent } else { if ( ! (map[node.name()] instanceof List) ) { map[node.name()] = [ map[node.name()] ] } - map[node.name()] << node.text() + map[node.name()] << nodeContent } map } @@ -182,4 +195,5 @@ public class RecordingServiceHelperImp implements RecordingServiceHelper { } map } + } diff --git a/bigbluebutton-web/web-app/WEB-INF/freemarker/get-recordings.ftl b/bigbluebutton-web/web-app/WEB-INF/freemarker/get-recordings.ftl index 3fabb55a87..269d296306 100644 --- a/bigbluebutton-web/web-app/WEB-INF/freemarker/get-recordings.ftl +++ b/bigbluebutton-web/web-app/WEB-INF/freemarker/get-recordings.ftl @@ -36,11 +36,11 @@ <#list attributes?keys as attribute> <${attribute}> <#if attribute == "text"> - ${attributes[attribute]} + ${attributes[attribute]["text"]} <#elseif attribute == "images"> <#list attributes[attribute]?keys as images> <#list attributes[attribute][images] as image> - ${image} + ${image["text"]} From a995979ce53c293665943ecdcbc07f7fa3f31d34 Mon Sep 17 00:00:00 2001 From: jfederico Date: Fri, 16 Sep 2016 15:11:58 -0400 Subject: [PATCH 03/20] bbb-web: Refactored Extension converting attributes to properties --- .../org/bigbluebutton/api/domain/Extension.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/bigbluebutton-web/src/java/org/bigbluebutton/api/domain/Extension.java b/bigbluebutton-web/src/java/org/bigbluebutton/api/domain/Extension.java index d16302a3ae..2e6af5ecd6 100644 --- a/bigbluebutton-web/src/java/org/bigbluebutton/api/domain/Extension.java +++ b/bigbluebutton-web/src/java/org/bigbluebutton/api/domain/Extension.java @@ -23,11 +23,11 @@ import java.util.Map; public class Extension { private String type; - private Map attributes; + private Map properties; - public Extension(String type, Map attributes) { + public Extension(String type, Map properties) { this.type = type; - this.attributes = attributes; + this.properties = properties; } public String getType() { return type; @@ -35,10 +35,10 @@ public class Extension { public void setType(String type) { this.type = type; } - public Map getAttributes() { - return attributes; + public Map getProperties() { + return properties; } - public void setAttributes(Map attributes) { - this.attributes = attributes; + public void setProperties(Map properties) { + this.properties = properties; } } From 48fc5d645834a8d78febcff6878ed2bff7841197 Mon Sep 17 00:00:00 2001 From: jfederico Date: Fri, 16 Sep 2016 15:12:27 -0400 Subject: [PATCH 04/20] bbb-web: Fixed issue in freemarker template so get recording support extension preview with one or multiple images --- .../WEB-INF/freemarker/get-recordings.ftl | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/bigbluebutton-web/web-app/WEB-INF/freemarker/get-recordings.ftl b/bigbluebutton-web/web-app/WEB-INF/freemarker/get-recordings.ftl index 269d296306..8ae50f17b3 100644 --- a/bigbluebutton-web/web-app/WEB-INF/freemarker/get-recordings.ftl +++ b/bigbluebutton-web/web-app/WEB-INF/freemarker/get-recordings.ftl @@ -31,20 +31,23 @@ <#if p.getExtensions()??> <#list p.getExtensions() as extension> <${extension.getType()}> - <#assign attributes = extension.getAttributes()> + <#assign properties = extension.getProperties()> <#if extension.getType() == "preview"> - <#list attributes?keys as attribute> - <${attribute}> - <#if attribute == "text"> - ${attributes[attribute]["text"]} - <#elseif attribute == "images"> - <#list attributes[attribute]?keys as images> - <#list attributes[attribute][images] as image> + <#list properties?keys as property> + <${property}> + <#if property == "text"> + ${properties[property]["text"]} + <#elseif property == "images"> + <#if properties[property]["image"]?is_hash> + <#assign image = properties[property]["image"]> + ${image["text"]} + <#elseif properties[property]["image"]?is_enumerable> + <#list properties[property]["image"] as image> ${image["text"]} - + - + From 90108bf29c52d535ae327fb356d64a070f9c69af Mon Sep 17 00:00:00 2001 From: jfederico Date: Mon, 19 Sep 2016 14:52:32 -0400 Subject: [PATCH 05/20] record-and-playback: Include default thumbnails into recordings --- .../presentation/scripts/process/presentation.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/record-and-playback/presentation/scripts/process/presentation.rb b/record-and-playback/presentation/scripts/process/presentation.rb index 1789874979..7d2adbc98a 100755 --- a/record-and-playback/presentation/scripts/process/presentation.rb +++ b/record-and-playback/presentation/scripts/process/presentation.rb @@ -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" BigBlueButton.execute(command) end + + # Copy thumbnails from raw files + FileUtils.cp_r("#{pres_dir}/thumbnails", "#{target_pres_dir}/thumbnails") end BigBlueButton.logger.info("Generating closed captions") From e94fcf8d015e6563de07354a145f0af48ed6b2d3 Mon Sep 17 00:00:00 2001 From: jfederico Date: Mon, 19 Sep 2016 17:40:29 -0400 Subject: [PATCH 06/20] bbb-web: Fixed getRecording freemarker template, it works even if preview images have no attributes --- .../web-app/WEB-INF/freemarker/get-recordings.ftl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bigbluebutton-web/web-app/WEB-INF/freemarker/get-recordings.ftl b/bigbluebutton-web/web-app/WEB-INF/freemarker/get-recordings.ftl index 8ae50f17b3..506d368fe5 100644 --- a/bigbluebutton-web/web-app/WEB-INF/freemarker/get-recordings.ftl +++ b/bigbluebutton-web/web-app/WEB-INF/freemarker/get-recordings.ftl @@ -40,10 +40,10 @@ <#elseif property == "images"> <#if properties[property]["image"]?is_hash> <#assign image = properties[property]["image"]> - ${image["text"]} + width="${image["attributes"]["width"]}" <#if image["attributes"]?? && image["attributes"]["height"]??>height="${image["attributes"]["height"]}">${image["text"]} <#elseif properties[property]["image"]?is_enumerable> <#list properties[property]["image"] as image> - ${image["text"]} + width="${image["attributes"]["width"]}" <#if image["attributes"]?? && image["attributes"]["height"]??>height="${image["attributes"]["height"]}">${image["text"]} From f9d76b473970d0e45fcc25e1f596a34dc13980a4 Mon Sep 17 00:00:00 2001 From: jfederico Date: Mon, 19 Sep 2016 18:09:31 -0400 Subject: [PATCH 07/20] recording-and-playpack: Includes thumbnails as an extension of the playbacks --- .../presentation/scripts/publish/presentation.rb | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/record-and-playback/presentation/scripts/publish/presentation.rb b/record-and-playback/presentation/scripts/publish/presentation.rb index 62964a9a73..08b0402e49 100755 --- a/record-and-playback/presentation/scripts/publish/presentation.rb +++ b/record-and-playback/presentation/scripts/publish/presentation.rb @@ -1022,12 +1022,25 @@ begin playback.remove end ## Add the actual playback + presentations = BigBlueButton::Presentation.get_presentations("#{$process_dir}/events.xml") metadata_with_playback = Nokogiri::XML::Builder.with(metadata.at('recording')) do |xml| xml.playback { xml.format("presentation") xml.link("#{playback_protocol}://#{playback_host}/playback/presentation/0.9.0/playback.html?meetingId=#{$meeting_id}") xml.processing_time("#{processing_time}") xml.duration("#{recording_time}") + if presentations.any? + presentation_id = presentations.first + xml.extensions { + xml.preview { + xml.images { + xml.image("#{playback_protocol}://#{playback_host}/presentation/#{$meeting_id}/presentation/#{presentation_id}/thumbnails/thumb-1.png") + xml.image("#{playback_protocol}://#{playback_host}/presentation/#{$meeting_id}/presentation/#{presentation_id}/thumbnails/thumb-2.png") + xml.image("#{playback_protocol}://#{playback_host}/presentation/#{$meeting_id}/presentation/#{presentation_id}/thumbnails/thumb-3.png") + } + } + } + end } end ## Write the new metadata.xml From 45ba7d85c2048e283f4a9b5245bdd1b41b48c024 Mon Sep 17 00:00:00 2001 From: jfederico Date: Tue, 20 Sep 2016 14:10:28 -0400 Subject: [PATCH 08/20] record-and-playback: Filtered presentation files to provide only the first thumbnail for default.pdf --- .../recordandplayback/generators/presentation.rb | 13 +++++++++++++ .../presentation/scripts/publish/presentation.rb | 16 ++++++++++------ 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/record-and-playback/core/lib/recordandplayback/generators/presentation.rb b/record-and-playback/core/lib/recordandplayback/generators/presentation.rb index 775f12aad0..5942ea4e94 100755 --- a/record-and-playback/core/lib/recordandplayback/generators/presentation.rb +++ b/record-and-playback/core/lib/recordandplayback/generators/presentation.rb @@ -74,5 +74,18 @@ module BigBlueButton BigBlueButton.execute(command) end + def self.get_presentation_for_preview(events_xml) + BigBlueButton.logger.info("Task: Getting presentation to be used for preview from events") + presentation = {} + doc = Nokogiri::XML(File.open(events_xml)) + doc.xpath("//event[@eventname='SharePresentationEvent']").each do |presentation_event| + presentation["id"] = presentation_event.xpath("presentationName").text + presentation["filename"] = presentation_event.xpath("originalFilename").text + if presentation_event.xpath("originalFilename").text != "default.pdf" + break + end + end + presentation + end end end diff --git a/record-and-playback/presentation/scripts/publish/presentation.rb b/record-and-playback/presentation/scripts/publish/presentation.rb index 08b0402e49..dddfc70b66 100755 --- a/record-and-playback/presentation/scripts/publish/presentation.rb +++ b/record-and-playback/presentation/scripts/publish/presentation.rb @@ -1022,21 +1022,25 @@ begin playback.remove end ## Add the actual playback - presentations = BigBlueButton::Presentation.get_presentations("#{$process_dir}/events.xml") + presentation = BigBlueButton::Presentation.get_presentation_for_preview("#{$process_dir}/events.xml") metadata_with_playback = Nokogiri::XML::Builder.with(metadata.at('recording')) do |xml| xml.playback { xml.format("presentation") xml.link("#{playback_protocol}://#{playback_host}/playback/presentation/0.9.0/playback.html?meetingId=#{$meeting_id}") xml.processing_time("#{processing_time}") xml.duration("#{recording_time}") - if presentations.any? - presentation_id = presentations.first + unless presentation.empty? xml.extensions { xml.preview { + unless !presentation.has_key?("text") + xml.text("#{presentation["text"]}") + end xml.images { - xml.image("#{playback_protocol}://#{playback_host}/presentation/#{$meeting_id}/presentation/#{presentation_id}/thumbnails/thumb-1.png") - xml.image("#{playback_protocol}://#{playback_host}/presentation/#{$meeting_id}/presentation/#{presentation_id}/thumbnails/thumb-2.png") - xml.image("#{playback_protocol}://#{playback_host}/presentation/#{$meeting_id}/presentation/#{presentation_id}/thumbnails/thumb-3.png") + xml.image(:width => "176", :height => "136"){ xml.text("#{playback_protocol}://#{playback_host}/presentation/#{$meeting_id}/presentation/#{presentation["id"]}/thumbnails/thumb-1.png") } + unless presentation["filename"] == "default.pdf" + xml.image(:width => "176", :height => "136"){ xml.text("#{playback_protocol}://#{playback_host}/presentation/#{$meeting_id}/presentation/#{presentation["id"]}/thumbnails/thumb-2.png") } + xml.image(:width => "176", :height => "136"){ xml.text("#{playback_protocol}://#{playback_host}/presentation/#{$meeting_id}/presentation/#{presentation["id"]}/thumbnails/thumb-3.png") } + end } } } From 8adf729e0f16bdf371617a8d2580186a242b4b94 Mon Sep 17 00:00:00 2001 From: jfederico Date: Tue, 20 Sep 2016 16:46:45 -0400 Subject: [PATCH 09/20] recording-and-playback: Added general text to the preview --- .../WEB-INF/freemarker/get-recordings.ftl | 8 ++++--- .../generators/presentation.rb | 21 ++++++++++++++++--- .../scripts/publish/presentation.rb | 4 ++-- 3 files changed, 25 insertions(+), 8 deletions(-) diff --git a/bigbluebutton-web/web-app/WEB-INF/freemarker/get-recordings.ftl b/bigbluebutton-web/web-app/WEB-INF/freemarker/get-recordings.ftl index 506d368fe5..d0edaf9858 100644 --- a/bigbluebutton-web/web-app/WEB-INF/freemarker/get-recordings.ftl +++ b/bigbluebutton-web/web-app/WEB-INF/freemarker/get-recordings.ftl @@ -34,10 +34,10 @@ <#assign properties = extension.getProperties()> <#if extension.getType() == "preview"> <#list properties?keys as property> - <${property}> <#if property == "text"> - ${properties[property]["text"]} + <${property}>${properties[property]["text"]} <#elseif property == "images"> + <${property}> <#if properties[property]["image"]?is_hash> <#assign image = properties[property]["image"]> width="${image["attributes"]["width"]}" <#if image["attributes"]?? && image["attributes"]["height"]??>height="${image["attributes"]["height"]}">${image["text"]} @@ -46,8 +46,10 @@ width="${image["attributes"]["width"]}" <#if image["attributes"]?? && image["attributes"]["height"]??>height="${image["attributes"]["height"]}">${image["text"]} - + <#else> + <${property} /> + diff --git a/record-and-playback/core/lib/recordandplayback/generators/presentation.rb b/record-and-playback/core/lib/recordandplayback/generators/presentation.rb index 5942ea4e94..e41962c58d 100755 --- a/record-and-playback/core/lib/recordandplayback/generators/presentation.rb +++ b/record-and-playback/core/lib/recordandplayback/generators/presentation.rb @@ -67,25 +67,40 @@ module BigBlueButton self.extract_png_page_from_pdf(1, pdf_page, png_out, '800x600') end - #Convert an image to a png + # Convert an image to a png def self.convert_image_to_png(image, png_image, resize = '800x600') BigBlueButton.logger.info("Task: Converting image to .png") command = "convert #{image} -resize #{resize} -background white -flatten #{png_image}" BigBlueButton.execute(command) end - def self.get_presentation_for_preview(events_xml) + # Get 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 presentation to be used for preview from events") presentation = {} doc = Nokogiri::XML(File.open(events_xml)) doc.xpath("//event[@eventname='SharePresentationEvent']").each do |presentation_event| presentation["id"] = presentation_event.xpath("presentationName").text presentation["filename"] = presentation_event.xpath("originalFilename").text - if presentation_event.xpath("originalFilename").text != "default.pdf" + unless presentation_event.xpath("originalFilename").text == "default.pdf" + # Gathers the text from the slide + textfiles_dir = "#{process_dir}/presentation/#{presentation["id"]}/textfiles" + if File.file?("#{textfiles_dir}/slide-1.txt") + presentation["text"] = File.open("#{textfiles_dir}/slide-1.txt") {|f| f.readline} + unless presentation["text"] == nil + presentation["text"] = presentation["text"].strip + end + end + # Break because something else than default.pdf was found break end end presentation end end + + # Extract a page from a pdf file as a png image + def self.extract_page_title_from_pdf(page_num, pdf_presentation) + end end diff --git a/record-and-playback/presentation/scripts/publish/presentation.rb b/record-and-playback/presentation/scripts/publish/presentation.rb index dddfc70b66..ec01c0c40a 100755 --- a/record-and-playback/presentation/scripts/publish/presentation.rb +++ b/record-and-playback/presentation/scripts/publish/presentation.rb @@ -1022,7 +1022,7 @@ begin playback.remove end ## Add the actual playback - presentation = BigBlueButton::Presentation.get_presentation_for_preview("#{$process_dir}/events.xml") + presentation = BigBlueButton::Presentation.get_presentation_for_preview("#{$process_dir}") metadata_with_playback = Nokogiri::XML::Builder.with(metadata.at('recording')) do |xml| xml.playback { xml.format("presentation") @@ -1033,7 +1033,7 @@ begin xml.extensions { xml.preview { unless !presentation.has_key?("text") - xml.text("#{presentation["text"]}") + xml.text_("#{presentation["text"]}") end xml.images { xml.image(:width => "176", :height => "136"){ xml.text("#{playback_protocol}://#{playback_host}/presentation/#{$meeting_id}/presentation/#{presentation["id"]}/thumbnails/thumb-1.png") } From 59c67809d057c400f6918af5b9876a40ba2fa7f8 Mon Sep 17 00:00:00 2001 From: jfederico Date: Wed, 21 Sep 2016 16:39:32 -0400 Subject: [PATCH 10/20] recording-and-playback: Added alt text to the preview per slide --- .../generators/presentation.rb | 51 ++++++++++++------- .../scripts/publish/presentation.rb | 12 ++--- 2 files changed, 38 insertions(+), 25 deletions(-) diff --git a/record-and-playback/core/lib/recordandplayback/generators/presentation.rb b/record-and-playback/core/lib/recordandplayback/generators/presentation.rb index e41962c58d..b5e53bb993 100755 --- a/record-and-playback/core/lib/recordandplayback/generators/presentation.rb +++ b/record-and-playback/core/lib/recordandplayback/generators/presentation.rb @@ -69,29 +69,45 @@ module BigBlueButton # Convert an image to a png def self.convert_image_to_png(image, png_image, resize = '800x600') - BigBlueButton.logger.info("Task: Converting image to .png") - command = "convert #{image} -resize #{resize} -background white -flatten #{png_image}" - BigBlueButton.execute(command) + BigBlueButton.logger.info("Task: Converting image to .png") + command = "convert #{image} -resize #{resize} -background white -flatten #{png_image}" + BigBlueButton.execute(command) end - # Get the presentation that will be used for preview. + # 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} + BigBlueButton.logger.info(text_from_slide) + 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 presentation to be used for preview from events") + 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| - presentation["id"] = presentation_event.xpath("presentationName").text - presentation["filename"] = presentation_event.xpath("originalFilename").text - unless presentation_event.xpath("originalFilename").text == "default.pdf" - # Gathers the text from the slide - textfiles_dir = "#{process_dir}/presentation/#{presentation["id"]}/textfiles" - if File.file?("#{textfiles_dir}/slide-1.txt") - presentation["text"] = File.open("#{textfiles_dir}/slide-1.txt") {|f| f.readline} - unless presentation["text"] == nil - presentation["text"] = presentation["text"].strip - end - end + # 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[:text] = presentation[:slides][1][:alt] + presentation[:slides][2] = { :alt => self.get_text_from_slide(textfiles_dir, 2) } + presentation[:slides][3] = { :alt => self.get_text_from_slide(textfiles_dir, 3) } # Break because something else than default.pdf was found break end @@ -100,7 +116,4 @@ module BigBlueButton end end - # Extract a page from a pdf file as a png image - def self.extract_page_title_from_pdf(page_num, pdf_presentation) - end end diff --git a/record-and-playback/presentation/scripts/publish/presentation.rb b/record-and-playback/presentation/scripts/publish/presentation.rb index ec01c0c40a..7e32318ef4 100755 --- a/record-and-playback/presentation/scripts/publish/presentation.rb +++ b/record-and-playback/presentation/scripts/publish/presentation.rb @@ -1032,14 +1032,14 @@ begin unless presentation.empty? xml.extensions { xml.preview { - unless !presentation.has_key?("text") - xml.text_("#{presentation["text"]}") + unless !presentation.has_key?(:text) + xml.text_("#{presentation[:text]}") end xml.images { - xml.image(:width => "176", :height => "136"){ xml.text("#{playback_protocol}://#{playback_host}/presentation/#{$meeting_id}/presentation/#{presentation["id"]}/thumbnails/thumb-1.png") } - unless presentation["filename"] == "default.pdf" - xml.image(:width => "176", :height => "136"){ xml.text("#{playback_protocol}://#{playback_host}/presentation/#{$meeting_id}/presentation/#{presentation["id"]}/thumbnails/thumb-2.png") } - xml.image(:width => "176", :height => "136"){ xml.text("#{playback_protocol}://#{playback_host}/presentation/#{$meeting_id}/presentation/#{presentation["id"]}/thumbnails/thumb-3.png") } + xml.image(:width => "176", :height => "136", :alt => (presentation[:slides][1][:alt] != nil)? "#{presentation[:slides][1][:alt]}": ""){ xml.text("#{playback_protocol}://#{playback_host}/presentation/#{$meeting_id}/presentation/#{presentation[:id]}/thumbnails/thumb-1.png") } + unless presentation[:filename] == "default.pdf" + xml.image(:width => "176", :height => "136", :alt => (presentation[:slides][2][:alt] != nil)? "#{presentation[:slides][2][:alt]}": ""){ xml.text("#{playback_protocol}://#{playback_host}/presentation/#{$meeting_id}/presentation/#{presentation[:id]}/thumbnails/thumb-2.png") } + xml.image(:width => "176", :height => "136", :alt => (presentation[:slides][3][:alt] != nil)? "#{presentation[:slides][3][:alt]}": ""){ xml.text("#{playback_protocol}://#{playback_host}/presentation/#{$meeting_id}/presentation/#{presentation[:id]}/thumbnails/thumb-3.png") } end } } From 870e9d5b79048288af9b824240e9b5ca01e8c8ec Mon Sep 17 00:00:00 2001 From: jfederico Date: Wed, 21 Sep 2016 16:43:11 -0400 Subject: [PATCH 11/20] bbb-web: Modified freeMarker template for adding support to alt text per slide on previews --- .../web-app/WEB-INF/freemarker/get-recordings.ftl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bigbluebutton-web/web-app/WEB-INF/freemarker/get-recordings.ftl b/bigbluebutton-web/web-app/WEB-INF/freemarker/get-recordings.ftl index d0edaf9858..8d52cae6af 100644 --- a/bigbluebutton-web/web-app/WEB-INF/freemarker/get-recordings.ftl +++ b/bigbluebutton-web/web-app/WEB-INF/freemarker/get-recordings.ftl @@ -40,10 +40,10 @@ <${property}> <#if properties[property]["image"]?is_hash> <#assign image = properties[property]["image"]> - width="${image["attributes"]["width"]}" <#if image["attributes"]?? && image["attributes"]["height"]??>height="${image["attributes"]["height"]}">${image["text"]} + width="${image["attributes"]["width"]}" <#if image["attributes"]?? && image["attributes"]["height"]??>height="${image["attributes"]["height"]}" <#if image["attributes"]?? && image["attributes"]["alt"]??>alt="${image["attributes"]["alt"]}">${image["text"]} <#elseif properties[property]["image"]?is_enumerable> <#list properties[property]["image"] as image> - width="${image["attributes"]["width"]}" <#if image["attributes"]?? && image["attributes"]["height"]??>height="${image["attributes"]["height"]}">${image["text"]} + width="${image["attributes"]["width"]}" <#if image["attributes"]?? && image["attributes"]["height"]??>height="${image["attributes"]["height"]}" <#if image["attributes"]?? && image["attributes"]["alt"]??>alt="${image["attributes"]["alt"]}">${image["text"]} From e0b6a9ebf8108e9e7e1944e3090e44c9b850d36d Mon Sep 17 00:00:00 2001 From: jfederico Date: Wed, 21 Sep 2016 17:31:40 -0400 Subject: [PATCH 12/20] recording-and-playback: Removed log used for debugging --- .../core/lib/recordandplayback/generators/presentation.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/record-and-playback/core/lib/recordandplayback/generators/presentation.rb b/record-and-playback/core/lib/recordandplayback/generators/presentation.rb index b5e53bb993..1bedd1c96c 100755 --- a/record-and-playback/core/lib/recordandplayback/generators/presentation.rb +++ b/record-and-playback/core/lib/recordandplayback/generators/presentation.rb @@ -79,7 +79,6 @@ module BigBlueButton 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} - BigBlueButton.logger.info(text_from_slide) unless text_from_slide == nil text_from_slide = text_from_slide.strip end From d567254b9ced83a6a6f99a197e0c41e2697d284d Mon Sep 17 00:00:00 2001 From: jfederico Date: Thu, 22 Sep 2016 10:05:21 -0400 Subject: [PATCH 13/20] bbb-web: Updated internal xml example for a recording descriptor --- .../api/RecordingServiceHelperImp.groovy | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/bigbluebutton-web/src/groovy/org/bigbluebutton/api/RecordingServiceHelperImp.groovy b/bigbluebutton-web/src/groovy/org/bigbluebutton/api/RecordingServiceHelperImp.groovy index 43ed9a6345..8e1bcca7f9 100755 --- a/bigbluebutton-web/src/groovy/org/bigbluebutton/api/RecordingServiceHelperImp.groovy +++ b/bigbluebutton-web/src/groovy/org/bigbluebutton/api/RecordingServiceHelperImp.groovy @@ -50,16 +50,13 @@ public class RecordingServiceHelperImp implements RecordingServiceHelper { - Introduction to Unit 1 Professor Jones Office Hours are Wedn + Instrument Flying - http://example.com/f000057.jpg - http://example.com/f001032.jpg - http://example.com/f002103.jpg + Instrument Flyinghttp://bbb-server/.../thumb-1.png + Course Structurehttp://bbb-server/.../thumb-2.png + Requirementshttp://bbb-server/.../thumb-3.png - - en - From 78cb599a5bf6bc38aeee4ddcc8fe7af6444a8056 Mon Sep 17 00:00:00 2001 From: jfederico Date: Thu, 22 Sep 2016 13:11:01 -0400 Subject: [PATCH 14/20] record-and-playback: removed text element from extension preview --- .../core/lib/recordandplayback/generators/presentation.rb | 1 - .../presentation/scripts/publish/presentation.rb | 3 --- 2 files changed, 4 deletions(-) diff --git a/record-and-playback/core/lib/recordandplayback/generators/presentation.rb b/record-and-playback/core/lib/recordandplayback/generators/presentation.rb index 1bedd1c96c..59a3ca1915 100755 --- a/record-and-playback/core/lib/recordandplayback/generators/presentation.rb +++ b/record-and-playback/core/lib/recordandplayback/generators/presentation.rb @@ -104,7 +104,6 @@ module BigBlueButton presentation[:slides] = {} presentation[:slides][1] = { :alt => self.get_text_from_slide(textfiles_dir, 1) } unless presentation_filename == "default.pdf" - presentation[:text] = presentation[:slides][1][:alt] presentation[:slides][2] = { :alt => self.get_text_from_slide(textfiles_dir, 2) } presentation[:slides][3] = { :alt => self.get_text_from_slide(textfiles_dir, 3) } # Break because something else than default.pdf was found diff --git a/record-and-playback/presentation/scripts/publish/presentation.rb b/record-and-playback/presentation/scripts/publish/presentation.rb index 7e32318ef4..b2dbdfaa3e 100755 --- a/record-and-playback/presentation/scripts/publish/presentation.rb +++ b/record-and-playback/presentation/scripts/publish/presentation.rb @@ -1032,9 +1032,6 @@ begin unless presentation.empty? xml.extensions { xml.preview { - unless !presentation.has_key?(:text) - xml.text_("#{presentation[:text]}") - end xml.images { xml.image(:width => "176", :height => "136", :alt => (presentation[:slides][1][:alt] != nil)? "#{presentation[:slides][1][:alt]}": ""){ xml.text("#{playback_protocol}://#{playback_host}/presentation/#{$meeting_id}/presentation/#{presentation[:id]}/thumbnails/thumb-1.png") } unless presentation[:filename] == "default.pdf" From 6839ffeb151870343ad767651cab3e60c5de6904 Mon Sep 17 00:00:00 2001 From: jfederico Date: Thu, 22 Sep 2016 13:11:27 -0400 Subject: [PATCH 15/20] bbb-web: removed text element from extension preview --- .../web-app/WEB-INF/freemarker/get-recordings.ftl | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/bigbluebutton-web/web-app/WEB-INF/freemarker/get-recordings.ftl b/bigbluebutton-web/web-app/WEB-INF/freemarker/get-recordings.ftl index 8d52cae6af..f22002ee14 100644 --- a/bigbluebutton-web/web-app/WEB-INF/freemarker/get-recordings.ftl +++ b/bigbluebutton-web/web-app/WEB-INF/freemarker/get-recordings.ftl @@ -34,9 +34,7 @@ <#assign properties = extension.getProperties()> <#if extension.getType() == "preview"> <#list properties?keys as property> - <#if property == "text"> - <${property}>${properties[property]["text"]} - <#elseif property == "images"> + <#if property == "images"> <${property}> <#if properties[property]["image"]?is_hash> <#assign image = properties[property]["image"]> From 0506db4f262acfa1f12523c6948f47c37e8ac726 Mon Sep 17 00:00:00 2001 From: jfederico Date: Sat, 24 Sep 2016 10:54:09 -0400 Subject: [PATCH 16/20] bbb-web: Fixed issue with publish/unpublish removing extensions from metadata.xml --- .../api/RecordingServiceHelperImp.groovy | 65 +++++++++++++++++-- 1 file changed, 59 insertions(+), 6 deletions(-) diff --git a/bigbluebutton-web/src/groovy/org/bigbluebutton/api/RecordingServiceHelperImp.groovy b/bigbluebutton-web/src/groovy/org/bigbluebutton/api/RecordingServiceHelperImp.groovy index 8e1bcca7f9..a6f1fe96fb 100755 --- a/bigbluebutton-web/src/groovy/org/bigbluebutton/api/RecordingServiceHelperImp.groovy +++ b/bigbluebutton-web/src/groovy/org/bigbluebutton/api/RecordingServiceHelperImp.groovy @@ -19,9 +19,11 @@ package org.bigbluebutton.api; +import groovy.json.JsonBuilder; import groovy.util.XmlSlurper; import groovy.util.slurpersupport.Attributes; import groovy.util.slurpersupport.GPathResult; +import groovy.xml.MarkupBuilder; import java.io.File; import java.io.FileNotFoundException; @@ -71,7 +73,7 @@ public class RecordingServiceHelperImp implements RecordingServiceHelper { public void writeRecordingInfo(String path, Recording info) { def writer = new StringWriter() def builder = new groovy.xml.MarkupBuilder(writer) - def metadataXml = builder.recording { + builder.recording { builder.id(info.getId()) builder.state(info.getState()) builder.published(info.isPublished()) @@ -84,7 +86,17 @@ public class RecordingServiceHelperImp implements RecordingServiceHelper { builder.format(info.getPlaybackFormat()) builder.link(info.getPlaybackLink()) 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 metainfo = info.getMetadata(); @@ -104,7 +116,7 @@ public class RecordingServiceHelperImp implements RecordingServiceHelper { File file = new File(dir.getPath() + File.separatorChar + "metadata.xml"); if ( file ) { def recording = new XmlSlurper().parse(file); - return getInfo(recording); + return getInfo(recording); } } catch ( FileNotFoundException e) { // Do nothing, just return null @@ -117,6 +129,7 @@ public class RecordingServiceHelperImp implements RecordingServiceHelper { private Recording getInfo(GPathResult rec) { Recording r = new Recording(); + //Add basic information r.setId(rec.id.text()); r.setState(rec.state.text()); r.setPublished(Boolean.parseBoolean(rec.published.text())); @@ -128,11 +141,14 @@ public class RecordingServiceHelperImp implements RecordingServiceHelper { r.setPlaybackDuration(rec.playback.duration.text()); } + //Add extensions List extensions = new ArrayList() rec.playback.extensions.children().each { extension -> - extensions.add( new Extension(extension.name(),parse(extension)) ) + extensions.add( new Extension(extension.name(), extensionPropertiesToMap(extension)) ) } r.setPlaybackExtensions(extensions) + + //Add metadata Map meta = new HashMap(); rec.meta.children().each { anode -> meta.put(anode.name().toString(), anode.text().toString()); @@ -170,7 +186,7 @@ public class RecordingServiceHelperImp implements RecordingServiceHelper { } } //Add content to the node - if ( map[node.name()] == null) { + if ( map[node.name()] == null ) { map[node.name()] = nodeContent } else { if ( ! (map[node.name()] instanceof List) ) { @@ -181,7 +197,7 @@ public class RecordingServiceHelperImp implements RecordingServiceHelper { map } - private Map parse(GPathResult xml) { + private Map extensionPropertiesToMap(GPathResult xml) { Map map = [ : ] xml.children().each { if ( it.children().size() == 0 ) { @@ -193,4 +209,41 @@ public class RecordingServiceHelperImp implements RecordingServiceHelper { 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) + } + } + } + } } From 36dfbe70889c121888a9a8302894074494954a31 Mon Sep 17 00:00:00 2001 From: jfederico Date: Sat, 24 Sep 2016 10:59:26 -0400 Subject: [PATCH 17/20] bbb-web: Added validation to freemarker template to verify image elements are included when extension preview used --- bigbluebutton-web/web-app/WEB-INF/freemarker/get-recordings.ftl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bigbluebutton-web/web-app/WEB-INF/freemarker/get-recordings.ftl b/bigbluebutton-web/web-app/WEB-INF/freemarker/get-recordings.ftl index f22002ee14..2ff4cf55ec 100644 --- a/bigbluebutton-web/web-app/WEB-INF/freemarker/get-recordings.ftl +++ b/bigbluebutton-web/web-app/WEB-INF/freemarker/get-recordings.ftl @@ -36,7 +36,7 @@ <#list properties?keys as property> <#if property == "images"> <${property}> - <#if properties[property]["image"]?is_hash> + <#if properties[property]["image"]?? && properties[property]["image"]?is_hash> <#assign image = properties[property]["image"]> width="${image["attributes"]["width"]}" <#if image["attributes"]?? && image["attributes"]["height"]??>height="${image["attributes"]["height"]}" <#if image["attributes"]?? && image["attributes"]["alt"]??>alt="${image["attributes"]["alt"]}">${image["text"]} <#elseif properties[property]["image"]?is_enumerable> From 1a4438d459aa4b0086d73048d7ebb6a7005b2a6d Mon Sep 17 00:00:00 2001 From: jfederico Date: Tue, 27 Sep 2016 15:19:53 -0400 Subject: [PATCH 18/20] record-and-playback: Fixed issue with presentations containing less than 3 slides --- .../core/lib/recordandplayback/generators/presentation.rb | 4 ++-- .../presentation/scripts/publish/presentation.rb | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/record-and-playback/core/lib/recordandplayback/generators/presentation.rb b/record-and-playback/core/lib/recordandplayback/generators/presentation.rb index 59a3ca1915..92021a5159 100755 --- a/record-and-playback/core/lib/recordandplayback/generators/presentation.rb +++ b/record-and-playback/core/lib/recordandplayback/generators/presentation.rb @@ -104,8 +104,8 @@ module BigBlueButton 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) } - presentation[:slides][3] = { :alt => self.get_text_from_slide(textfiles_dir, 3) } + 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 diff --git a/record-and-playback/presentation/scripts/publish/presentation.rb b/record-and-playback/presentation/scripts/publish/presentation.rb index b2dbdfaa3e..b3a35cf3d8 100755 --- a/record-and-playback/presentation/scripts/publish/presentation.rb +++ b/record-and-playback/presentation/scripts/publish/presentation.rb @@ -1033,10 +1033,10 @@ begin xml.extensions { xml.preview { xml.images { - xml.image(:width => "176", :height => "136", :alt => (presentation[:slides][1][:alt] != nil)? "#{presentation[:slides][1][:alt]}": ""){ xml.text("#{playback_protocol}://#{playback_host}/presentation/#{$meeting_id}/presentation/#{presentation[:id]}/thumbnails/thumb-1.png") } - unless presentation[:filename] == "default.pdf" - xml.image(:width => "176", :height => "136", :alt => (presentation[:slides][2][:alt] != nil)? "#{presentation[:slides][2][:alt]}": ""){ xml.text("#{playback_protocol}://#{playback_host}/presentation/#{$meeting_id}/presentation/#{presentation[:id]}/thumbnails/thumb-2.png") } - xml.image(:width => "176", :height => "136", :alt => (presentation[:slides][3][:alt] != nil)? "#{presentation[:slides][3][:alt]}": ""){ xml.text("#{playback_protocol}://#{playback_host}/presentation/#{$meeting_id}/presentation/#{presentation[:id]}/thumbnails/thumb-3.png") } + presentation[:slides].each do |key,val| + attributes = {:width => "176", :height => "136"} + attributes[:alt] = val[:alt] if val[:alt] != nil + xml.image(attributes){ xml.text("#{playback_protocol}://#{playback_host}/presentation/#{$meeting_id}/presentation/#{presentation[:id]}/thumbnails/thumb-#{key}.png") } end } } From 039d85fe5c3649e4a4723e2b57be42f2195334c8 Mon Sep 17 00:00:00 2001 From: jfederico Date: Tue, 27 Sep 2016 15:27:28 -0400 Subject: [PATCH 19/20] bbb-web: Added internalMeetingID to xml response from create and getMeetings --- .../org/bigbluebutton/web/controllers/ApiController.groovy | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bigbluebutton-web/grails-app/controllers/org/bigbluebutton/web/controllers/ApiController.groovy b/bigbluebutton-web/grails-app/controllers/org/bigbluebutton/web/controllers/ApiController.groovy index 23bc08cc01..33a27a8d48 100755 --- a/bigbluebutton-web/grails-app/controllers/org/bigbluebutton/web/controllers/ApiController.groovy +++ b/bigbluebutton-web/grails-app/controllers/org/bigbluebutton/web/controllers/ApiController.groovy @@ -865,6 +865,7 @@ class ApiController { for (m in mtgs) { meeting { meetingID() { mkp.yield(m.getExternalId()) } + internalMeetingID() { mkp.yield(m.getInternalId()) } isBreakout() { mkp.yield(m.isBreakout()) } meetingName() { mkp.yield(m.getName()) } createTime(m.getCreateTime()) @@ -2192,6 +2193,7 @@ class ApiController { response() { returncode(RESP_CODE_SUCCESS) meetingID() { mkp.yield(meeting.getExternalId()) } + internalMeetingID() { mkp.yield(meeting.getInternalId()) } attendeePW() { mkp.yield(meeting.getViewerPassword()) } moderatorPW() { mkp.yield(meeting.getModeratorPassword()) } createTime(meeting.getCreateTime()) From d2a633a27b2542cbb55cfe351d7812cc41d9a8f1 Mon Sep 17 00:00:00 2001 From: jfederico Date: Tue, 27 Sep 2016 16:02:20 -0400 Subject: [PATCH 20/20] record-and-playback: Forced alt to be included as part of the image thumbnail element in preview extension --- .../presentation/scripts/publish/presentation.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/record-and-playback/presentation/scripts/publish/presentation.rb b/record-and-playback/presentation/scripts/publish/presentation.rb index b3a35cf3d8..3335020ae0 100755 --- a/record-and-playback/presentation/scripts/publish/presentation.rb +++ b/record-and-playback/presentation/scripts/publish/presentation.rb @@ -1034,8 +1034,7 @@ begin xml.preview { xml.images { presentation[:slides].each do |key,val| - attributes = {:width => "176", :height => "136"} - attributes[:alt] = val[:alt] if val[:alt] != nil + 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 }