- refactor presentation service
- generate blank slide or thumbnail if conversion fails for that page - if the resulting swf file is greater than 500K, generate a SWF file using a PNG snapshot to make resulting SWF file smaller. This helps to improve performance when rendering the slide on the client Config Changes: /etc/nginx/sites-available/bigbluebutton - set client_max_body_size 20m; // Allow 20Mb file upload - put blank slide and thumbnail in /var/bigbluebutton/blank (see bigbluebutton.properties) git-svn-id: http://bigbluebutton.googlecode.com/svn/trunk@2356 af16638f-c34d-0410-8cfa-b39d5352b314
This commit is contained in:
parent
1f660af841
commit
4cc227cd99
@ -9,7 +9,9 @@ swfToolsDir=/bin
|
||||
imageMagickDir=/usr/bin
|
||||
presentationDir=/var/bigbluebutton
|
||||
ghostScriptExec=/usr/bin/gs
|
||||
|
||||
BLANK_SLIDE = /var/bigbluebutton/blank/blank-slide.swf
|
||||
BLANK_THUMBNAIL = /var/bigbluebutton/blank/blank-thumb.png
|
||||
|
||||
beans.presentationService.swfToolsDir=${swfToolsDir}
|
||||
beans.presentationService.imageMagickDir=${imageMagickDir}
|
||||
beans.presentationService.presentationDir=${presentationDir}
|
||||
@ -20,7 +22,7 @@ beans.presentationService.ghostScriptExec=${ghostScriptExec}
|
||||
|
||||
#
|
||||
# This URL needs to reference the host running the tomcat server
|
||||
bigbluebutton.web.serverURL=http://localhost
|
||||
bigbluebutton.web.serverURL=http://192.168.0.182
|
||||
|
||||
# This is a workaround for a problem converting PDF files, referenced at
|
||||
# http://groups.google.com/group/comp.lang.postscript/browse_thread/thread/c2e264ca76534ce0?pli=1
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* BigBlueButton - http://www.bigbluebutton.org
|
||||
/* BigBlueButton - http://www.bigbluebutton.org
|
||||
*
|
||||
*
|
||||
* Copyright (c) 2008-2009 by respective authors (see below). All rights reserved.
|
||||
*
|
||||
@ -84,7 +84,16 @@ class PublicScheduledSessionController {
|
||||
|
||||
}
|
||||
|
||||
def signIn = {
|
||||
def signIn = {
|
||||
if (params.fullname.trim() == "") {
|
||||
log.debug "USer entered a blank name"
|
||||
flash.message = "Please enter your name."
|
||||
render(view:"joinIn", model: [id:params.id, fullname:params.fullname])
|
||||
return
|
||||
} else {
|
||||
log.debug "Fullname is not null ${params.fullname}"
|
||||
}
|
||||
|
||||
log.debug "Attempting to sign in to ${params.id}"
|
||||
def conference = Conference.findByConferenceNumber(params.id)
|
||||
def signedIn = false
|
||||
@ -166,72 +175,7 @@ class PublicScheduledSessionController {
|
||||
render(view:"joinIn",model: [id:params.id, fullname:params.fullname])
|
||||
}
|
||||
}
|
||||
|
||||
def signIn2 = {
|
||||
println 'signIn start'
|
||||
def confSession = ScheduledSession.findByTokenId(params.id)
|
||||
def role = ''
|
||||
def signedIn = false
|
||||
|
||||
if (confSession) {
|
||||
println 'signIn: has conference session'
|
||||
|
||||
println 'Found scheduled session'
|
||||
switch (params.password) {
|
||||
case confSession.hostPassword:
|
||||
println 'as host'
|
||||
// Let us set role to MODERATOR for now as we don't support HOST yet
|
||||
role = "MODERATOR"
|
||||
signedIn = true
|
||||
break
|
||||
case confSession.moderatorPassword:
|
||||
println 'as moderator'
|
||||
role = "MODERATOR"
|
||||
signedIn = true
|
||||
break
|
||||
case confSession.attendeePassword:
|
||||
println 'as viewer'
|
||||
role = "VIEWER"
|
||||
signedIn = true
|
||||
break
|
||||
}
|
||||
if (signedIn) {
|
||||
println 'successful'
|
||||
session["fullname"] = params.fullname
|
||||
session["role"] = role
|
||||
session["conference"] = params.id
|
||||
session["room"] = confSession.sessionId
|
||||
session["voicebridge"] = confSession.voiceConferenceBridge
|
||||
}
|
||||
|
||||
def long _10_MINUTES = 10*60*1000
|
||||
def now = new Date().time
|
||||
|
||||
def startTime = confSession.startDateTime.time - _10_MINUTES
|
||||
def endTime = confSession.endDateTime.time + _10_MINUTES
|
||||
|
||||
if ((startTime <= now) && (now <= endTime)) {
|
||||
session["mode"] = "LIVE"
|
||||
session["record"] = false
|
||||
if (confSession.record) {
|
||||
session["record"] = true
|
||||
}
|
||||
} else {
|
||||
session["mode"] = "PLAYBACK"
|
||||
}
|
||||
|
||||
println 'rendering signIn'
|
||||
|
||||
redirect(action:show)
|
||||
}
|
||||
|
||||
if (!signedIn) {
|
||||
println 'failed'
|
||||
flash.message = "Failed to join the conference session."
|
||||
redirect(action:joinIn,id:params.id, params:[fullname:params.fullname])
|
||||
}
|
||||
}
|
||||
|
||||
def enter = {
|
||||
def fname = session["fullname"]
|
||||
def rl = session["role"]
|
||||
@ -247,7 +191,7 @@ class PublicScheduledSessionController {
|
||||
xml {
|
||||
render(contentType:"text/xml") {
|
||||
'join'() {
|
||||
returnCode("FAILED")
|
||||
returncode("FAILED")
|
||||
message("Could not find conference ${params.conference}.")
|
||||
}
|
||||
}
|
||||
@ -277,8 +221,11 @@ class PublicScheduledSessionController {
|
||||
def signOut = {
|
||||
// Log the user out of the application.
|
||||
session.invalidate()
|
||||
|
||||
|
||||
def config = ConfigurationHolder.config
|
||||
def hostURL = config.bigbluebutton.web.serverURL
|
||||
println "serverURL $hostURL"
|
||||
// For now, redirect back to the home page.
|
||||
redirect(uri: '/')
|
||||
redirect(url: hostURL)
|
||||
}
|
||||
}
|
||||
|
@ -26,7 +26,11 @@ import javax.jms.MapMessage
|
||||
import org.springframework.jms.core.JmsTemplate
|
||||
import java.util.*;
|
||||
import java.util.concurrent.*;
|
||||
import java.lang.InterruptedException
|
||||
import java.lang.InterruptedException
|
||||
import org.springframework.util.FileCopyUtils
|
||||
|
||||
import org.bigbluebutton.presentation.*
|
||||
|
||||
class PresentationService {
|
||||
|
||||
boolean transactional = false
|
||||
@ -35,6 +39,8 @@ class PresentationService {
|
||||
def ghostScriptExec
|
||||
def swfToolsDir
|
||||
def presentationDir
|
||||
def BLANK_SLIDE = '/var/bigbluebutton/blank/blank-slide.swf'
|
||||
def BLANK_THUMBNAIL = '/var/bigbluebutton/blank/blank-thumb.png'
|
||||
|
||||
/*
|
||||
* This is a workaround for this problem.
|
||||
@ -101,55 +107,15 @@ class PresentationService {
|
||||
new Timer().runAfter(1000)
|
||||
{
|
||||
//first we need to know how many pages in this pdf
|
||||
log.debug "Determining number of pages"
|
||||
int numPages = determineNumberOfPages(presentationFile)
|
||||
log.debug "Determining number of pages"
|
||||
PageCounter pageCounter = new Pdf2SwfPageCounter()
|
||||
pageCounter.setSwfToolsDir(swfToolsDir)
|
||||
|
||||
int numPages = pageCounter.countNumberOfPages(presentationFile)
|
||||
log.info "There are $numPages pages in $presentationFile.absolutePath"
|
||||
convertUploadedPresentation(room, presentationName, presentationFile, numPages)
|
||||
}
|
||||
}
|
||||
|
||||
public int determineNumberOfPages(File presentationFile) {
|
||||
def numPages = -1 //total numbers of this pdf, also used as errorcode(-1)
|
||||
|
||||
try
|
||||
{
|
||||
def command = swfToolsDir + "/pdf2swf -I " + presentationFile.getAbsolutePath()
|
||||
log.debug "Executing with waitFor $command"
|
||||
def p = Runtime.getRuntime().exec(command);
|
||||
|
||||
def stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
|
||||
def stdError = new BufferedReader(new InputStreamReader(p.getErrorStream()));
|
||||
def info
|
||||
def str //output information to console for stdInput and stdError
|
||||
while ((info = stdInput.readLine()) != null) {
|
||||
//The output would be something like this 'page=21 width=718.00 height=538.00'.
|
||||
//We need to extract the page number (i.e. 21) from it.
|
||||
def infoRegExp = /page=([0-9]+)(?: .+)/
|
||||
def matcher = (info =~ infoRegExp)
|
||||
if (matcher.matches()) {
|
||||
numPages = matcher[0][1]
|
||||
} else {
|
||||
println "no match info: ${info}"
|
||||
}
|
||||
}
|
||||
while ((info = stdError.readLine()) != null) {
|
||||
System.out.println("Got error getting info from file):\n");
|
||||
System.out.println(str);
|
||||
}
|
||||
stdInput.close();
|
||||
stdError.close();
|
||||
|
||||
//if(p.exitValue() != 0) return -1;
|
||||
// Wait for the process to finish.
|
||||
int exitVal = p.waitFor()
|
||||
}
|
||||
catch (IOException e) {
|
||||
System.out.println("exception happened - here's what I know: ");
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return new Integer(numPages).intValue()
|
||||
}
|
||||
|
||||
def showSlide(String conf, String room, String presentationName, String id) {
|
||||
new File(roomDirectory(conf, room).absolutePath + File.separatorChar + presentationName + File.separatorChar + "slide-${id}.swf")
|
||||
@ -193,8 +159,12 @@ class PresentationService {
|
||||
convertPage(presentationFile, page)
|
||||
}
|
||||
|
||||
log.debug "Creating thumbnails for $presentationFile.absolutePath"
|
||||
createThumbnails(presentationFile)
|
||||
log.debug "Creating thumbnails for $presentationFile.absolutePath"
|
||||
|
||||
ThumbnailCreatorImp tc = new ThumbnailCreatorImp()
|
||||
tc.imageMagickDir = imageMagickDir
|
||||
tc.blankThumbnail = BLANK_THUMBNAIL
|
||||
tc.createThumbnails(presentationFile, numPages)
|
||||
|
||||
def msg = new HashMap()
|
||||
msg.put("room", room)
|
||||
@ -207,198 +177,69 @@ class PresentationService {
|
||||
sendJmsMessage(msg)
|
||||
}
|
||||
|
||||
public boolean convertPage(File presentationFile, int page) {
|
||||
if (! convertUsingPdf2Swf(presentationFile, page)) {
|
||||
log.info "cannot convert page $page"
|
||||
if (extractPageUsingGhostScript(presentationFile, page)) {
|
||||
log.info "created using ghostscript page $page"
|
||||
if (convertUsingImageMagick(presentationFile, page)) {
|
||||
log.info "created using imagemagick page $page"
|
||||
if (convertUsingJpeg2Swf(presentationFile, page)) {
|
||||
log.info "create using jpeg page $page"
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
public boolean convertPage(File presentationFile, int page) {
|
||||
PageConverter converter = new Pdf2SwfPageConverter()
|
||||
converter.setSwfToolsDir(swfToolsDir)
|
||||
|
||||
File output = new File(presentationFile.getParent() + File.separatorChar + "slide-" + page + ".swf")
|
||||
|
||||
if (! converter.convert(presentationFile, output, page)) {
|
||||
log.info "cannot create ${output.absolutePath}"
|
||||
println "cannot create ${output.absolutePath}"
|
||||
convertPageAsAnImage(presentationFile, output, page)
|
||||
} else {
|
||||
println "The size of the swf file is " + output.size()
|
||||
// If the resulting swf file is greater than 500K, it probably contains a lot of objects
|
||||
// that it becomes very slow to render on the client. Take an image snapshot instead and
|
||||
// use it to generate the SWF file. (ralam Sept 2, 2009)
|
||||
if (output.size() > 500000) {
|
||||
convertPageAsAnImage(presentationFile, output, page)
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
|
||||
// If all fails, generate a blank slide.
|
||||
if (! output.exists()) {
|
||||
println "Creating balnk slide for ${output.absolutePath}"
|
||||
generateBlankSlide(output.getAbsolutePath())
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
private boolean convertPageAsAnImage(File presentationFile, File output, int page) {
|
||||
PageExtractor extractor = new GhostscriptPageExtractor()
|
||||
extractor.setGhostscriptExec(ghostScriptExec)
|
||||
extractor.setNoPdfMarkWorkaround(noPdfMarkWorkaround)
|
||||
|
||||
def tempDir = new File(presentationFile.parent + File.separatorChar + "temp")
|
||||
tempDir.mkdir()
|
||||
|
||||
File tempPdfFile = new File(tempDir.absolutePath + File.separator + "temp-${page}.pdf")
|
||||
|
||||
if (extractor.extractPage(presentationFile, tempPdfFile, page)) {
|
||||
log.info "created using ghostscript ${tempPdfFile.absolutePath}"
|
||||
println "created using ghostscript ${tempPdfFile.absolutePath}"
|
||||
|
||||
File tempPngFile = new File(tempDir.getAbsolutePath() + "/temp-${page}.png")
|
||||
|
||||
PageConverter imConverter = new ImageMagickPageConverter()
|
||||
imConverter.setImageMagickDir(imageMagickDir)
|
||||
if (imConverter.convert(tempPdfFile, tempPngFile, 1)) {
|
||||
log.info "created using imagemagick ${tempPngFile.absolutePath}"
|
||||
println "created using imagemagick ${tempPngFile.absolutePath}"
|
||||
|
||||
PageConverter pngConverter = new Png2SwfPageConverter()
|
||||
pngConverter.setSwfToolsDir(swfToolsDir)
|
||||
if (pngConverter.convert(tempPngFile, output, 1)) {
|
||||
log.info "converted ${tempPngFile.absolutePath} to ${output.absolutePath} "
|
||||
println "converted ${tempPngFile.absolutePath} to ${output.absolutePath}"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean extractPageUsingGhostScript(File presentationFile, int page) {
|
||||
def tempDir = new File(presentationFile.parent + File.separatorChar + "temp")
|
||||
tempDir.mkdir()
|
||||
|
||||
String OPTIONS = "-sDEVICE=pdfwrite -dNOPAUSE -dQUIET -dBATCH"
|
||||
String PAGE = "-dFirstPage=${page} -dLastPage=${page}"
|
||||
String dest = tempDir.absolutePath + File.separator + "temp-${page}.pdf"
|
||||
|
||||
//extract that specific page and create a temp-pdf(only one page) with GhostScript
|
||||
def command = ghostScriptExec + " " + OPTIONS + " " + PAGE + " " + "-sOutputFile=${dest}" + " " + noPdfMarkWorkaround + " " + presentationFile
|
||||
log.debug "Executing $command"
|
||||
|
||||
def process
|
||||
try {
|
||||
def now = new Date()
|
||||
println "GS starting $now"
|
||||
|
||||
process = Runtime.getRuntime().exec(command);
|
||||
|
||||
// Wait for the process to finish.
|
||||
int exitVal = process.waitFor()
|
||||
|
||||
now = new Date()
|
||||
println "GS starting $now"
|
||||
|
||||
def stdInput = new BufferedReader(new InputStreamReader(process.getInputStream()));
|
||||
def stdError = new BufferedReader(new InputStreamReader(process.getErrorStream()));
|
||||
def str
|
||||
while ((str = stdInput.readLine()) != null) {
|
||||
System.out.println(str);
|
||||
}
|
||||
// read any errors from the attempted command
|
||||
System.out.println("Here is the standard error of the command (if any):\n");
|
||||
while ((str = stdError.readLine()) != null) {
|
||||
System.out.println(str);
|
||||
}
|
||||
stdInput.close();
|
||||
stdError.close();
|
||||
} catch (InterruptedException e) {
|
||||
System.out.println(e.toString());
|
||||
}
|
||||
|
||||
if (process.exitValue() == 0) {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
public boolean convertUsingJpeg2Swf(File presentationFile, int page) {
|
||||
def tempDir = new File(presentationFile.getParent() + File.separatorChar + "temp")
|
||||
|
||||
def source = tempDir.absolutePath + File.separator + "temp-${page}.jpeg"
|
||||
def dest = presentationFile.parent + File.separatorChar + "slide-${page}.swf"
|
||||
println "converting $source to $dest"
|
||||
|
||||
def now = new Date()
|
||||
println "JPEG2SWF starting $now"
|
||||
|
||||
def command = swfToolsDir + "/jpeg2swf -o " + dest + " " + source
|
||||
log.debug "Executing $command"
|
||||
def process = Runtime.getRuntime().exec(command);
|
||||
|
||||
// Wait for the process to finish.
|
||||
int exitValue = process.waitFor()
|
||||
|
||||
now = new Date()
|
||||
println "JPEG2SWF ended $now"
|
||||
|
||||
def stdInput = new BufferedReader(new InputStreamReader(process.getInputStream()));
|
||||
def stdError = new BufferedReader(new InputStreamReader(process.getErrorStream()));
|
||||
def str
|
||||
while ((str = stdInput.readLine()) != null) {
|
||||
System.out.println(str);
|
||||
}
|
||||
// read any errors from the attempted command
|
||||
System.out.println("Here is the standard error of the command (if any):\n");
|
||||
while ((str = stdError.readLine()) != null) {
|
||||
System.out.println(str);
|
||||
}
|
||||
stdInput.close();
|
||||
stdError.close();
|
||||
|
||||
File destFile = new File(dest)
|
||||
if (destFile.exists()) return true
|
||||
return false
|
||||
}
|
||||
|
||||
public boolean convertUsingImageMagick(File presentationFile, int page) {
|
||||
def tempDir = new File(presentationFile.getParent() + File.separatorChar + "temp")
|
||||
tempDir.mkdir()
|
||||
|
||||
def source = tempDir.getAbsolutePath() + "/temp-${page}.pdf"
|
||||
def dest = tempDir.getAbsolutePath() + "/temp-${page}.jpeg"
|
||||
|
||||
def now = new Date()
|
||||
println "IMAGEMAGICK starting $now"
|
||||
|
||||
def command = imageMagickDir + "/convert " + source + " " + dest
|
||||
log.debug "Executing $command"
|
||||
def process = Runtime.getRuntime().exec(command);
|
||||
// Wait for the process to finish.
|
||||
int exitValue = process.waitFor()
|
||||
|
||||
now = new Date()
|
||||
println "IMAGEMAGICK ends $now"
|
||||
|
||||
File destFile = new File(dest)
|
||||
if (destFile.exists()) return true
|
||||
return false
|
||||
}
|
||||
|
||||
public boolean convertUsingPdf2Swf(File presentationFile, int page) {
|
||||
def source = presentationFile.getAbsolutePath()
|
||||
def dest = presentationFile.parent + File.separatorChar + "slide-" + page + ".swf"
|
||||
|
||||
def command = swfToolsDir + "/pdf2swf -p " + page + " " + source + " -o " + dest
|
||||
log.debug "Executing $command"
|
||||
def process = Runtime.getRuntime().exec(command)
|
||||
|
||||
// Wait for the process to finish
|
||||
int exitValue = process.waitFor()
|
||||
|
||||
File destFile = new File(dest)
|
||||
if (destFile.exists()) return true
|
||||
return false
|
||||
}
|
||||
|
||||
public boolean createThumbnails(File presentationFile) {
|
||||
try {
|
||||
log.debug "Creating thumbnails:"
|
||||
def thumbsDir = new File(presentationFile.getParent() + File.separatorChar + "thumbnails")
|
||||
thumbsDir.mkdir()
|
||||
|
||||
def source = presentationFile.getAbsolutePath()
|
||||
def dest = thumbsDir.getAbsolutePath() + "/temp-thumb.png"
|
||||
|
||||
def command = imageMagickDir + "/convert -thumbnail 150x150 " + source + " " + dest
|
||||
log.debug "Executing $command"
|
||||
Process p = Runtime.getRuntime().exec(command);
|
||||
int exitValue = p.waitFor()
|
||||
|
||||
renameThumbnails(thumbsDir)
|
||||
|
||||
if (exitValue == 0) return true
|
||||
|
||||
return false
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
log.error "exception happened - here's what I know: "
|
||||
log.error e.printStackTrace()
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
private renameThumbnails(File dir) {
|
||||
dir.eachFile{file ->
|
||||
// filename should be something like 'c:/temp/bigluebutton/presname/thumbnails/temp-thumb-1.png'
|
||||
def filename = file.absolutePath
|
||||
|
||||
// Extract the page number. There should be 3 matches.
|
||||
// 1. c:/temp/bigluebutton/presname/thumbnails/temp-thumb
|
||||
// 2. 1 ---> what we are interested in
|
||||
// 3. .png
|
||||
def infoRegExp = /(.+-thumb)-([0-9]+)(.png)/
|
||||
def matcher = (filename =~ infoRegExp)
|
||||
if (matcher.matches()) {
|
||||
// We are interested in the second match.
|
||||
int pageNum = new Integer(matcher[0][2]).intValue()
|
||||
def newFilename = "thumb-${++pageNum}.png"
|
||||
File renamedFile = new File(file.parent + File.separator + newFilename)
|
||||
file.renameTo(renamedFile)
|
||||
}
|
||||
}
|
||||
|
||||
private void generateBlankSlide(String dest) {
|
||||
File slide = new File(dest);
|
||||
FileCopyUtils.copy(new File(BLANK_SLIDE), slide);
|
||||
}
|
||||
|
||||
private sendJmsMessage(HashMap message) {
|
||||
|
@ -0,0 +1,47 @@
|
||||
|
||||
package org.bigbluebutton.presentation
|
||||
|
||||
|
||||
public class GhostscriptPageExtractor implements PageExtractor{
|
||||
|
||||
private String GHOSTSCRIPT_EXEC
|
||||
private String noPdfMarkWorkaround
|
||||
|
||||
public boolean extractPage(File presentationFile, File output, int page){
|
||||
|
||||
String OPTIONS = "-sDEVICE=pdfwrite -dNOPAUSE -dQUIET -dBATCH"
|
||||
String PAGE = "-dFirstPage=${page} -dLastPage=${page}"
|
||||
String dest = output.getAbsolutePath()
|
||||
|
||||
//extract that specific page and create a temp-pdf(only one page) with GhostScript
|
||||
def command = GHOSTSCRIPT_EXEC + " " + OPTIONS + " " + PAGE + " " + "-sOutputFile=${dest}" + " " + noPdfMarkWorkaround + " " + presentationFile
|
||||
println "Executing $command"
|
||||
|
||||
def process
|
||||
int exitVal = -1
|
||||
|
||||
try {
|
||||
process = Runtime.getRuntime().exec(command);
|
||||
|
||||
// Wait for the process to finish.
|
||||
exitVal = process.waitFor()
|
||||
|
||||
} catch (InterruptedException e) {
|
||||
System.out.println(e.toString());
|
||||
}
|
||||
|
||||
if (exitVal == 0) {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
public void setGhostscriptExec(String exec) {
|
||||
GHOSTSCRIPT_EXEC = exec
|
||||
}
|
||||
|
||||
public void setNoPdfMarkWorkaround(String noPdfMarkWorkaround) {
|
||||
this.noPdfMarkWorkaround = noPdfMarkWorkaround
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
|
||||
package org.bigbluebutton.presentation
|
||||
|
||||
|
||||
public class ImageMagickPageConverter implements PageConverter{
|
||||
|
||||
private String IMAGEMAGICK_DIR
|
||||
|
||||
public boolean convert(File presentationFile, File output, int page){
|
||||
|
||||
def now = new Date()
|
||||
println "IMAGEMAGICK starting $now"
|
||||
|
||||
def command = IMAGEMAGICK_DIR + "/convert -depth 8 " + presentationFile.getAbsolutePath() + " " + output.getAbsolutePath()
|
||||
println "Executing $command"
|
||||
def process = Runtime.getRuntime().exec(command);
|
||||
// Wait for the process to finish.
|
||||
int exitValue = process.waitFor()
|
||||
|
||||
now = new Date()
|
||||
println "IMAGEMAGICK ends $now"
|
||||
|
||||
if (output.exists()) return true
|
||||
return false
|
||||
}
|
||||
|
||||
public void setImageMagickDir(String dir) {
|
||||
IMAGEMAGICK_DIR = dir
|
||||
}
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
|
||||
package org.bigbluebutton.presentation
|
||||
|
||||
|
||||
public class Jpeg2SwfPageConverter implements PageConverter{
|
||||
|
||||
private String SWFTOOLS_DIR
|
||||
|
||||
public boolean convert(File presentationFile, File output, int page){
|
||||
|
||||
def now = new Date()
|
||||
println "JPEG2SWF starting $now"
|
||||
|
||||
def command = SWFTOOLS_DIR + "/jpeg2swf -o " + output.getAbsolutePath() + " " + presentationFile.getAbsolutePath()
|
||||
println "Executing $command"
|
||||
def process = Runtime.getRuntime().exec(command);
|
||||
|
||||
// Wait for the process to finish.
|
||||
int exitValue = process.waitFor()
|
||||
|
||||
now = new Date()
|
||||
println "JPEG2SWF ended $now"
|
||||
|
||||
if (output.exists()) return true
|
||||
return false
|
||||
}
|
||||
|
||||
public void setSwfToolsDir(String dir) {
|
||||
SWFTOOLS_DIR = dir
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
package org.bigbluebutton.presentation;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public interface PageConverter {
|
||||
|
||||
public boolean convert(File presentation, File output, int page);
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
package org.bigbluebutton.presentation;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public interface PageCounter {
|
||||
|
||||
public int countNumberOfPages(File presentation);
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
package org.bigbluebutton.presentation;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public interface PageExtractor {
|
||||
|
||||
public boolean extractPage(File presentationFile, File output, int page);
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
|
||||
package org.bigbluebutton.presentation
|
||||
|
||||
import org.springframework.util.FileCopyUtils
|
||||
|
||||
public class Pdf2SwfPageConverter implements PageConverter {
|
||||
|
||||
private String SWFTOOLS_DIR;
|
||||
private String blankSlide;
|
||||
|
||||
public boolean convert(File presentation, File output, int page) {
|
||||
String source = presentation.getAbsolutePath();
|
||||
//String dest = presentation.getParent() + File.separatorChar + "slide-" + page + ".swf";
|
||||
String dest = output.getAbsolutePath()
|
||||
|
||||
String command = SWFTOOLS_DIR + File.separator + "pdf2swf -p " + page + " " + source + " -o " + dest;
|
||||
System.out.println("Executing $command");
|
||||
|
||||
Process process;
|
||||
int exitValue = -1;
|
||||
|
||||
try {
|
||||
process = Runtime.getRuntime().exec(command);
|
||||
|
||||
// Wait for the process to finish
|
||||
exitValue = process.waitFor();
|
||||
|
||||
} catch (IOException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
} catch (InterruptedException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
// if (exitValue != 0) {
|
||||
// generateBlankSlide(dest);
|
||||
// }
|
||||
|
||||
File destFile = new File(dest);
|
||||
if (destFile.exists()) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public void generateBlankSlide(String dest) {
|
||||
File slide = new File(dest);
|
||||
|
||||
FileCopyUtils.copy(new File(blankSlide), slide);
|
||||
}
|
||||
|
||||
public void setSwfToolsDir(String dir) {
|
||||
SWFTOOLS_DIR = dir;
|
||||
}
|
||||
|
||||
public void setBlankSlide(String slide) {
|
||||
blankSlide = slide;
|
||||
}
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
|
||||
package org.bigbluebutton.presentation
|
||||
|
||||
|
||||
public class Pdf2SwfPageCounter implements PageCounter{
|
||||
|
||||
private String SWFTOOLS_DIR
|
||||
|
||||
public int countNumberOfPages(File presentationFile){
|
||||
def numPages = -1 //total numbers of this pdf, also used as errorcode(-1)
|
||||
|
||||
try
|
||||
{
|
||||
def command = SWFTOOLS_DIR + "/pdf2swf -I " + presentationFile.getAbsolutePath()
|
||||
println "Executing with waitFor $command"
|
||||
def p = Runtime.getRuntime().exec(command);
|
||||
|
||||
def stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
|
||||
def stdError = new BufferedReader(new InputStreamReader(p.getErrorStream()));
|
||||
def info
|
||||
def str //output information to console for stdInput and stdError
|
||||
while ((info = stdInput.readLine()) != null) {
|
||||
//The output would be something like this 'page=21 width=718.00 height=538.00'.
|
||||
//We need to extract the page number (i.e. 21) from it.
|
||||
def infoRegExp = /page=([0-9]+)(?: .+)/
|
||||
def matcher = (info =~ infoRegExp)
|
||||
if (matcher.matches()) {
|
||||
numPages = matcher[0][1]
|
||||
} else {
|
||||
println "no match info: ${info}"
|
||||
}
|
||||
}
|
||||
while ((info = stdError.readLine()) != null) {
|
||||
System.out.println("Got error getting info from file):\n");
|
||||
System.out.println(str);
|
||||
}
|
||||
stdInput.close();
|
||||
stdError.close();
|
||||
|
||||
// Wait for the process to finish.
|
||||
int exitVal = p.waitFor()
|
||||
}
|
||||
catch (IOException e) {
|
||||
System.out.println("exception happened - here's what I know: ");
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return new Integer(numPages).intValue()
|
||||
}
|
||||
|
||||
public void setSwfToolsDir(String dir) {
|
||||
SWFTOOLS_DIR = dir;
|
||||
}
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
|
||||
package org.bigbluebutton.presentation
|
||||
|
||||
|
||||
public class Png2SwfPageConverter implements PageConverter{
|
||||
|
||||
private String SWFTOOLS_DIR
|
||||
|
||||
public boolean convert(File presentationFile, File output, int page){
|
||||
|
||||
def now = new Date()
|
||||
println "PNG2SWF starting $now"
|
||||
|
||||
def command = SWFTOOLS_DIR + "/png2swf -o " + output.getAbsolutePath() + " " + presentationFile.getAbsolutePath()
|
||||
println "Executing $command"
|
||||
def process = Runtime.getRuntime().exec(command);
|
||||
|
||||
// Wait for the process to finish.
|
||||
int exitValue = process.waitFor()
|
||||
|
||||
now = new Date()
|
||||
println "PNG2SWF ended $now"
|
||||
|
||||
if (output.exists()) return true
|
||||
return false
|
||||
}
|
||||
|
||||
public void setSwfToolsDir(String dir) {
|
||||
SWFTOOLS_DIR = dir
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* BigBlueButton - http://www.bigbluebutton.org
|
||||
*
|
||||
* Copyright (c) 2008-2009 by respective authors (see below). All rights reserved.
|
||||
*
|
||||
* BigBlueButton 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 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, If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* $Id: $
|
||||
*/
|
||||
package org.bigbluebutton.presentation;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public interface ThumbnailCreator {
|
||||
|
||||
public boolean createThumbnails(File presentationFile, int pageCount);
|
||||
}
|
@ -0,0 +1,124 @@
|
||||
/*
|
||||
* BigBlueButton - http://www.bigbluebutton.org
|
||||
*
|
||||
* Copyright (c) 2008-2009 by respective authors (see below). All rights reserved.
|
||||
*
|
||||
* BigBlueButton 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 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, If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* $Id: $
|
||||
*/
|
||||
package org.bigbluebutton.presentation
|
||||
|
||||
import org.springframework.util.FileCopyUtils
|
||||
|
||||
public class ThumbnailCreatorImp implements ThumbnailCreator {
|
||||
|
||||
String imageMagickDir
|
||||
String blankThumbnail
|
||||
|
||||
private static String TEMP_THUMB_NAME = "temp-thumb"
|
||||
|
||||
public boolean createThumbnails(File presentationFile, int pageCount){
|
||||
boolean success = false
|
||||
File thumbsDir = determineThumbnailDirectory(presentationFile)
|
||||
|
||||
if (! thumbsDir.exists())
|
||||
thumbsDir.mkdir()
|
||||
|
||||
cleanDirectory(thumbsDir)
|
||||
|
||||
try {
|
||||
success = generateThumbnails(thumbsDir, presentationFile)
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
println "exception happened - here's what I know: "
|
||||
println e.printStackTrace()
|
||||
success = false
|
||||
}
|
||||
|
||||
if (! success) createBlankThumbnails(thumbsDir, pageCount)
|
||||
|
||||
renameThumbnails(thumbsDir)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
private def generateThumbnails(File thumbsDir, File presentationFile) throws InterruptedException {
|
||||
println "Creating thumbnails:"
|
||||
|
||||
def source = presentationFile.getAbsolutePath()
|
||||
def dest = thumbsDir.getAbsolutePath() + "/${TEMP_THUMB_NAME}.png"
|
||||
|
||||
def command = imageMagickDir + "/convert -thumbnail 150x150 " + source + " " + dest
|
||||
println "Executing $command"
|
||||
Process p = Runtime.getRuntime().exec(command);
|
||||
|
||||
int exitValue = p.waitFor()
|
||||
|
||||
if (exitValue == 0) return true
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
private File determineThumbnailDirectory(File presentationFile) {
|
||||
return new File(presentationFile.getParent() + File.separatorChar + "thumbnails")
|
||||
}
|
||||
|
||||
private def renameThumbnails(File dir) {
|
||||
|
||||
dir.eachFile{ file ->
|
||||
// filename should be something like 'c:/temp/bigluebutton/presname/thumbnails/temp-thumb-1.png'
|
||||
def filename = file.absolutePath
|
||||
|
||||
// Extract the page number. There should be 3 matches.
|
||||
// 1. c:/temp/bigluebutton/presname/thumbnails/temp-thumb
|
||||
// 2. 1 ---> what we are interested in
|
||||
// 3. .png
|
||||
def infoRegExp = /(.+-thumb)-([0-9]+)(.png)/
|
||||
def matcher = (filename =~ infoRegExp)
|
||||
if (matcher.matches()) {
|
||||
// We are interested in the second match.
|
||||
int pageNum = new Integer(matcher[0][2]).intValue()
|
||||
println "Renaming thumnail ${pageNum}"
|
||||
def newFilename = "thumb-${++pageNum}.png"
|
||||
File renamedFile = new File(file.parent + File.separator + newFilename)
|
||||
file.renameTo(renamedFile)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def createBlankThumbnails(File thumbsDir, int pageCount) {
|
||||
println "Creating blank thumbnail"
|
||||
File[] thumbs = thumbsDir.listFiles();
|
||||
|
||||
if (thumbs.length != pageCount) {
|
||||
for (int i = 0; i < pageCount; i++) {
|
||||
File thumb = new File(thumbsDir.absolutePath + File.separator + "${TEMP_THUMB_NAME}-${i}.png")
|
||||
if (! thumb.exists()) {
|
||||
copyBlankThumbnail(thumb);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void copyBlankThumbnail(File thumb) {
|
||||
FileCopyUtils.copy(new File(blankThumbnail), thumb)
|
||||
}
|
||||
|
||||
private def cleanDirectory = {directory ->
|
||||
File[] files = directory.listFiles();
|
||||
for (int i = 0; i < files.length; i++) {
|
||||
files[i].delete()
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
|
||||
package org.bigbluebutton.presentation
|
||||
|
||||
final class Util{
|
||||
|
||||
static def deleteDirectory(File directory) {
|
||||
/**
|
||||
* Go through each directory and check if it's not empty.
|
||||
* We need to delete files inside a directory before a
|
||||
* directory can be deleted.
|
||||
**/
|
||||
File[] files = directory.listFiles();
|
||||
for (int i = 0; i < files.length; i++) {
|
||||
if (files[i].isDirectory()) {
|
||||
deleteDirectory(files[i])
|
||||
} else {
|
||||
files[i].delete()
|
||||
}
|
||||
}
|
||||
// Now that the directory is empty. Delete it.
|
||||
directory.delete()
|
||||
}
|
||||
|
||||
}
|
@ -3,6 +3,8 @@ package org.bigbluebutton.web.services
|
||||
import org.springframework.util.FileCopyUtils
|
||||
import org.codehaus.groovy.grails.commons.*
|
||||
|
||||
import groovy.mock.interceptor.StubFor
|
||||
|
||||
class PresentationServiceTests extends GroovyTestCase {
|
||||
|
||||
def SWFTOOLS = "C:/swftools-0.9"
|
||||
@ -11,7 +13,7 @@ class PresentationServiceTests extends GroovyTestCase {
|
||||
def PRESENTATIONDIR = "c:/temp/bigbluebutton"
|
||||
|
||||
def presService
|
||||
|
||||
|
||||
void setUp() {
|
||||
/* Get the values from bigbluebutton.properties
|
||||
* We have to set this manually unlike when running
|
||||
@ -31,6 +33,7 @@ class PresentationServiceTests extends GroovyTestCase {
|
||||
presService.presentationDir = PRESENTATIONDIR
|
||||
presService.noPdfMarkWorkaround = config.noPdfMarkWorkaround
|
||||
|
||||
presService.jmsTemplate = new FakeJmsTemplate()
|
||||
}
|
||||
|
||||
void testGetUploadDirectory() {
|
||||
@ -47,8 +50,7 @@ class PresentationServiceTests extends GroovyTestCase {
|
||||
assertTrue(uploadedPresentation.exists())
|
||||
}
|
||||
|
||||
void testGetNumberOfPagesForPresentation() {
|
||||
//def uploadedFilename = 'sample-presentation.pdf'
|
||||
void testPresentationThatShouldConvertSuccessfully() {
|
||||
def uploadedFilename = 'PresentationsTips.pdf'
|
||||
def uploadedFile = new File("test/resources/$uploadedFilename")
|
||||
def conf = "test-conf"
|
||||
@ -58,212 +60,95 @@ class PresentationServiceTests extends GroovyTestCase {
|
||||
File uploadDir = presService.uploadedPresentationDirectory(conf, rm, presName)
|
||||
def uploadedPresentation = new File(uploadDir.absolutePath + File.separator + uploadedFilename)
|
||||
uploadedPresentation = new File("$PRESENTATIONDIR/$conf/$rm/$presName/$uploadedFilename")
|
||||
|
||||
int copied = FileCopyUtils.copy(uploadedFile, uploadedPresentation)
|
||||
assertTrue(uploadedPresentation.exists())
|
||||
int numPages = presService.determineNumberOfPages(uploadedPresentation)
|
||||
//assertEquals 21, numPages
|
||||
}
|
||||
/*
|
||||
void testConvertUsingPdf2Swf() {
|
||||
def uploadedFilename = 'sample-presentation.pdf'
|
||||
def uploadedFile = new File("test/resources/$uploadedFilename")
|
||||
def conf = "test-conf"
|
||||
def rm = "test-room"
|
||||
def presName = "test-presentation"
|
||||
|
||||
File uploadDir = presService.uploadedPresentationDirectory(conf, rm, presName)
|
||||
def uploadedPresentation = new File(uploadDir.absolutePath + File.separator + uploadedFilename)
|
||||
uploadedPresentation = new File("$PRESENTATIONDIR/$conf/$rm/$presName/$uploadedFilename")
|
||||
int copied = FileCopyUtils.copy(uploadedFile, uploadedPresentation)
|
||||
assertTrue(uploadedPresentation.exists())
|
||||
int numPages = presService.determineNumberOfPages(uploadedPresentation)
|
||||
assertEquals 8, numPages
|
||||
|
||||
for (int page = 1; page <= numPages; page++) {
|
||||
presService.convertUsingPdf2Swf(uploadedPresentation, page)
|
||||
}
|
||||
|
||||
presService.convertUploadedPresentation(rm, presName, uploadedPresentation, 21)
|
||||
|
||||
int numPages = presService.numberOfThumbnails(conf, rm, presName)
|
||||
assertEquals 21, numPages
|
||||
}
|
||||
|
||||
void testExtractPageUsingGhostscript() {
|
||||
def uploadedFilename = 'sample-presentation.pdf'
|
||||
def uploadedFile = new File("test/resources/$uploadedFilename")
|
||||
def conf = "test-conf"
|
||||
def rm = "test-room"
|
||||
def presName = "test-presentation"
|
||||
|
||||
File uploadDir = presService.uploadedPresentationDirectory(conf, rm, presName)
|
||||
def uploadedPresentation = new File(uploadDir.absolutePath + File.separator + uploadedFilename)
|
||||
uploadedPresentation = new File("$PRESENTATIONDIR/$conf/$rm/$presName/$uploadedFilename")
|
||||
int copied = FileCopyUtils.copy(uploadedFile, uploadedPresentation)
|
||||
assertTrue(uploadedPresentation.exists())
|
||||
int numPages = presService.determineNumberOfPages(uploadedPresentation)
|
||||
assertEquals 8, numPages
|
||||
|
||||
for (int page = 1; page <= numPages; page++) {
|
||||
def result = presService.extractPageUsingGhostScript(uploadedPresentation, page)
|
||||
assertTrue result
|
||||
}
|
||||
|
||||
File tempdir = new File(uploadedPresentation.parent + File.separator + "temp")
|
||||
FilenameFilter filter = new PdfFilter();
|
||||
String[] files = tempdir.list(filter)
|
||||
assertEquals numPages, files.length
|
||||
|
||||
for (int page = 1; page <= numPages; page++) {
|
||||
def result = presService.convertUsingImageMagick(uploadedPresentation, page)
|
||||
assertTrue result
|
||||
}
|
||||
|
||||
filter = new JpegFilter();
|
||||
files = tempdir.list(filter)
|
||||
assertEquals numPages, files.length
|
||||
|
||||
for (int page = 1; page <= numPages; page++) {
|
||||
def result = presService.convertUsingJpeg2Swf(uploadedPresentation, page)
|
||||
assertTrue result
|
||||
}
|
||||
|
||||
File outDir = new File(uploadedPresentation.parent)
|
||||
filter = new SwfFilter();
|
||||
files = outDir.list(filter)
|
||||
assertEquals numPages, files.length
|
||||
}
|
||||
|
||||
void testProcessOneSlideWithTooManyObjectsPresentation() {
|
||||
void testProcessOneSlideWithTooManyObjectsPresentation() {
|
||||
def uploadedFilename = 'big.pdf'
|
||||
def uploadedFile = new File("test/resources/$uploadedFilename")
|
||||
def conf = "test-conf"
|
||||
def rm = "test-room"
|
||||
def presName = "big"
|
||||
|
||||
|
||||
File uploadDir = presService.uploadedPresentationDirectory(conf, rm, presName)
|
||||
def uploadedPresentation = new File(uploadDir.absolutePath + File.separator + uploadedFilename)
|
||||
uploadedPresentation = new File("$PRESENTATIONDIR/$conf/$rm/$presName/$uploadedFilename")
|
||||
int copied = FileCopyUtils.copy(uploadedFile, uploadedPresentation)
|
||||
assertTrue(uploadedPresentation.exists())
|
||||
int numPages = presService.determineNumberOfPages(uploadedPresentation)
|
||||
assertEquals 1, numPages
|
||||
|
||||
for (int page = 1; page <= numPages; page++) {
|
||||
presService.extractPageUsingGhostScript(uploadedPresentation, page)
|
||||
}
|
||||
|
||||
File tempdir = new File(uploadedPresentation.parent + File.separator + "temp")
|
||||
FilenameFilter filter = new PdfFilter();
|
||||
String[] files = tempdir.list(filter)
|
||||
assertEquals numPages, files.length
|
||||
|
||||
for (int page = 1; page <= numPages; page++) {
|
||||
presService.convertUsingImageMagick(uploadedPresentation, page)
|
||||
}
|
||||
|
||||
filter = new JpegFilter();
|
||||
files = tempdir.list(filter)
|
||||
assertEquals numPages, files.length
|
||||
|
||||
for (int page = 1; page <= numPages; page++) {
|
||||
presService.convertUsingJpeg2Swf(uploadedPresentation, page)
|
||||
}
|
||||
|
||||
File outDir = new File(uploadedPresentation.parent)
|
||||
filter = new SwfFilter();
|
||||
files = outDir.list(filter)
|
||||
assertEquals numPages, files.length
|
||||
}
|
||||
|
||||
|
||||
void testProcessSeveralSlidesWithTooManyObjectsPresentation() {
|
||||
def uploadedFilename = 'SeveralBigPagesPresentation.pdf'
|
||||
def uploadedFile = new File("test/resources/$uploadedFilename")
|
||||
def conf = "test-conf"
|
||||
def rm = "test-room"
|
||||
def presName = "severalbig"
|
||||
|
||||
File uploadDir = presService.uploadedPresentationDirectory(conf, rm, presName)
|
||||
def uploadedPresentation = new File(uploadDir.absolutePath + File.separator + uploadedFilename)
|
||||
uploadedPresentation = new File("$PRESENTATIONDIR/$conf/$rm/$presName/$uploadedFilename")
|
||||
int copied = FileCopyUtils.copy(uploadedFile, uploadedPresentation)
|
||||
assertTrue(uploadedPresentation.exists())
|
||||
int numPages = presService.determineNumberOfPages(uploadedPresentation)
|
||||
assertEquals 5, numPages
|
||||
|
||||
for (int page = 1; page <= numPages; page++) {
|
||||
presService.extractPageUsingGhostScript(uploadedPresentation, page)
|
||||
}
|
||||
|
||||
File tempdir = new File(uploadedPresentation.parent + File.separator + "temp")
|
||||
FilenameFilter filter = new PdfFilter();
|
||||
String[] files = tempdir.list(filter)
|
||||
assertEquals numPages, files.length
|
||||
|
||||
for (int page = 1; page <= numPages; page++) {
|
||||
presService.convertUsingImageMagick(uploadedPresentation, page)
|
||||
}
|
||||
|
||||
filter = new JpegFilter();
|
||||
files = tempdir.list(filter)
|
||||
assertEquals numPages, files.length
|
||||
|
||||
for (int page = 1; page <= numPages; page++) {
|
||||
presService.convertUsingJpeg2Swf(uploadedPresentation, page)
|
||||
}
|
||||
|
||||
File outDir = new File(uploadedPresentation.parent)
|
||||
filter = new SwfFilter();
|
||||
files = outDir.list(filter)
|
||||
assertEquals numPages, files.length
|
||||
}
|
||||
|
||||
|
||||
void testConvertPage() {
|
||||
def uploadedFilename = 'SeveralBigPagesPresentation.pdf'
|
||||
def uploadedFile = new File("test/resources/$uploadedFilename")
|
||||
def conf = "test-conf"
|
||||
def rm = "test-room"
|
||||
def presName = "convertpage"
|
||||
|
||||
File uploadDir = presService.uploadedPresentationDirectory(conf, rm, presName)
|
||||
def uploadedPresentation = new File(uploadDir.absolutePath + File.separator + uploadedFilename)
|
||||
uploadedPresentation = new File("$PRESENTATIONDIR/$conf/$rm/$presName/$uploadedFilename")
|
||||
int copied = FileCopyUtils.copy(uploadedFile, uploadedPresentation)
|
||||
assertTrue(uploadedPresentation.exists())
|
||||
int numPages = presService.determineNumberOfPages(uploadedPresentation)
|
||||
assertEquals 5, numPages
|
||||
|
||||
for (int page = 1; page <= numPages; page++) {
|
||||
presService.convertPage(uploadedPresentation, page)
|
||||
}
|
||||
|
||||
File outDir = new File(uploadedPresentation.parent)
|
||||
FilenameFilter filter = new SwfFilter();
|
||||
String[] files = outDir.list(filter)
|
||||
assertEquals numPages, files.length
|
||||
}
|
||||
|
||||
void testCreateThumbnails() {
|
||||
def uploadedFilename = 'SeveralBigPagesPresentation.pdf'
|
||||
def uploadedFile = new File("test/resources/$uploadedFilename")
|
||||
def conf = "test-conf"
|
||||
def rm = "test-room"
|
||||
def presName = "thumbs"
|
||||
|
||||
File uploadDir = presService.uploadedPresentationDirectory(conf, rm, presName)
|
||||
def uploadedPresentation = new File(uploadDir.absolutePath + File.separator + uploadedFilename)
|
||||
uploadedPresentation = new File("$PRESENTATIONDIR/$conf/$rm/$presName/$uploadedFilename")
|
||||
int copied = FileCopyUtils.copy(uploadedFile, uploadedPresentation)
|
||||
assertTrue(uploadedPresentation.exists())
|
||||
int numPages = presService.determineNumberOfPages(uploadedPresentation)
|
||||
assertEquals 5, numPages
|
||||
|
||||
presService.createThumbnails(uploadedPresentation)
|
||||
uploadedPresentation = new File("$PRESENTATIONDIR/$conf/$rm/$presName/$uploadedFilename")
|
||||
|
||||
|
||||
// File outDir = new File(uploadedPresentation.parent)
|
||||
// FilenameFilter filter = new SwfFilter();
|
||||
// String[] files = outDir.list(filter)
|
||||
// assertEquals numPages, files.length
|
||||
}
|
||||
*/
|
||||
int copied = FileCopyUtils.copy(uploadedFile, uploadedPresentation)
|
||||
assertTrue(uploadedPresentation.exists())
|
||||
|
||||
presService.convertUploadedPresentation(rm, presName, uploadedPresentation, 1)
|
||||
|
||||
int numPages = presService.numberOfThumbnails(conf, rm, presName)
|
||||
assertEquals 1, numPages
|
||||
}
|
||||
|
||||
void testProcessSeveralSlidesWithTooManyObjectsPresentation() {
|
||||
def uploadedFilename = 'SeveralBigPagesPresentation.pdf'
|
||||
def uploadedFile = new File("test/resources/$uploadedFilename")
|
||||
def conf = "test-conf"
|
||||
def rm = "test-room"
|
||||
def presName = "severalbig"
|
||||
|
||||
File uploadDir = presService.uploadedPresentationDirectory(conf, rm, presName)
|
||||
def uploadedPresentation = new File(uploadDir.absolutePath + File.separator + uploadedFilename)
|
||||
uploadedPresentation = new File("$PRESENTATIONDIR/$conf/$rm/$presName/$uploadedFilename")
|
||||
|
||||
int copied = FileCopyUtils.copy(uploadedFile, uploadedPresentation)
|
||||
assertTrue(uploadedPresentation.exists())
|
||||
|
||||
presService.convertUploadedPresentation(rm, presName, uploadedPresentation, 5)
|
||||
|
||||
int numPages = presService.numberOfThumbnails(conf, rm, presName)
|
||||
assertEquals 5, numPages
|
||||
}
|
||||
|
||||
void testProcessSlidesWithNoAvailableFontsPresentation() {
|
||||
def uploadedFilename = 'CaratulasManualesNutrisol.pdf'
|
||||
def uploadedFile = new File("test/resources/$uploadedFilename")
|
||||
def conf = "test-conf"
|
||||
def rm = "test-room"
|
||||
def presName = "caratulas"
|
||||
|
||||
File uploadDir = presService.uploadedPresentationDirectory(conf, rm, presName)
|
||||
def uploadedPresentation = new File(uploadDir.absolutePath + File.separator + uploadedFilename)
|
||||
uploadedPresentation = new File("$PRESENTATIONDIR/$conf/$rm/$presName/$uploadedFilename")
|
||||
|
||||
int copied = FileCopyUtils.copy(uploadedFile, uploadedPresentation)
|
||||
assertTrue(uploadedPresentation.exists())
|
||||
|
||||
presService.convertUploadedPresentation(rm, presName, uploadedPresentation, 2)
|
||||
|
||||
int numPages = presService.numberOfThumbnails(conf, rm, presName)
|
||||
assertEquals 2, numPages
|
||||
}
|
||||
|
||||
void testUseJpegWhenPresentationHasLotOfObjects() {
|
||||
def uploadedFilename = 'big-lots-of-objects.pdf'
|
||||
def uploadedFile = new File("test/resources/$uploadedFilename")
|
||||
def conf = "test-conf"
|
||||
def rm = "test-room"
|
||||
def presName = "big-lots-of-objects"
|
||||
|
||||
File uploadDir = presService.uploadedPresentationDirectory(conf, rm, presName)
|
||||
def uploadedPresentation = new File(uploadDir.absolutePath + File.separator + uploadedFilename)
|
||||
uploadedPresentation = new File("$PRESENTATIONDIR/$conf/$rm/$presName/$uploadedFilename")
|
||||
|
||||
int copied = FileCopyUtils.copy(uploadedFile, uploadedPresentation)
|
||||
assertTrue(uploadedPresentation.exists())
|
||||
|
||||
presService.convertUploadedPresentation(rm, presName, uploadedPresentation, 2)
|
||||
|
||||
int numPages = presService.numberOfThumbnails(conf, rm, presName)
|
||||
assertEquals 2, numPages
|
||||
}
|
||||
}
|
||||
|
||||
/*** Helper classes **/
|
||||
@ -286,3 +171,8 @@ class SwfFilter implements FilenameFilter {
|
||||
return (name.endsWith(".swf"));
|
||||
}
|
||||
}
|
||||
|
||||
/* Stub for JmsTemplate */
|
||||
class FakeJmsTemplate {
|
||||
def convertAndSend(String queue, Map message) { /* do nothing */}
|
||||
}
|
||||
|
BIN
bigbluebutton-web/test/resources/CaratulasManualesNutrisol.pdf
Normal file
BIN
bigbluebutton-web/test/resources/CaratulasManualesNutrisol.pdf
Normal file
Binary file not shown.
15789
bigbluebutton-web/test/resources/big-lots-of-objects.pdf
Normal file
15789
bigbluebutton-web/test/resources/big-lots-of-objects.pdf
Normal file
File diff suppressed because one or more lines are too long
BIN
bigbluebutton-web/test/resources/blankpresentation.pdf
Normal file
BIN
bigbluebutton-web/test/resources/blankpresentation.pdf
Normal file
Binary file not shown.
BIN
bigbluebutton-web/test/resources/sampleslide.jpeg
Normal file
BIN
bigbluebutton-web/test/resources/sampleslide.jpeg
Normal file
Binary file not shown.
After Width: | Height: | Size: 39 KiB |
@ -0,0 +1,52 @@
|
||||
package org.bigbluebutton.presentation
|
||||
|
||||
import org.springframework.util.FileCopyUtils
|
||||
|
||||
class GhostscriptPageExtractorTests extends GroovyTestCase {
|
||||
|
||||
def pageExtractor
|
||||
def GS_EXEC = '/usr/bin/gs'
|
||||
static final String PRESENTATIONDIR = '/var/bigbluebutton'
|
||||
def noPdfMarkWorkaround = "/etc/bigbluebutton/nopdfmark.ps"
|
||||
|
||||
def conf = "test-conf"
|
||||
def rm = "test-room"
|
||||
def presName = "thumbs"
|
||||
def presDir
|
||||
|
||||
void setUp() {
|
||||
println "Test setup"
|
||||
pageExtractor = new GhostscriptPageExtractor()
|
||||
pageExtractor.setGhostscriptExec(GS_EXEC)
|
||||
pageExtractor.setNoPdfMarkWorkaround(noPdfMarkWorkaround)
|
||||
|
||||
presDir = new File("$PRESENTATIONDIR/$conf/$rm/$presName")
|
||||
if (presDir.exists()) Util.deleteDirectory(presDir)
|
||||
|
||||
presDir.mkdirs()
|
||||
}
|
||||
|
||||
void testExtractPage() {
|
||||
def uploadedFilename = 'SeveralBigPagesPresentation.pdf'
|
||||
def uploadedFile = new File("test/resources/$uploadedFilename")
|
||||
|
||||
def uploadedPresentation = new File(presDir.absolutePath + "/$uploadedFilename")
|
||||
int copied = FileCopyUtils.copy(uploadedFile, uploadedPresentation)
|
||||
assertTrue(uploadedPresentation.exists())
|
||||
|
||||
def tempDir = new File(uploadedPresentation.parent + File.separatorChar + "temp")
|
||||
tempDir.mkdir()
|
||||
|
||||
int page = 1
|
||||
File outFile = new File(tempDir.absolutePath + File.separator + "temp-${page}.pdf")
|
||||
|
||||
boolean success = pageExtractor.extractPage(uploadedPresentation, outFile, page)
|
||||
assertTrue success
|
||||
|
||||
page = 3
|
||||
outFile = new File(tempDir.absolutePath + File.separator + "temp-${page}.pdf")
|
||||
success = pageExtractor.extractPage(uploadedPresentation, outFile, page)
|
||||
assertTrue success
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
package org.bigbluebutton.presentation
|
||||
|
||||
import org.springframework.util.FileCopyUtils
|
||||
|
||||
class ImageMagickPageConverterTests extends GroovyTestCase {
|
||||
|
||||
def pageConverter
|
||||
def IMAGEMAGICK_DIR = '/usr/bin'
|
||||
static final String PRESENTATIONDIR = '/var/bigbluebutton'
|
||||
|
||||
def conf = "test-conf"
|
||||
def rm = "test-room"
|
||||
def presName = "thumbs"
|
||||
def presDir
|
||||
|
||||
void setUp() {
|
||||
println "Test setup"
|
||||
pageConverter = new ImageMagickPageConverter()
|
||||
pageConverter.setImageMagickDir(IMAGEMAGICK_DIR)
|
||||
|
||||
presDir = new File("$PRESENTATIONDIR/$conf/$rm/$presName")
|
||||
if (presDir.exists()) Util.deleteDirectory(presDir)
|
||||
|
||||
presDir.mkdirs()
|
||||
}
|
||||
|
||||
void testConvertSuccess() {
|
||||
def uploadedFilename = 'big.pdf'
|
||||
def uploadedFile = new File("test/resources/$uploadedFilename")
|
||||
|
||||
def uploadedPresentation = new File(presDir.absolutePath + "/$uploadedFilename")
|
||||
int copied = FileCopyUtils.copy(uploadedFile, uploadedPresentation)
|
||||
assertTrue(uploadedPresentation.exists())
|
||||
|
||||
def tempDir = new File(uploadedPresentation.getParent() + File.separatorChar + "temp")
|
||||
tempDir.mkdir()
|
||||
|
||||
int page = 1
|
||||
File outFile = new File(tempDir.getAbsolutePath() + "/temp-${page}.jpeg")
|
||||
|
||||
boolean success = pageConverter.convert(uploadedPresentation, outFile, page)
|
||||
assertTrue success
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
package org.bigbluebutton.presentation
|
||||
|
||||
import org.springframework.util.FileCopyUtils
|
||||
|
||||
class Jpeg2SwfPageConverterTests extends GroovyTestCase {
|
||||
|
||||
def pageConverter
|
||||
def SWFTOOLS_DIR = '/bin'
|
||||
def BLANK_SLIDE = '/var/bigbluebutton/blank/blank-slide.swf'
|
||||
static final String PRESENTATIONDIR = '/var/bigbluebutton'
|
||||
|
||||
def conf = "test-conf"
|
||||
def rm = "test-room"
|
||||
def presName = "thumbs"
|
||||
def presDir
|
||||
|
||||
void setUp() {
|
||||
println "Test setup"
|
||||
pageConverter = new Jpeg2SwfPageConverter()
|
||||
pageConverter.setSwfToolsDir(SWFTOOLS_DIR)
|
||||
|
||||
presDir = new File("$PRESENTATIONDIR/$conf/$rm/$presName")
|
||||
if (presDir.exists()) Util.deleteDirectory(presDir)
|
||||
|
||||
presDir.mkdirs()
|
||||
}
|
||||
|
||||
void testConvertSlidesSuccessfully() {
|
||||
def uploadedFilename = 'sampleslide.jpeg'
|
||||
def uploadedFile = new File("test/resources/$uploadedFilename")
|
||||
|
||||
def uploadedPresentation = new File("$PRESENTATIONDIR/$conf/$rm/$presName/$uploadedFilename")
|
||||
int copied = FileCopyUtils.copy(uploadedFile, uploadedPresentation)
|
||||
assertTrue(uploadedPresentation.exists())
|
||||
|
||||
int page = 1
|
||||
File output = new File(uploadedPresentation.getParent() + File.separatorChar + "slide-" + page + ".swf")
|
||||
|
||||
boolean success = pageConverter.convert(uploadedPresentation, output, page)
|
||||
assertTrue success
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,66 @@
|
||||
package org.bigbluebutton.presentation
|
||||
|
||||
import org.springframework.util.FileCopyUtils
|
||||
|
||||
class Pdf2SwfPageConverterTests extends GroovyTestCase {
|
||||
|
||||
def pageConverter
|
||||
def SWFTOOLS_DIR = '/bin'
|
||||
def BLANK_SLIDE = '/var/bigbluebutton/blank/blank-slide.swf'
|
||||
static final String PRESENTATIONDIR = '/var/bigbluebutton'
|
||||
|
||||
def conf = "test-conf"
|
||||
def rm = "test-room"
|
||||
def presName = "thumbs"
|
||||
def presDir
|
||||
|
||||
void setUp() {
|
||||
println "Test setup"
|
||||
pageConverter = new Pdf2SwfPageConverter()
|
||||
pageConverter.setSwfToolsDir(SWFTOOLS_DIR)
|
||||
pageConverter.setBlankSlide(BLANK_SLIDE)
|
||||
|
||||
presDir = new File("$PRESENTATIONDIR/$conf/$rm/$presName")
|
||||
if (presDir.exists()) Util.deleteDirectory(presDir)
|
||||
|
||||
presDir.mkdirs()
|
||||
}
|
||||
|
||||
void testConvertSlidesSuccessfully() {
|
||||
def uploadedFilename = 'SeveralBigPagesPresentation.pdf'
|
||||
def uploadedFile = new File("test/resources/$uploadedFilename")
|
||||
|
||||
def uploadedPresentation = new File("$PRESENTATIONDIR/$conf/$rm/$presName/$uploadedFilename")
|
||||
int copied = FileCopyUtils.copy(uploadedFile, uploadedPresentation)
|
||||
assertTrue(uploadedPresentation.exists())
|
||||
|
||||
int page = 1
|
||||
File output = new File(uploadedPresentation.getParent() + File.separatorChar + "slide-" + page + ".swf")
|
||||
|
||||
boolean success = pageConverter.convert(uploadedPresentation, output, page)
|
||||
assertTrue success
|
||||
|
||||
page = 3
|
||||
output = new File(uploadedPresentation.getParent() + File.separatorChar + "slide-" + page + ".swf")
|
||||
success = pageConverter.convert(uploadedPresentation, output, page)
|
||||
assertFalse success
|
||||
}
|
||||
|
||||
void testConvertSlidesFail() {
|
||||
def uploadedFilename = 'SeveralBigPagesPresentation.pdf'
|
||||
def uploadedFile = new File("test/resources/$uploadedFilename")
|
||||
|
||||
def uploadedPresentation = new File("$PRESENTATIONDIR/$conf/$rm/$presName/$uploadedFilename")
|
||||
int copied = FileCopyUtils.copy(uploadedFile, uploadedPresentation)
|
||||
assertTrue(uploadedPresentation.exists())
|
||||
|
||||
int page = 3
|
||||
File output = new File(uploadedPresentation.getParent() + File.separatorChar + "slide-" + page + ".swf")
|
||||
boolean success = pageConverter.convert(uploadedPresentation, output, page)
|
||||
assertFalse success
|
||||
}
|
||||
|
||||
void tearDown() {
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
package org.bigbluebutton.presentation
|
||||
|
||||
import org.springframework.util.FileCopyUtils
|
||||
|
||||
class Pdf2SwfPageCounterTests extends GroovyTestCase {
|
||||
|
||||
def pageCounter
|
||||
def SWFTOOLS_DIR = '/bin'
|
||||
static final String PRESENTATIONDIR = '/var/bigbluebutton'
|
||||
|
||||
def conf = "test-conf"
|
||||
def rm = "test-room"
|
||||
def presName = "thumbs"
|
||||
def presDir
|
||||
|
||||
void setUp() {
|
||||
println "Test setup"
|
||||
pageCounter = new Pdf2SwfPageCounter()
|
||||
pageCounter.setSwfToolsDir(SWFTOOLS_DIR)
|
||||
|
||||
presDir = new File("$PRESENTATIONDIR/$conf/$rm/$presName")
|
||||
if (presDir.exists()) Util.deleteDirectory(presDir)
|
||||
|
||||
presDir.mkdirs()
|
||||
}
|
||||
|
||||
|
||||
void testCountPresentationPages() {
|
||||
def uploadedFilename = 'SeveralBigPagesPresentation.pdf'
|
||||
def uploadedFile = new File("test/resources/$uploadedFilename")
|
||||
|
||||
def uploadedPresentation = new File(presDir.absolutePath + "/$uploadedFilename")
|
||||
int copied = FileCopyUtils.copy(uploadedFile, uploadedPresentation)
|
||||
assertTrue(uploadedPresentation.exists())
|
||||
|
||||
int numPages = pageCounter.countNumberOfPages(uploadedPresentation)
|
||||
|
||||
assertEquals 5, numPages
|
||||
}
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
package org.bigbluebutton.presentation
|
||||
|
||||
import org.springframework.util.FileCopyUtils
|
||||
|
||||
class ThumbnailCreatorImpTests extends GroovyTestCase {
|
||||
|
||||
ThumbnailCreator tc
|
||||
static final String IMAGEMAGICK_DIR = "/usr/bin"
|
||||
static final String PRESENTATIONDIR = '/var/bigbluebutton'
|
||||
static final String BLANK_THUMBNAIL = '/var/bigbluebutton/blank/blank-thumb.png'
|
||||
|
||||
void setUp() {
|
||||
println "Test setup"
|
||||
tc = new ThumbnailCreatorImp()
|
||||
tc.imageMagickDir = IMAGEMAGICK_DIR
|
||||
tc.blankThumbnail = BLANK_THUMBNAIL
|
||||
}
|
||||
|
||||
void testCreateThumbnails() {
|
||||
def uploadedFilename = 'SeveralBigPagesPresentation.pdf'
|
||||
def uploadedFile = new File("test/resources/$uploadedFilename")
|
||||
def conf = "test-conf"
|
||||
def rm = "test-room"
|
||||
def presName = "thumbs"
|
||||
|
||||
def uploadedPresentation = new File("$PRESENTATIONDIR/$conf/$rm/$presName/$uploadedFilename")
|
||||
int copied = FileCopyUtils.copy(uploadedFile, uploadedPresentation)
|
||||
assertTrue(uploadedPresentation.exists())
|
||||
|
||||
boolean success = tc.createThumbnails(uploadedPresentation, 5)
|
||||
|
||||
assertTrue success
|
||||
|
||||
}
|
||||
|
||||
void testFailToCreateThumbnails() {
|
||||
def uploadedFilename = 'Caratulas Manuales Nutrisol.pdf'
|
||||
def uploadedFile = new File("test/resources/$uploadedFilename")
|
||||
def conf = "test-conf"
|
||||
def rm = "test-room"
|
||||
def presName = "thumbs"
|
||||
|
||||
def uploadedPresentation = new File("$PRESENTATIONDIR/$conf/$rm/$presName/$uploadedFilename")
|
||||
int copied = FileCopyUtils.copy(uploadedFile, uploadedPresentation)
|
||||
assertTrue(uploadedPresentation.exists())
|
||||
|
||||
boolean success = tc.createThumbnails(uploadedPresentation, 2)
|
||||
|
||||
assertTrue success
|
||||
|
||||
}
|
||||
|
||||
void testCreateBlankThumbnails() {
|
||||
tc.createBlankThumbnails(new File("/var/bigbluebutton/test-conf/test-room/thumbs/thumbnails"), 5)
|
||||
}
|
||||
|
||||
void tearDown() {
|
||||
println "Test Teardown"
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user