/** * <a href="http://www.openolat.org"> * OpenOLAT - Online Learning and Training</a><br> * <p> * Licensed under the Apache License, Version 2.0 (the "License"); <br> * you may not use this file except in compliance with the License.<br> * You may obtain a copy of the License at the * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> * <p> * Unless required by applicable law or agreed to in writing,<br> * software distributed under the License is distributed on an "AS IS" BASIS, <br> * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> * See the License for the specific language governing permissions and <br> * limitations under the License. * <p> * Initial code contributed and copyrighted by<br> * frentix GmbH, http://www.frentix.com * <p> */ package org.olat.modules.video.ui; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.form.flexible.FormItem; import org.olat.core.gui.components.form.flexible.FormItemContainer; import org.olat.core.gui.components.form.flexible.elements.FlexiTableElement; 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.elements.table.BooleanCellRenderer; import org.olat.core.gui.components.form.flexible.impl.elements.table.DefaultFlexiColumnModel; import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableColumnModel; import org.olat.core.gui.components.form.flexible.impl.elements.table.FlexiTableDataModelFactory; import org.olat.core.gui.components.form.flexible.impl.elements.table.SelectionEvent; import org.olat.core.gui.components.form.flexible.impl.elements.table.StaticFlexiCellRenderer; import org.olat.core.gui.control.Controller; import org.olat.core.gui.control.WindowControl; import org.olat.modules.video.VideoManager; import org.olat.modules.video.VideoModule; import org.olat.modules.video.VideoTranscoding; import org.olat.modules.video.model.TranscodingCount; import org.olat.modules.video.model.VideoMetaImpl; import org.olat.modules.video.ui.TranscodingTableModel.TranscodingCols; import org.olat.resource.OLATResource; import org.springframework.beans.factory.annotation.Autowired; /** * The Class VideoAdminTranscodingController. * Initial Date: 25.10.2016 * @autor fkiefer fabian.kiefer@frentix.com * this class controls the transcondings of a kind, either delete all, * transcode all or only the missing */ public class VideoAdminTranscodingController extends FormBasicController { private TranscodingTableModel tableModel; private FlexiTableElement transcodingTable; private Map<OLATResource,Integer> nativeResolutions; @Autowired private VideoManager videoManager; @Autowired private VideoModule videoModule; public VideoAdminTranscodingController(UserRequest ureq, WindowControl wControl) { super(ureq, wControl, "transcoding_admin"); nativeResolutions = new HashMap<>(); List<VideoMetaImpl> olatresources = videoManager.getAllVideoResourcesMetadata(); //cache native resolutions for (VideoMetaImpl videoResource : olatresources) { nativeResolutions.put(videoResource.getVideoResource(), videoResource.getHeight()); } initForm(ureq); } @Override protected void initForm(FormItemContainer formLayout, Controller listener, UserRequest ureq) { setFormTitle("manage.transcodings.title"); setFormDescription("manage.transcodings.description"); setFormContextHelp("Portfolio template: Administration and editing#configuration"); FlexiTableColumnModel transcodingModel = FlexiTableDataModelFactory.createFlexiTableColumnModel(); transcodingModel.addFlexiColumnModel(new DefaultFlexiColumnModel(TranscodingCols.resolutions)); transcodingModel.addFlexiColumnModel(new DefaultFlexiColumnModel(TranscodingCols.sumVideos)); transcodingModel.addFlexiColumnModel(new DefaultFlexiColumnModel(TranscodingCols.numberTranscodings)); transcodingModel.addFlexiColumnModel(new DefaultFlexiColumnModel(TranscodingCols.failedTranscodings)); transcodingModel.addFlexiColumnModel(new DefaultFlexiColumnModel(TranscodingCols.missingTranscodings)); transcodingModel.addFlexiColumnModel(new DefaultFlexiColumnModel(TranscodingCols.transcode, "quality.transcode", new BooleanCellRenderer(new StaticFlexiCellRenderer(translate("quality.transcode"), "quality.transcode", "", "o_icon o_icon_refresh o_icon-fw"), null))); transcodingModel.addFlexiColumnModel(new DefaultFlexiColumnModel(TranscodingCols.delete, "quality.delete", new BooleanCellRenderer(new StaticFlexiCellRenderer(translate("quality.delete"), "quality.delete", "", "o_icon o_icon_delete_item o_icon-fw"), null))); tableModel = new TranscodingTableModel(transcodingModel, getTranslator()); transcodingTable = uifactory.addTableElement(getWindowControl(), "table", tableModel, getTranslator(), formLayout); transcodingTable.setCustomizeColumns(false); transcodingTable.setNumOfRowsEnabled(false); loadTable(); } private boolean mayTranscode(int resolution){ if (!videoModule.isTranscodingEnabled()) { return false; } int[] transcodingRes = videoModule.getTranscodingResolutions(); for (int i = 0; i < transcodingRes.length; i++) { if (resolution == transcodingRes[i]){ return true; } } return false; } private void loadTable() { List<TranscodingRow> resolutions = new ArrayList<>(); // Hardcoded same as VideoAdminSetController int[] fixresolution = { 2160, 1080, 720, 480, 360, 240 }; Map<Integer, Integer> successCount = new HashMap<>(); int beginErrorCode = VideoTranscoding.TRANSCODING_STATUS_INEFFICIENT; for (TranscodingCount transcodingCount : videoManager.getAllVideoTranscodingsCountSuccess(beginErrorCode)) { successCount.put(transcodingCount.getResolution(), transcodingCount.getCount()); } Map<Integer, Integer> failCount = new HashMap<>(); for (TranscodingCount transcodingCount : videoManager.getAllVideoTranscodingsCountFails(beginErrorCode)) { failCount.put(transcodingCount.getResolution(), transcodingCount.getCount()); } for (int i = 0; i < fixresolution.length; i++) { int counter = 0; for (OLATResource videoResource : nativeResolutions.keySet()) { if (nativeResolutions.get(videoResource) >= fixresolution[i]) counter++; } int success = successCount.get(fixresolution[i]) != null ? successCount.get(fixresolution[i]) : 0; int fails = failCount.get(fixresolution[i]) != null ? failCount.get(fixresolution[i]) : 0; TranscodingRow transcodingRow = new TranscodingRow(fixresolution[i], success, fails, counter, mayTranscode(fixresolution[i])); resolutions.add(transcodingRow); } if (resolutions != null){ tableModel.setObjects(resolutions); } transcodingTable.reset(true, true, true); } /** * Update Table Content of all available Transcodings */ public void reloadTable(){ loadTable(); } @Override protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) { if(source == transcodingTable) { if(event instanceof SelectionEvent) { SelectionEvent se = (SelectionEvent)event; TranscodingRow currentObject = (TranscodingRow) tableModel.getObject(se.getIndex()); if ("quality.delete".equals(se.getCommand())){ queueDeleteTranscoding(currentObject); showInfo("delete.transcodings"); } else if ("quality.transcode".equals(se.getCommand())){ queueCreateTranscoding(currentObject); showInfo("info.transcoding"); } } } reloadTable(); } // state orders for inexistent transcodings private void queueCreateTranscoding(TranscodingRow source) { List<VideoTranscoding> allVideoTranscodings = videoManager.getOneVideoResolution(source.getResolution()); Map<OLATResource, Set<Integer>> availableTranscodings = new HashMap<>(); for (VideoTranscoding videoTranscoding : allVideoTranscodings) { if (availableTranscodings.containsKey(videoTranscoding.getVideoResource())) { availableTranscodings.get(videoTranscoding.getVideoResource()).add(videoTranscoding.getResolution()); } else { Set<Integer> availableresolutions = new HashSet<>(); availableresolutions.add(videoTranscoding.getResolution()); availableTranscodings.put(videoTranscoding.getVideoResource(), availableresolutions); } } for (OLATResource videoResource : nativeResolutions.keySet()) { if (availableTranscodings.get(videoResource) == null || !availableTranscodings.get(videoResource).contains(source.getResolution())) { if (nativeResolutions.get(videoResource) >= source.getResolution()) { videoManager.createTranscoding(videoResource, source.getResolution(), "mp4"); } } } } //go through all and delete selection private void queueDeleteTranscoding(TranscodingRow source) { List<VideoTranscoding> allVideoTranscodings = videoManager.getOneVideoResolution(source.getResolution()); for (VideoTranscoding videoTranscoding : allVideoTranscodings) { if (videoTranscoding.getResolution() == source.getResolution()) { videoManager.deleteVideoTranscoding(videoTranscoding); } } } @Override protected void formOK(UserRequest ureq) { // nothing to do } @Override protected void doDispose() { // no controllers to clean up } }