From 4f84a7655d51e6947fc6d2ada419f7acfd3e0ac0 Mon Sep 17 00:00:00 2001 From: srosse <stephane.rosse@frentix.com> Date: Wed, 8 May 2019 12:05:45 +0200 Subject: [PATCH] OO-4052: allow to replace video with an URL --- .../org/olat/modules/video/VideoManager.java | 4 +- .../org/olat/modules/video/VideoMeta.java | 2 + .../video/manager/VideoManagerImpl.java | 57 +++++++++------ .../video/ui/VideoDisplayController.java | 3 +- .../video/ui/VideoResourceEditController.java | 72 ++++++++++++++++--- .../video/ui/VideoRuntimeController.java | 11 +++ .../video/ui/_i18n/LocalStrings_de.properties | 1 + .../video/ui/_i18n/LocalStrings_en.properties | 1 + .../repository/handlers/VideoHandler.java | 4 +- 9 files changed, 120 insertions(+), 35 deletions(-) diff --git a/src/main/java/org/olat/modules/video/VideoManager.java b/src/main/java/org/olat/modules/video/VideoManager.java index b6cddd98240..9a76681b7b6 100644 --- a/src/main/java/org/olat/modules/video/VideoManager.java +++ b/src/main/java/org/olat/modules/video/VideoManager.java @@ -419,7 +419,7 @@ public interface VideoManager { * @param videoResource * @param url */ - public RepositoryEntry updateVideoMetadata(RepositoryEntry entry, String url); + public RepositoryEntry updateVideoMetadata(RepositoryEntry entry, String url, VideoFormat format); /** * Update the duration of the video, in repository entry as expenditure of work @@ -431,6 +431,8 @@ public interface VideoManager { */ public RepositoryEntry updateVideoMetadata(RepositoryEntry entry, Long durationInSeconds); + public VideoMeta updateVideoMetadata(VideoMeta meta); + /** * Gets the all video repo entries. * diff --git a/src/main/java/org/olat/modules/video/VideoMeta.java b/src/main/java/org/olat/modules/video/VideoMeta.java index 975a581fe13..7c8167b896f 100644 --- a/src/main/java/org/olat/modules/video/VideoMeta.java +++ b/src/main/java/org/olat/modules/video/VideoMeta.java @@ -49,6 +49,8 @@ public interface VideoMeta extends CreateInfo { */ public String getUrl(); + public void setUrl(String url); + /** * @return width of transcoded video in pixel */ diff --git a/src/main/java/org/olat/modules/video/manager/VideoManagerImpl.java b/src/main/java/org/olat/modules/video/manager/VideoManagerImpl.java index 14a1e981ba3..bf30e8cc8f7 100644 --- a/src/main/java/org/olat/modules/video/manager/VideoManagerImpl.java +++ b/src/main/java/org/olat/modules/video/manager/VideoManagerImpl.java @@ -717,6 +717,11 @@ public class VideoManagerImpl implements VideoManager { } } + @Override + public VideoMeta updateVideoMetadata(VideoMeta meta) { + return videoMetadataDao.updateVideoMetadata(meta); + } + @Override public void updateVideoMetadata (OLATResource videoResource,VFSLeaf uploadVideo) { VideoMeta meta = getVideoMetadata(videoResource); @@ -755,31 +760,43 @@ public class VideoManagerImpl implements VideoManager { } @Override - public RepositoryEntry updateVideoMetadata(RepositoryEntry entry, String url) { + public RepositoryEntry updateVideoMetadata(RepositoryEntry entry, String url, VideoFormat format) { OLATResource videoResource = entry.getOlatResource(); - VFSLeaf videoFile = downloadTmpVideo(videoResource, url); - if(videoFile.exists() && videoFile.getSize() > 0) { - VideoMeta meta = videoMetadataDao.getVideoMetadata(videoResource); - meta.setSize(videoFile.getSize()); - - Size dimensions = movieService.getSize(videoFile, "mp4"); - if(dimensions != null) { - meta.setWidth(dimensions.getWidth()); - meta.setHeight(dimensions.getHeight()); + VideoMeta meta = videoMetadataDao.getVideoMetadata(videoResource); + meta.setUrl(url); + meta.setVideoFormat(format); + if(format == VideoFormat.mp4 || format == VideoFormat.panopto) { + VFSLeaf videoFile = downloadTmpVideo(videoResource, url); + if(videoFile.exists() && videoFile.getSize() > 0) { + meta.setSize(videoFile.getSize()); + + Size dimensions = movieService.getSize(videoFile, "mp4"); + if(dimensions != null) { + meta.setWidth(dimensions.getWidth()); + meta.setHeight(dimensions.getHeight()); + } + + long duration = movieService.getDuration(videoFile, "mp4"); + if(duration > 0) { + String length = Formatter.formatTimecode(duration); + meta.setLength(length); + entry = repositoryManager.setExpenditureOfWork(entry, length); + } + } else { + meta.setSize(0l); + meta.setWidth(800); + meta.setHeight(600); } - long duration = movieService.getDuration(videoFile, "mp4"); - if(duration > 0) { - String length = Formatter.formatTimecode(duration); - meta.setLength(length); - entry = repositoryManager.setExpenditureOfWork(entry, length); + if(videoFile.exists()) { + videoFile.deleteSilently(); } - videoMetadataDao.updateVideoMetadata(meta); - } - - if(videoFile.exists()) { - videoFile.deleteSilently(); + } else { + meta.setSize(0l); + meta.setWidth(800); + meta.setHeight(600); } + videoMetadataDao.updateVideoMetadata(meta); return entry; } diff --git a/src/main/java/org/olat/modules/video/ui/VideoDisplayController.java b/src/main/java/org/olat/modules/video/ui/VideoDisplayController.java index dc816bff6d6..c9cbc87911e 100644 --- a/src/main/java/org/olat/modules/video/ui/VideoDisplayController.java +++ b/src/main/java/org/olat/modules/video/ui/VideoDisplayController.java @@ -248,7 +248,8 @@ public class VideoDisplayController extends BasicController { * @param currentTime The start time in seconds (optional) */ protected void reloadVideo(UserRequest ureq) { - if(StringHelper.containsNonWhitespace(this.videoMetadata.getUrl())) { + videoMetadata = videoManager.getVideoMetadata(videoEntry.getOlatResource()); + if(StringHelper.containsNonWhitespace(videoMetadata.getUrl())) { loadVideo(ureq, videoMetadata.getUrl(), videoMetadata.getVideoFormat()); } else { //load video as VFSLeaf diff --git a/src/main/java/org/olat/modules/video/ui/VideoResourceEditController.java b/src/main/java/org/olat/modules/video/ui/VideoResourceEditController.java index 1087b9ec0ad..aff673765e5 100644 --- a/src/main/java/org/olat/modules/video/ui/VideoResourceEditController.java +++ b/src/main/java/org/olat/modules/video/ui/VideoResourceEditController.java @@ -24,18 +24,22 @@ import java.util.HashSet; import java.util.List; import java.util.Set; +import org.olat.core.commons.persistence.DB; import org.olat.core.commons.services.image.Size; import org.olat.core.commons.services.video.MovieService; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.form.flexible.FormItemContainer; import org.olat.core.gui.components.form.flexible.elements.FileElement; import org.olat.core.gui.components.form.flexible.elements.StaticTextElement; +import org.olat.core.gui.components.form.flexible.elements.TextElement; import org.olat.core.gui.components.form.flexible.impl.FormBasicController; import org.olat.core.gui.components.form.flexible.impl.FormEvent; import org.olat.core.gui.components.form.flexible.impl.FormLayoutContainer; import org.olat.core.gui.control.Controller; +import org.olat.core.gui.control.Event; import org.olat.core.gui.control.WindowControl; import org.olat.core.util.Formatter; +import org.olat.core.util.StringHelper; import org.olat.core.util.vfs.VFSContainer; import org.olat.core.util.vfs.VFSLeaf; import org.olat.core.util.vfs.VFSManager; @@ -46,13 +50,15 @@ import org.olat.modules.video.VideoModule; import org.olat.modules.video.VideoTranscoding; import org.olat.modules.video.manager.VideoManagerImpl; import org.olat.repository.RepositoryEntry; +import org.olat.repository.RepositoryManager; import org.olat.resource.OLATResource; import org.springframework.beans.factory.annotation.Autowired; /** * The Class VideoResourceEditController. - * @autor fkiefer fabian.kiefer@frentix.com * this class replaces an an existing video resource with another, * deletes existing transcodings and recreates them considering the new resolution + * + * @autor fkiefer fabian.kiefer@frentix.com */ public class VideoResourceEditController extends FormBasicController { @@ -63,33 +69,39 @@ public class VideoResourceEditController extends FormBasicController { } private static final String VIDEO_RESOURCE = "video.mp4"; + private VideoMeta meta; private VFSContainer vfsContainer; private OLATResource videoResource; private RepositoryEntry entry; + @Autowired + private DB dbInstance; @Autowired private VideoManager videoManager; @Autowired private VideoModule videoModule; @Autowired private MovieService movieService; + @Autowired + private RepositoryManager repositoryManager; + private TextElement urlEl; private StaticTextElement typeEl; private FileElement uploadFileEl; - public VideoResourceEditController(UserRequest ureq, WindowControl wControl, RepositoryEntry entry){ super(ureq, wControl); this.entry = entry; this.videoResource = entry.getOlatResource(); vfsContainer = videoManager.getMasterContainer(videoResource); + meta = videoManager.getVideoMetadata(videoResource); initForm(ureq); } @Override protected void doDispose() { - + // } @Override @@ -98,23 +110,42 @@ public class VideoResourceEditController extends FormBasicController { setFormDescription("video.replace.desc"); setFormContextHelp("ok"); - uploadFileEl = uifactory.addFileElement(getWindowControl(), "upload", "video.replace.upload", formLayout); - uploadFileEl.addActionListener(FormEvent.ONCHANGE); - uploadFileEl.limitToMimeType(videoMimeTypes, "video.mime.type.error", null); - + if(StringHelper.containsNonWhitespace(meta.getUrl())) { + urlEl = uifactory.addTextElement("video.config.url", 512, meta.getUrl(), formLayout); + } else { + uploadFileEl = uifactory.addFileElement(getWindowControl(), "upload", "video.replace.upload", formLayout); + uploadFileEl.addActionListener(FormEvent.ONCHANGE); + uploadFileEl.limitToMimeType(videoMimeTypes, "video.mime.type.error", null); + } typeEl = uifactory.addStaticTextElement("video.mime.type", "video.mime.type", "", formLayout); - typeEl.setVisible(false); + typeEl.setVisible(false); FormLayoutContainer buttonGroupLayout = FormLayoutContainer.createButtonLayout("buttons", getTranslator()); formLayout.add(buttonGroupLayout); uifactory.addFormSubmitButton("submit", "tab.video.exchange", buttonGroupLayout); } + + private void doReplaceURLAndUpdateMetadata() { + String url = urlEl.getValue(); + VideoFormat format = VideoFormat.valueOfUrl(url); + if(format == null) { + return;// cannot understand the URL + } + if(format == VideoFormat.panopto) { + url = videoManager.toPodcastVideoUrl(url); + } + + RepositoryEntry repoEntry = repositoryManager.lookupRepositoryEntry(videoResource, true); + videoManager.updateVideoMetadata(repoEntry, url, format); + dbInstance.commit(); + meta = videoManager.getVideoMetadata(videoResource); + } private int doReplaceFileAndUpdateMetadata() { VFSLeaf video = (VFSLeaf) vfsContainer.resolve(VIDEO_RESOURCE); File uploadFile = uploadFileEl.getUploadFile(); - VideoMeta meta = videoManager.getVideoMetadata(videoResource); + meta = videoManager.getVideoMetadata(videoResource); if (uploadFileEl.getUploadSize() > 0 && uploadFile.exists()){ video.delete(); VFSLeaf uploadVideo = vfsContainer.createChildLeaf(VIDEO_RESOURCE); @@ -160,9 +191,29 @@ public class VideoResourceEditController extends FormBasicController { } } + @Override + protected boolean validateFormLogic(UserRequest ureq) { + boolean allOk = super.validateFormLogic(ureq); + + if(urlEl != null) { + urlEl.clearError(); + if(!StringHelper.containsNonWhitespace(urlEl.getValue())) { + urlEl.setErrorKey("form.legende.mandatory", null); + allOk &= false; + } else if(VideoFormat.valueOfUrl(urlEl.getValue()) == null) { + urlEl.setErrorKey("error.format.not.supported", null); + allOk &= false; + } + } + + return allOk; + } + @Override protected void formOK(UserRequest ureq) { - if (uploadFileEl.getUploadFile() != null && uploadFileEl.isUploadSuccess()) { + if(urlEl != null) { + doReplaceURLAndUpdateMetadata(); + } else if (uploadFileEl != null && uploadFileEl.getUploadFile() != null && uploadFileEl.isUploadSuccess()) { queueDeleteTranscoding(); int height = doReplaceFileAndUpdateMetadata(); queueCreateTranscoding(height); @@ -173,5 +224,6 @@ public class VideoResourceEditController extends FormBasicController { typeEl.setVisible(false); showWarning("video.not.replaced"); } + fireEvent(ureq, Event.CHANGED_EVENT); } } diff --git a/src/main/java/org/olat/modules/video/ui/VideoRuntimeController.java b/src/main/java/org/olat/modules/video/ui/VideoRuntimeController.java index 4d39c849d5c..3a3c2b690f2 100644 --- a/src/main/java/org/olat/modules/video/ui/VideoRuntimeController.java +++ b/src/main/java/org/olat/modules/video/ui/VideoRuntimeController.java @@ -29,6 +29,7 @@ import org.olat.core.gui.components.link.Link; import org.olat.core.gui.components.link.LinkFactory; import org.olat.core.gui.components.stack.PopEvent; import org.olat.core.gui.components.stack.RootEvent; +import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.Event; import org.olat.core.gui.control.WindowControl; import org.olat.core.gui.control.generic.dtabs.Activateable2; @@ -107,6 +108,16 @@ public class VideoRuntimeController extends RepositoryEntryRuntimeController { doRefreshVideoPosterIfEntryAdmin(); } + @Override + protected void event(UserRequest ureq, Controller source, Event event) { + if(source instanceof VideoResourceEditController) { + if(event == Event.CHANGED_EVENT) { + VideoDisplayController videoDisplayCtr = (VideoDisplayController)getRuntimeController(); + videoDisplayCtr.reloadVideo(ureq); + } + } + } + private void doReplaceVideo (UserRequest ureq) { VideoResourceEditController resourceCtrl = new VideoResourceEditController(ureq, getWindowControl(), repositoryEntry); listenTo(resourceCtrl); diff --git a/src/main/java/org/olat/modules/video/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/modules/video/ui/_i18n/LocalStrings_de.properties index 2207546872a..5d6ad04c2e2 100644 --- a/src/main/java/org/olat/modules/video/ui/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/modules/video/ui/_i18n/LocalStrings_de.properties @@ -17,6 +17,7 @@ chapter.error.notime=Bitte geben Sie eine Zeit ein\! chapter.error.notitle=Bitte geben Sie einen Titel ein\! chapter.error.out.of.range=Ihre Zeitangabe \u00FCberschreitet die L\u00E4nge des Videos\! delete.transcodings=Alle Transcodings dieser Aufl\u00F6sung wurden gel\u00F6scht. +error.format.not.supported=Format ist nicht unterst\u00FCtzt. error.no.duration=Dauer must gr\u00F6sser als 0 sein. error.percent.value=Wert muss zwischen 0 und 100 sein. info.transcoding=Fehlende Transcodings werden erstellt. diff --git a/src/main/java/org/olat/modules/video/ui/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/modules/video/ui/_i18n/LocalStrings_en.properties index 91379b6c48c..2880ae633b0 100644 --- a/src/main/java/org/olat/modules/video/ui/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/modules/video/ui/_i18n/LocalStrings_en.properties @@ -17,6 +17,7 @@ chapter.error.notime=Please put a valid time\! chapter.error.notitle=Please set a valid Chapter Title\! chapter.error.out.of.range=Your Chapter Timecode exceeds the length of the Video\! delete.transcodings=All Transcodings of this Resolution have been deleted. +error.format.not.supported=Format is not supported. error.no.duration=Duration must be greater than 0. error.percent.value=Value nned to be between 0 and 100 info.transcoding=Missing Transcodings will be created. diff --git a/src/main/java/org/olat/repository/handlers/VideoHandler.java b/src/main/java/org/olat/repository/handlers/VideoHandler.java index 932dd4fb53f..3decc1c7eaa 100644 --- a/src/main/java/org/olat/repository/handlers/VideoHandler.java +++ b/src/main/java/org/olat/repository/handlers/VideoHandler.java @@ -203,9 +203,7 @@ public class VideoHandler extends FileHandler { videoManager.createVideoMetadata(repoEntry, url, format); dbInstance.commit(); - if(format == VideoFormat.mp4 || format == VideoFormat.panopto) { - repoEntry = videoManager.updateVideoMetadata(repoEntry, url); - } + repoEntry = videoManager.updateVideoMetadata(repoEntry, url, format); return repoEntry; } -- GitLab