Skip to content
Snippets Groups Projects
Commit d994dd99 authored by uhensler's avatar uhensler
Browse files

OO-4357: Configuration of the player layout

parent 077b2f44
No related branches found
No related tags found
No related merge requests found
Showing
with 418 additions and 32 deletions
......@@ -65,6 +65,7 @@ public class LiveStreamCourseNode extends AbstractAccessableCourseNode {
public static final String CONFIG_BUFFER_BEFORE_MIN = "bufferBeforeMin";
public static final String CONFIG_BUFFER_AFTER_MIN = "bufferBeforeAfter";
public static final String CONFIG_COACH_CAN_EDIT = "coachCanEdit";
public static final String CONFIG_PLAYER_PROFILE = "playerProfile";
public LiveStreamCourseNode() {
super(TYPE);
......@@ -130,6 +131,8 @@ public class LiveStreamCourseNode extends AbstractAccessableCourseNode {
config.setIntValue(CONFIG_BUFFER_BEFORE_MIN, liveStreamModule.getBufferBeforeMin());
config.setIntValue(CONFIG_BUFFER_AFTER_MIN, liveStreamModule.getBufferAfterMin());
config.setBooleanEntry(CONFIG_COACH_CAN_EDIT, liveStreamModule.isEditCoach());
// CONFIG_PLAYER_PROFILE has no default value, because previously the multi
// stream option has to be enabled and the default value has to be selected.
}
config.setConfigurationVersion(CURRENT_VERSION);
}
......
......@@ -37,13 +37,17 @@ import org.springframework.stereotype.Service;
public class LiveStreamModule extends AbstractSpringModule implements ConfigOnOff {
public static final String LIVE_STREAM_ENABLED = "live.stream.enabled";
public static final String LIVE_STREAM_MULTI_STREAM_ENABLED = "live.stream.multi.stream.enabled";
public static final String LIVE_STREAM_URL_SEPARATOR = "live.stream.url.separator";
public static final String LIVE_STREAM_BUFFER_BEFORE_MIN = "live.stream.buffer.before.min";
public static final String LIVE_STREAM_BUFFER_AFTER_MIN = "live.stream.buffer.after.min";
public static final String LIVE_STREAM_EDIT_COACH = "live.stream.edit.coach";
public static final String LIVE_STREAM_PLAYER_PROFILE = "live.stream.player.profile";
@Value("${live.stream.enabled:false}")
private boolean enabled;
@Value("${live.stream.multi.stream.enabled:false}")
private boolean multiStreamEnabled;
@Value("${live.stream.url.separator:,}")
private String urlSeparator;
@Value("${live.stream.buffer.before.min:5}")
......@@ -52,6 +56,8 @@ public class LiveStreamModule extends AbstractSpringModule implements ConfigOnOf
private int bufferAfterMin;
@Value("${live.stream.edit.coach:false}")
private boolean editCoach;
@Value("${live.stream.player.profile:both}")
private String playerProfile;
@Autowired
public LiveStreamModule(CoordinatorManager coordinatorManager) {
......@@ -65,6 +71,11 @@ public class LiveStreamModule extends AbstractSpringModule implements ConfigOnOf
enabled = "true".equals(enabledObj);
}
String multiStreamEnabledObj = getStringPropertyValue(LIVE_STREAM_MULTI_STREAM_ENABLED, true);
if(StringHelper.containsNonWhitespace(multiStreamEnabledObj)) {
multiStreamEnabled = "true".equals(multiStreamEnabledObj);
}
String urlSeparatorObj = getStringPropertyValue(LIVE_STREAM_URL_SEPARATOR, true);
if(StringHelper.containsNonWhitespace(urlSeparatorObj)) {
urlSeparator = urlSeparatorObj;
......@@ -84,6 +95,11 @@ public class LiveStreamModule extends AbstractSpringModule implements ConfigOnOf
if(StringHelper.containsNonWhitespace(editCoachObj)) {
editCoach = "true".equals(editCoachObj);
}
String playerProfileObj = getStringPropertyValue(LIVE_STREAM_PLAYER_PROFILE, true);
if(StringHelper.containsNonWhitespace(playerProfileObj)) {
playerProfile = playerProfileObj;
}
}
@Override
......@@ -101,6 +117,15 @@ public class LiveStreamModule extends AbstractSpringModule implements ConfigOnOf
setStringProperty(LIVE_STREAM_ENABLED, Boolean.toString(enabled), true);
}
public boolean isMultiStreamEnabled() {
return multiStreamEnabled;
}
public void setMultiStreamEnabled(boolean multiStreamEnabled) {
this.multiStreamEnabled = multiStreamEnabled;
setStringProperty(LIVE_STREAM_MULTI_STREAM_ENABLED, Boolean.toString(multiStreamEnabled), true);
}
public String getUrlSeparator() {
return urlSeparator;
}
......@@ -137,4 +162,13 @@ public class LiveStreamModule extends AbstractSpringModule implements ConfigOnOf
setStringProperty(LIVE_STREAM_EDIT_COACH, Boolean.toString(editCoach), true);
}
public String getPlayerProfile() {
return playerProfile;
}
public void setPlayerProfile(String playerProfile) {
this.playerProfile = playerProfile;
setStringProperty(LIVE_STREAM_PLAYER_PROFILE, playerProfile, true);
}
}
/**
* <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.course.nodes.livestream.manager;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadFactory;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import org.olat.commons.calendar.CalendarManager;
import org.olat.commons.calendar.CalendarUtils;
import org.olat.commons.calendar.model.KalendarEvent;
import org.olat.commons.calendar.ui.components.KalendarRenderWrapper;
import org.olat.course.nodes.cal.CourseCalendars;
import org.olat.course.nodes.livestream.LiveStreamEvent;
import org.olat.course.nodes.livestream.LiveStreamService;
import org.olat.course.nodes.livestream.model.LiveStreamEventImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.CustomizableThreadFactory;
import org.springframework.stereotype.Service;
/**
*
* Initial date: 28 May 2019<br>
* @author uhensler, urs.hensler@frentix.com, http://www.frentix.com
*
*/
@Service
public class LiveStreamServiceImpl implements LiveStreamService {
private ScheduledExecutorService scheduler;
@Autowired
private CalendarManager calendarManager;
@Override
public ScheduledExecutorService getScheduler() {
if (scheduler == null) {
ThreadFactory threadFactory = new CustomizableThreadFactory("oo-livestream-");
scheduler = Executors.newScheduledThreadPool(1, threadFactory);
}
return scheduler;
}
@Override
public List<? extends LiveStreamEvent> getRunningEvents(CourseCalendars calendars, int bufferBeforeMin,
int bufferAfterMin) {
Date now = new Date();
Calendar cFrom = Calendar.getInstance();
cFrom.setTime(now);
cFrom.add(Calendar.MINUTE, -bufferAfterMin);
Date from = cFrom.getTime();
Calendar cTo = Calendar.getInstance();
cTo.setTime(now);
cTo.add(Calendar.MINUTE, bufferBeforeMin);
Date to = cTo.getTime();
return getLiveStreamEvents(calendars, from, to);
}
@Override
public List<? extends LiveStreamEvent> getUpcomingEvents(CourseCalendars calendars, int bufferBeforeMin) {
Date now = new Date();
Calendar cFrom = Calendar.getInstance();
cFrom.setTime(now);
cFrom.add(Calendar.MINUTE, bufferBeforeMin);
Date from = cFrom.getTime();
Calendar cTo = Calendar.getInstance();
cTo.setTime(now);
cTo.add(Calendar.YEAR, 10);
Date to = cTo.getTime();
return getLiveStreamEvents(calendars, from, to).stream()
.filter(notStartedFilter(from))
.collect(Collectors.toList());
}
private Predicate<LiveStreamEvent> notStartedFilter(Date from) {
return (LiveStreamEvent e) -> {
return !e.getBegin().before(from);
};
}
private List<? extends LiveStreamEvent> getLiveStreamEvents(CourseCalendars calendars, Date from, Date to) {
List<LiveStreamEvent> liveStreamEvents = new ArrayList<>();
for (KalendarRenderWrapper cal : calendars.getCalendars()) {
if(cal != null) {
boolean privateEventsVisible = cal.isPrivateEventsVisible();
List<KalendarEvent> events = calendarManager.getEvents(cal.getKalendar(), from, to, privateEventsVisible);
for(KalendarEvent event:events) {
if(!privateEventsVisible && event.getClassification() == KalendarEvent.CLASS_PRIVATE) {
continue;
}
if (isLiveStream(event)) {
boolean timeOnly = !privateEventsVisible && event.getClassification() == KalendarEvent.CLASS_X_FREEBUSY;
LiveStreamEventImpl liveStreamEvent = toLiveStreamEvent(event, timeOnly);
liveStreamEvents.add(liveStreamEvent);
};
}
}
}
return liveStreamEvents;
}
private boolean isLiveStream(KalendarEvent event) {
return event.getLiveStreamUrl() != null;
}
private LiveStreamEventImpl toLiveStreamEvent(KalendarEvent event, boolean timeOnly) {
LiveStreamEventImpl liveStreamEvent = new LiveStreamEventImpl();
liveStreamEvent.setId(event.getID());
liveStreamEvent.setAllDayEvent(event.isAllDayEvent());
liveStreamEvent.setBegin(event.getBegin());
Date end = CalendarUtils.endOf(event);
liveStreamEvent.setEnd(end);
liveStreamEvent.setLiveStreamUrl(event.getLiveStreamUrl());
if (!timeOnly) {
liveStreamEvent.setSubject(event.getSubject());
liveStreamEvent.setDescription(event.getDescription());
liveStreamEvent.setLocation(event.getLocation());
}
return liveStreamEvent;
}
}
......@@ -49,9 +49,11 @@ public class PaellaMapper implements Mapper {
private final ObjectMapper mapper = new ObjectMapper();
private final Streams streams;
private final PlayerProfile playerProfile;
public PaellaMapper(Streams streams) {
public PaellaMapper(Streams streams, PlayerProfile playerProfile) {
this.streams = streams;
this.playerProfile = playerProfile;
}
@Override
......@@ -210,18 +212,9 @@ public class PaellaMapper implements Mapper {
sb.append(" 'es.upv.paella.translecture.captionsPlugin': {'enabled':true},");
sb.append(" 'es.upv.paella.trimmingPlayerPlugin': {'enabled':true},");
sb.append(" 'es.upv.paella.windowTitlePlugin': {'enabled': true},");
sb.append(" 'es.upv.paella.singleStreamProfilePlugin': {");
sb.append(" 'enabled': true,");
sb.append(" 'videoSets': [");
sb.append(" { 'icon':'professor_icon.svg', 'id':'professor', 'content':['stream1']},");
sb.append(" { 'icon':'slide_icon.svg', 'id':'slide', 'content':['stream2']}");
sb.append(" ]");
sb.append(" },");
sb.append(" 'es.upv.paella.dualStreamProfilePlugin': { 'enabled':true,");
sb.append(" 'videoSets': [");
sb.append(" { 'icon':'slide_professor_icon.svg', 'id':'slide_over_professor', 'content':['stream1','stream2'] }");
sb.append(" ]");
sb.append(" }");
playerProfile.appendPlayerConfig(sb);
// The last plugin must not have a comma at the and of the configs.
sb.append(" 'es.upv.paella.windowTitlePlugin': {'enabled': true}");
sb.append(" }");
sb.append(" },");
sb.append(" 'defaultProfile':'presenter_presentation',");
......
/**
* <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.course.nodes.livestream.paella;
import org.olat.core.gui.render.StringOutput;
/**
*
* Initial date: 17 Dec 2019<br>
* @author uhensler, urs.hensler@frentix.com, http://www.frentix.com
*
*/
public enum PlayerProfile {
both("player.profile.both") {
@Override
public void appendPlayerConfig(StringOutput sb) {
sb.append(" 'es.upv.paella.singleStreamProfilePlugin': {");
sb.append(" 'enabled': true,");
sb.append(" 'videoSets': [");
sb.append(" { 'icon':'professor_icon.svg', 'id':'professor', 'content':['stream1']},");
sb.append(" { 'icon':'slide_icon.svg', 'id':'slide', 'content':['stream2']}");
sb.append(" ]");
sb.append(" },");
sb.append(" 'es.upv.paella.dualStreamProfilePlugin': { 'enabled':true,");
sb.append(" 'videoSets': [");
sb.append(" { 'icon':'slide_professor_icon.svg', 'id':'slide_over_professor', 'content':['stream1','stream2'] }");
sb.append(" ]");
sb.append(" },");
}
},
stream1("player.profile.stream1") {
@Override
public void appendPlayerConfig(StringOutput sb) {
sb.append(" 'es.upv.paella.singleStreamProfilePlugin': {");
sb.append(" 'enabled': true,");
sb.append(" 'videoSets': [");
sb.append(" { 'icon':'professor_icon.svg', 'id':'professor', 'content':['stream1']}");
sb.append(" ]");
sb.append(" },");
}
},
stream2("player.profile.stream2") {
@Override
public void appendPlayerConfig(StringOutput sb) {
sb.append(" 'es.upv.paella.singleStreamProfilePlugin': {");
sb.append(" 'enabled': true,");
sb.append(" 'videoSets': [");
sb.append(" { 'icon':'slide_icon.svg', 'id':'slide', 'content':['stream2']}");
sb.append(" ]");
sb.append(" },");
}
};
private final String i18nKey;
private PlayerProfile(String i18nKey) {
this.i18nKey = i18nKey;
}
public String getI18nKey() {
return i18nKey;
}
public abstract void appendPlayerConfig(StringOutput sb);
}
......@@ -19,21 +19,29 @@
*/
package org.olat.course.nodes.livestream.ui;
import static org.olat.core.gui.components.util.KeyValues.entry;
import static org.olat.core.gui.translator.TranslatorHelper.translateAll;
import static org.olat.course.nodes.livestream.ui.LiveStreamUIFactory.validateInteger;
import static org.olat.course.nodes.livestream.ui.LiveStreamUIFactory.validateMandatory;
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.MultipleSelectionElement;
import org.olat.core.gui.components.form.flexible.elements.SingleSelection;
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.components.util.KeyValues;
import org.olat.core.gui.control.Controller;
import org.olat.core.gui.control.WindowControl;
import org.olat.course.nodes.livestream.LiveStreamModule;
import org.olat.course.nodes.livestream.paella.PlayerProfile;
import org.springframework.beans.factory.annotation.Autowired;
import edu.emory.mathcs.backport.java.util.Arrays;
/**
*
* Initial date: 5 Jun 2019<br>
......@@ -45,17 +53,18 @@ public class LiveStreamAdminController extends FormBasicController {
private static final String[] ENABLED_KEYS = new String[]{"on"};
private MultipleSelectionElement enabledEl;
private MultipleSelectionElement multiStreamEnabledEl;
private TextElement urlSeparatorEl;
private TextElement bufferBeforeMinEl;
private TextElement bufferAfterMinEl;
private MultipleSelectionElement coachCanEditEl;
private SingleSelection playerProfileEl;
@Autowired
private LiveStreamModule liveStreamModule;
public LiveStreamAdminController(UserRequest ureq, WindowControl wControl) {
super(ureq, wControl, LAYOUT_BAREBONE);
initForm(ureq);
}
......@@ -70,6 +79,11 @@ public class LiveStreamAdminController extends FormBasicController {
translateAll(getTranslator(), ENABLED_KEYS));
enabledEl.select(ENABLED_KEYS[0], liveStreamModule.isEnabled());
multiStreamEnabledEl = uifactory.addCheckboxesHorizontal("admin.multi.stream.enabled", generalCont,
ENABLED_KEYS, translateAll(getTranslator(), ENABLED_KEYS));
multiStreamEnabledEl.addActionListener(FormEvent.ONCHANGE);
multiStreamEnabledEl.select(ENABLED_KEYS[0], liveStreamModule.isMultiStreamEnabled());
urlSeparatorEl = uifactory.addTextElement("admin.url.separator", 10, liveStreamModule.getUrlSeparator(), generalCont);
urlSeparatorEl.setMandatory(true);
urlSeparatorEl.setHelpTextKey("admin.url.separator.help", null);
......@@ -95,10 +109,37 @@ public class LiveStreamAdminController extends FormBasicController {
boolean coachCanEdit = liveStreamModule.isEditCoach();
coachCanEditEl.select(ENABLED_KEYS[0], coachCanEdit);
KeyValues playerProfileKV = new KeyValues();
for (PlayerProfile playerProfile : PlayerProfile.values()) {
playerProfileKV.add(entry(playerProfile.name(), translate(playerProfile.getI18nKey())));
}
playerProfileEl = uifactory.addDropdownSingleselect("admin.player.profile", defaultValuesCont, playerProfileKV.keys(),
playerProfileKV.values());
String playerProfile = liveStreamModule.getPlayerProfile();
if (Arrays.asList(playerProfileEl.getKeys()).contains(playerProfile)) {
playerProfileEl.select(playerProfile, true);
}
FormLayoutContainer buttonsCont = FormLayoutContainer.createDefaultFormLayout("buttons", getTranslator());
buttonsCont.setRootForm(mainForm);
formLayout.add("buttons", buttonsCont);
uifactory.addFormSubmitButton("save", buttonsCont);
updateUI();
}
private void updateUI() {
boolean multiStream = multiStreamEnabledEl.isAtLeastSelected(1);
urlSeparatorEl.setVisible(multiStream);
playerProfileEl.setVisible(multiStream);
}
@Override
protected void formInnerEvent(UserRequest ureq, FormItem source, FormEvent event) {
if (source == multiStreamEnabledEl) {
updateUI();
}
super.formInnerEvent(ureq, source, event);
}
@Override
......@@ -117,8 +158,13 @@ public class LiveStreamAdminController extends FormBasicController {
boolean enabled = enabledEl.isAtLeastSelected(1);
liveStreamModule.setEnabled(enabled);
String urlSeparator = urlSeparatorEl.getValue();
liveStreamModule.setUrlSeparator(urlSeparator);
boolean multiStreamEnabled = multiStreamEnabledEl.isAtLeastSelected(1);
liveStreamModule.setMultiStreamEnabled(multiStreamEnabled);
if (urlSeparatorEl.isVisible()) {
String urlSeparator = urlSeparatorEl.getValue();
liveStreamModule.setUrlSeparator(urlSeparator);
}
int bufferBeforeMin = Integer.parseInt(bufferBeforeMinEl.getValue());
liveStreamModule.setBufferBeforeMin(bufferBeforeMin);
......@@ -128,6 +174,11 @@ public class LiveStreamAdminController extends FormBasicController {
boolean coachCanEdit = coachCanEditEl.isAtLeastSelected(1);
liveStreamModule.setEditCoach(coachCanEdit);
if (playerProfileEl.isVisible()) {
String playerProfile = playerProfileEl.getSelectedKey();
liveStreamModule.setPlayerProfile(playerProfile);
}
}
@Override
......
......@@ -19,19 +19,27 @@
*/
package org.olat.course.nodes.livestream.ui;
import static org.olat.core.gui.components.util.KeyValues.entry;
import static org.olat.core.gui.translator.TranslatorHelper.translateAll;
import static org.olat.course.nodes.livestream.ui.LiveStreamUIFactory.validateInteger;
import org.olat.core.gui.UserRequest;
import org.olat.core.gui.components.form.flexible.FormItemContainer;
import org.olat.core.gui.components.form.flexible.elements.MultipleSelectionElement;
import org.olat.core.gui.components.form.flexible.elements.SingleSelection;
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.util.KeyValues;
import org.olat.core.gui.control.Controller;
import org.olat.core.gui.control.Event;
import org.olat.core.gui.control.WindowControl;
import org.olat.course.nodes.LiveStreamCourseNode;
import org.olat.course.nodes.livestream.LiveStreamModule;
import org.olat.course.nodes.livestream.paella.PlayerProfile;
import org.olat.modules.ModuleConfiguration;
import org.springframework.beans.factory.annotation.Autowired;
import edu.emory.mathcs.backport.java.util.Arrays;
/**
*
......@@ -48,6 +56,10 @@ public class LiveStreamConfigController extends FormBasicController {
private TextElement bufferBeforeMinEl;
private TextElement bufferAfterMinEl;
private MultipleSelectionElement coachCanEditEl;
private SingleSelection playerProfileEl;
@Autowired
private LiveStreamModule liveStreamModule;
public LiveStreamConfigController(UserRequest ureq, WindowControl wControl, ModuleConfiguration moduleConfiguration) {
super(ureq, wControl);
......@@ -73,6 +85,20 @@ public class LiveStreamConfigController extends FormBasicController {
boolean coachCanEdit = config.getBooleanSafe(LiveStreamCourseNode.CONFIG_COACH_CAN_EDIT);
coachCanEditEl.select(ENABLED_KEYS[0], coachCanEdit);
if (liveStreamModule.isMultiStreamEnabled()) {
KeyValues playerProfileKV = new KeyValues();
for (PlayerProfile playerProfile : PlayerProfile.values()) {
playerProfileKV.add(entry(playerProfile.name(), translate(playerProfile.getI18nKey())));
}
playerProfileEl = uifactory.addDropdownSingleselect("config.player.profile", formLayout, playerProfileKV.keys(),
playerProfileKV.values());
String playerProfile = config.getStringValue(LiveStreamCourseNode.CONFIG_PLAYER_PROFILE,
liveStreamModule.getPlayerProfile());
if (Arrays.asList(playerProfileEl.getKeys()).contains(playerProfile)) {
playerProfileEl.select(playerProfile, true);
}
}
uifactory.addFormSubmitButton("save", formLayout);
}
......@@ -101,6 +127,11 @@ public class LiveStreamConfigController extends FormBasicController {
boolean coachCanEdit = coachCanEditEl.isAtLeastSelected(1);
config.setBooleanEntry(LiveStreamCourseNode.CONFIG_COACH_CAN_EDIT, coachCanEdit);
if (playerProfileEl != null) {
String playerProfile = playerProfileEl.getSelectedKey();
config.setStringValue(LiveStreamCourseNode.CONFIG_PLAYER_PROFILE, playerProfile);
}
return config;
}
......
......@@ -36,6 +36,7 @@ import org.olat.core.util.UserSession;
import org.olat.course.nodes.livestream.LiveStreamEvent;
import org.olat.course.nodes.livestream.paella.PaellaFactory;
import org.olat.course.nodes.livestream.paella.PaellaMapper;
import org.olat.course.nodes.livestream.paella.PlayerProfile;
import org.olat.course.nodes.livestream.paella.Streams;
import org.springframework.beans.factory.annotation.Autowired;
......@@ -49,14 +50,16 @@ public class LiveStreamVideoController extends BasicController {
private final VelocityContainer mainVC;
private final PlayerProfile playerProfile;
private final List<MapperKey> mappers = new ArrayList<>();
private String url;
@Autowired
private MapperService mapperService;
protected LiveStreamVideoController(UserRequest ureq, WindowControl wControl) {
protected LiveStreamVideoController(UserRequest ureq, WindowControl wControl, PlayerProfile playerProfile) {
super(ureq, wControl);
this.playerProfile = playerProfile;
mainVC = createVelocityContainer("video");
updateUI(ureq.getUserSession());
putInitialPanel(mainVC);
......@@ -74,7 +77,7 @@ public class LiveStreamVideoController extends BasicController {
if (StringHelper.containsNonWhitespace(url)) {
mainVC.contextPut("id", CodeHelper.getRAMUniqueID());
Streams streams = PaellaFactory.createStreams(url);
PaellaMapper paellaMapper = new PaellaMapper(streams);
PaellaMapper paellaMapper = new PaellaMapper(streams, playerProfile);
MapperKey mapperKey = mapperService.register(usess, paellaMapper);
mappers.add(mapperKey);
String baseURI = mapperKey.getUrl();
......
......@@ -27,6 +27,7 @@ import org.olat.core.gui.control.WindowControl;
import org.olat.core.gui.control.controller.BasicController;
import org.olat.core.util.UserSession;
import org.olat.course.nodes.livestream.LiveStreamEvent;
import org.olat.course.nodes.livestream.paella.PlayerProfile;
/**
*
......@@ -40,12 +41,12 @@ public class LiveStreamViewerController extends BasicController {
private final LiveStreamVideoController videoCtrl;
private final LiveStreamMetadataController metadataCtrl;
public LiveStreamViewerController(UserRequest ureq, WindowControl wControl) {
public LiveStreamViewerController(UserRequest ureq, WindowControl wControl, PlayerProfile playerProfile) {
super(ureq, wControl);
mainVC = createVelocityContainer("viewer");
videoCtrl = new LiveStreamVideoController(ureq, wControl);
videoCtrl = new LiveStreamVideoController(ureq, wControl, playerProfile);
listenTo(videoCtrl);
mainVC.put("video", videoCtrl.getInitialComponent());
metadataCtrl = new LiveStreamMetadataController(ureq, wControl);
......
......@@ -30,11 +30,14 @@ import org.olat.core.gui.components.velocity.VelocityContainer;
import org.olat.core.gui.control.Event;
import org.olat.core.gui.control.WindowControl;
import org.olat.core.gui.control.controller.BasicController;
import org.olat.core.util.StringHelper;
import org.olat.core.util.UserSession;
import org.olat.course.nodes.LiveStreamCourseNode;
import org.olat.course.nodes.cal.CourseCalendars;
import org.olat.course.nodes.livestream.LiveStreamEvent;
import org.olat.course.nodes.livestream.LiveStreamModule;
import org.olat.course.nodes.livestream.LiveStreamService;
import org.olat.course.nodes.livestream.paella.PlayerProfile;
import org.olat.modules.ModuleConfiguration;
import org.springframework.beans.factory.annotation.Autowired;
......@@ -66,6 +69,8 @@ public class LiveStreamViewersController extends BasicController {
private final List<DisplayWrapper> displayWrappers;
private Boolean noLiveStream;
@Autowired
private LiveStreamModule liveStreamModule;
@Autowired
private LiveStreamService liveStreamService;
......@@ -76,56 +81,57 @@ public class LiveStreamViewersController extends BasicController {
bufferBeforeMin = moduleConfiguration.getIntegerSafe(LiveStreamCourseNode.CONFIG_BUFFER_BEFORE_MIN, 0);
bufferAfterMin = moduleConfiguration.getIntegerSafe(LiveStreamCourseNode.CONFIG_BUFFER_AFTER_MIN, 0);
PlayerProfile playerProfile = getPlayerProfile(moduleConfiguration);
mainVC = createVelocityContainer("viewers");
displayWrappers = new ArrayList<>();
displayCtrl0 = new LiveStreamViewerController(ureq, wControl);
displayCtrl0 = new LiveStreamViewerController(ureq, wControl, playerProfile);
listenTo(displayCtrl0);
mainVC.put("display0", displayCtrl0.getInitialComponent());
displayWrappers.add(new DisplayWrapper(displayCtrl0));
displayCtrl1 = new LiveStreamViewerController(ureq, wControl);
displayCtrl1 = new LiveStreamViewerController(ureq, wControl, playerProfile);
listenTo(displayCtrl1);
mainVC.put("display1", displayCtrl1.getInitialComponent());
displayWrappers.add(new DisplayWrapper(displayCtrl1));
displayCtrl2 = new LiveStreamViewerController(ureq, wControl);
displayCtrl2 = new LiveStreamViewerController(ureq, wControl, playerProfile);
listenTo(displayCtrl2);
mainVC.put("display2", displayCtrl2.getInitialComponent());
displayWrappers.add(new DisplayWrapper(displayCtrl2));
displayCtrl3 = new LiveStreamViewerController(ureq, wControl);
displayCtrl3 = new LiveStreamViewerController(ureq, wControl, playerProfile);
listenTo(displayCtrl3);
mainVC.put("display3", displayCtrl3.getInitialComponent());
displayWrappers.add(new DisplayWrapper(displayCtrl3));
displayCtrl4 = new LiveStreamViewerController(ureq, wControl);
displayCtrl4 = new LiveStreamViewerController(ureq, wControl, playerProfile);
listenTo(displayCtrl4);
mainVC.put("display4", displayCtrl4.getInitialComponent());
displayWrappers.add(new DisplayWrapper(displayCtrl4));
displayCtrl5 = new LiveStreamViewerController(ureq, wControl);
displayCtrl5 = new LiveStreamViewerController(ureq, wControl, playerProfile);
listenTo(displayCtrl5);
mainVC.put("display5", displayCtrl5.getInitialComponent());
displayWrappers.add(new DisplayWrapper(displayCtrl5));
displayCtrl6 = new LiveStreamViewerController(ureq, wControl);
displayCtrl6 = new LiveStreamViewerController(ureq, wControl, playerProfile);
listenTo(displayCtrl6);
mainVC.put("display6", displayCtrl6.getInitialComponent());
displayWrappers.add(new DisplayWrapper(displayCtrl6));
displayCtrl7 = new LiveStreamViewerController(ureq, wControl);
displayCtrl7 = new LiveStreamViewerController(ureq, wControl, playerProfile);
listenTo(displayCtrl7);
mainVC.put("display7", displayCtrl7.getInitialComponent());
displayWrappers.add(new DisplayWrapper(displayCtrl7));
displayCtrl8 = new LiveStreamViewerController(ureq, wControl);
displayCtrl8 = new LiveStreamViewerController(ureq, wControl, playerProfile);
listenTo(displayCtrl8);
mainVC.put("display8", displayCtrl8.getInitialComponent());
displayWrappers.add(new DisplayWrapper(displayCtrl8));
displayCtrl9 = new LiveStreamViewerController(ureq, wControl);
displayCtrl9 = new LiveStreamViewerController(ureq, wControl, playerProfile);
listenTo(displayCtrl9);
mainVC.put("display9", displayCtrl9.getInitialComponent());
displayWrappers.add(new DisplayWrapper(displayCtrl9));
......@@ -135,6 +141,20 @@ public class LiveStreamViewersController extends BasicController {
putInitialPanel(mainVC);
}
private PlayerProfile getPlayerProfile(ModuleConfiguration moduleConfiguration) {
PlayerProfile playerProfile = PlayerProfile.stream1;
if (liveStreamModule.isMultiStreamEnabled()) {
String nodePlayerProfile = moduleConfiguration.getStringValue(LiveStreamCourseNode.CONFIG_PLAYER_PROFILE);
if (StringHelper.containsNonWhitespace(nodePlayerProfile)) {
playerProfile = PlayerProfile.valueOf(nodePlayerProfile);
} else {
playerProfile = PlayerProfile.valueOf(liveStreamModule.getPlayerProfile());
}
}
return playerProfile;
}
void refresh(UserSession usess) {
List<? extends LiveStreamEvent> events = liveStreamService.getRunningEvents(calendars, bufferBeforeMin, bufferAfterMin);
putNoLiveStreamToMainVC(events);
......
......@@ -61,7 +61,7 @@ public class LiveStreamsController extends BasicController {
CourseCalendars calendars) {
super(ureq, wControl);
mainVC = createVelocityContainer("streams");
viewersCtrl = new LiveStreamViewersController(ureq, wControl, moduleConfiguration, calendars);
listenTo(viewersCtrl);
mainVC.put("viewers", viewersCtrl.getInitialComponent());
......
......@@ -7,12 +7,15 @@ admin.general.title=$:\admin.menu.title
admin.menu.title=Livestream
admin.menu.title.alt=$:\admin.menu.title
admin.module.enabled=Kursbaustein
admin.multi.stream.enabled=Multistream
admin.player.profile=Stream
admin.url.separator=URL Trennzeichen
admin.url.separator.help=Trennzeichen, um mehrere URLs eines einzelnen Termins zu trennen.
condition.accessibility.title=Zugang
config.buffer.before.min=Vorlaufzeit (in Minuten)
config.buffer.after.min=Nachlaufzeit (in Minuten)
config.coach.edit=Betreuer darf Termine bearbeiten
config.player.profile=$\:admin.player.profile
form.error.wrong.int=Falsches Zahlenformat. Beispiele\: 2, 10, 144
link.text=Video Livestream
list.title=Anstehende Livestreams
......@@ -23,6 +26,9 @@ peekview.open.live=Livestream anzeigen
peekview.open.upcoming=Alle anzeigen
peekview.title.live=Jetzt live: {0}
peekview.title.upcoming=Demn\u00E4chst: {0}
player.profile.both=Beide Streams anzeigen
player.profile.stream1=Stream 1 anzeigen
player.profile.stream2=Stream 2 anzeigen
run.edit.events=Termine bearbeiten
run.streams=Live Streams
table.empty=Es sind keine Livestreams anstehend.
......
......@@ -7,12 +7,15 @@ admin.general.title=$:\admin.menu.title
admin.menu.title=Live stream
admin.menu.title.alt=$:\admin.menu.title
admin.module.enabled=Course element
admin.multi.stream.enabled=Multi stream
admin.player.profile=Stream
admin.url.separator=URL separator
admin.url.separator.help=Char / String to separate multiple URLs of a single event.
condition.accessibility.title=Access
config.buffer.before.min=Buffer time before start (in minutes)
config.buffer.after.min=Buffer time after end (in minutes)
config.coach.edit=Coach is allowed to edit
config.player.profile=$\:admin.player.profile
form.error.wrong.int=Wrong numeral format. Examples\: 2, 10, 144
link.text=Video live stream
list.title=Upcoming live streams
......@@ -23,6 +26,9 @@ peekview.open.live=Show live stream
peekview.open.upcoming=Show all
peekview.title.live=Live: {0}
peekview.title.upcoming=Upcoming: {0}
player.profile.both=Show both streams
player.profile.stream1=Show stream 1
player.profile.stream2=Show stream 2
run.edit.events=Edit events
run.streams=Livestreams
table.empty=No upcoming live streams are available.
......
......@@ -1656,6 +1656,8 @@ youtube.api.key=
# Options for the live stream course node
###############################################################################
live.stream.enabled=false
# Enable multiple streams pre event. Actually two streams are supported.
live.stream.multi.stream.enabled=false
# Char / String to separate multiple urls of a single event
live.stream.url.separator=,
# Buffer time to switch from the announcement page to the live stream (in minutes)
......@@ -1663,4 +1665,6 @@ live.stream.url.separator=,
live.stream.buffer.before.min=5
live.stream.buffer.after.min=5
live.stream.edit.coach=false
# Profile to control witch stream is visible for the watchers.
live.stream.player.profile=both
live.stream.player.profile.values=both,stream1,stream2
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment