From 238debe28cef2bb8acab1a4e61785420d2f37f7e Mon Sep 17 00:00:00 2001 From: uhensler <urs.hensler@frentix.com> Date: Wed, 26 Feb 2020 14:24:17 +0100 Subject: [PATCH] OO-4541: Show info if stream is not broadcasted yet. --- .../nodes/livestream/LiveStreamService.java | 16 ++++++ .../manager/LiveStreamServiceImpl.java | 57 +++++++++++++++++++ .../livestream/paella/PaellaFactory.java | 14 +---- .../ui/LiveStreamVideoController.java | 43 ++++++++++---- .../nodes/livestream/ui/_content/video.html | 18 ++++-- .../ui/_i18n/LocalStrings_de.properties | 2 + .../ui/_i18n/LocalStrings_en.properties | 2 + .../ui/_i18n/LocalStrings_fr.properties | 2 + .../ui/_i18n/LocalStrings_pt_BR.properties | 2 + 9 files changed, 127 insertions(+), 29 deletions(-) diff --git a/src/main/java/org/olat/course/nodes/livestream/LiveStreamService.java b/src/main/java/org/olat/course/nodes/livestream/LiveStreamService.java index e9d16eea850..31209f23055 100644 --- a/src/main/java/org/olat/course/nodes/livestream/LiveStreamService.java +++ b/src/main/java/org/olat/course/nodes/livestream/LiveStreamService.java @@ -65,4 +65,20 @@ public interface LiveStreamService { */ Long getLaunchers(RepositoryEntryRef courseEntry, String subIdent, Date from, Date to); + /** + * Split the url to separate urls + * + * @param url + * @return + */ + String[] splitUrl(String url); + + /** + * Checks whether at the urls are currently streaming and returns the streaming urls + * + * @param urls + * @return + */ + String[] getStreamingUrls(String[] urls); + } diff --git a/src/main/java/org/olat/course/nodes/livestream/manager/LiveStreamServiceImpl.java b/src/main/java/org/olat/course/nodes/livestream/manager/LiveStreamServiceImpl.java index c4826a717d7..19bc4eaf66c 100644 --- a/src/main/java/org/olat/course/nodes/livestream/manager/LiveStreamServiceImpl.java +++ b/src/main/java/org/olat/course/nodes/livestream/manager/LiveStreamServiceImpl.java @@ -30,13 +30,23 @@ import java.util.concurrent.ThreadFactory; import java.util.function.Predicate; import java.util.stream.Collectors; +import org.apache.http.Header; +import org.apache.http.HttpStatus; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.apache.logging.log4j.Logger; 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.core.id.Identity; +import org.olat.core.logging.Tracing; +import org.olat.core.util.StringHelper; 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.model.LiveStreamEventImpl; import org.olat.repository.RepositoryEntry; @@ -54,8 +64,12 @@ import org.springframework.stereotype.Service; @Service public class LiveStreamServiceImpl implements LiveStreamService { + private static final Logger log = Tracing.createLoggerFor(LiveStreamServiceImpl.class); + private ScheduledExecutorService scheduler; + @Autowired + private LiveStreamModule liveStreamModule; @Autowired private CalendarManager calendarManager; @Autowired @@ -177,4 +191,47 @@ public class LiveStreamServiceImpl implements LiveStreamService { public Long getLaunchers(RepositoryEntryRef courseEntry, String subIdent, Date from, Date to) { return launchDao.getLaunchers(courseEntry, subIdent, from, to); } + + @Override + public String[] splitUrl(String url) { + if (!StringHelper.containsNonWhitespace(url)) return new String[0]; + + String urlSeparator = liveStreamModule.getUrlSeparator(); + return url.split(urlSeparator); + } + + @Override + public String[] getStreamingUrls(String[] urls) { + if (urls == null || urls.length < 1) return urls; + + List<String> streamingUrls = new ArrayList<>(urls.length); + for (String url : urls) { + if (isStreaming(url)) { + streamingUrls.add(url); + } + } + + String[] streaming = new String[streamingUrls.size()]; + streamingUrls.toArray(streaming); + return streaming; + } + + private boolean isStreaming(String url) { + HttpGet request = new HttpGet(url); + try(CloseableHttpClient httpclient = HttpClients.createDefault(); + CloseableHttpResponse response = httpclient.execute(request);) { + int statusCode = response.getStatusLine().getStatusCode(); + if (statusCode == HttpStatus.SC_OK) { + // Wrong WOWZA urls returns a html message instead of a video. + Header contentType = response.getFirstHeader("Content-Type"); + if (contentType != null && !contentType.getValue().contains("html")) { + return true; + } + } + } catch(Exception e) { + log.error("", e); + } + + return false; + } } diff --git a/src/main/java/org/olat/course/nodes/livestream/paella/PaellaFactory.java b/src/main/java/org/olat/course/nodes/livestream/paella/PaellaFactory.java index af8c7f3b90a..0465ea425ca 100644 --- a/src/main/java/org/olat/course/nodes/livestream/paella/PaellaFactory.java +++ b/src/main/java/org/olat/course/nodes/livestream/paella/PaellaFactory.java @@ -22,10 +22,6 @@ package org.olat.course.nodes.livestream.paella; import java.util.ArrayList; import java.util.List; -import org.olat.core.CoreSpringFactory; -import org.olat.core.util.StringHelper; -import org.olat.course.nodes.livestream.LiveStreamModule; - /** * * Initial date: 13 Dec 2019<br> @@ -34,19 +30,13 @@ import org.olat.course.nodes.livestream.LiveStreamModule; */ public class PaellaFactory { - public static Streams createStreams(String url) { + public static Streams createStreams(String[] urls) { Streams streams = new Streams(); - if (StringHelper.containsNonWhitespace(url)) { - String[] urls = splitUrls(url); + if (urls.length > 0) { addStreams(streams, urls); } return streams; } - - private static String[] splitUrls(String url) { - String urlSeparator = CoreSpringFactory.getImpl(LiveStreamModule.class).getUrlSeparator(); - return url.split(urlSeparator); - } private static void addStreams(Streams streams, String[] urls) { List<Stream> streamList = new ArrayList<>(2); diff --git a/src/main/java/org/olat/course/nodes/livestream/ui/LiveStreamVideoController.java b/src/main/java/org/olat/course/nodes/livestream/ui/LiveStreamVideoController.java index 04743bf6211..6efce834d2e 100644 --- a/src/main/java/org/olat/course/nodes/livestream/ui/LiveStreamVideoController.java +++ b/src/main/java/org/olat/course/nodes/livestream/ui/LiveStreamVideoController.java @@ -26,6 +26,8 @@ import org.olat.core.dispatcher.mapper.MapperService; import org.olat.core.dispatcher.mapper.manager.MapperKey; import org.olat.core.gui.UserRequest; import org.olat.core.gui.components.Component; +import org.olat.core.gui.components.link.Link; +import org.olat.core.gui.components.link.LinkFactory; import org.olat.core.gui.components.velocity.VelocityContainer; import org.olat.core.gui.control.Event; import org.olat.core.gui.control.WindowControl; @@ -34,6 +36,7 @@ import org.olat.core.util.CodeHelper; import org.olat.core.util.StringHelper; import org.olat.core.util.UserSession; import org.olat.course.nodes.livestream.LiveStreamEvent; +import org.olat.course.nodes.livestream.LiveStreamService; import org.olat.course.nodes.livestream.paella.PaellaFactory; import org.olat.course.nodes.livestream.paella.PaellaMapper; import org.olat.course.nodes.livestream.paella.PlayerProfile; @@ -49,11 +52,16 @@ import org.springframework.beans.factory.annotation.Autowired; public class LiveStreamVideoController extends BasicController { private final VelocityContainer mainVC; + private Link retryLink; private final PlayerProfile playerProfile; private final List<MapperKey> mappers = new ArrayList<>(); + private boolean error = false; private String url; + private String[] urls; + @Autowired + private LiveStreamService liveStreamService; @Autowired private MapperService mapperService; @@ -61,35 +69,48 @@ public class LiveStreamVideoController extends BasicController { super(ureq, wControl); this.playerProfile = playerProfile; mainVC = createVelocityContainer("video"); - updateUI(ureq.getUserSession()); putInitialPanel(mainVC); } public void setEvent(UserSession usess, LiveStreamEvent event) { String newUrl = event != null? event.getLiveStreamUrl(): null; if (newUrl == null || !newUrl.equalsIgnoreCase(url)) { + error = false; url = newUrl; + urls = liveStreamService.splitUrl(newUrl); updateUI(usess); } } private void updateUI(UserSession usess) { - if (StringHelper.containsNonWhitespace(url)) { - mainVC.contextPut("id", CodeHelper.getRAMUniqueID()); - Streams streams = PaellaFactory.createStreams(url); - PaellaMapper paellaMapper = new PaellaMapper(streams, playerProfile); - MapperKey mapperKey = mapperService.register(usess, paellaMapper); - mappers.add(mapperKey); - String baseURI = mapperKey.getUrl(); - mainVC.contextPut("baseURI", baseURI); - } else { + if (!StringHelper.containsNonWhitespace(url)) { mainVC.contextRemove("id"); + mainVC.contextRemove("error"); + } else { + String[] streamingUrls = liveStreamService.getStreamingUrls(urls); + if (streamingUrls.length > 0) { + mainVC.contextRemove("error"); + mainVC.contextPut("id", CodeHelper.getRAMUniqueID()); + Streams streams = PaellaFactory.createStreams(streamingUrls); + PaellaMapper paellaMapper = new PaellaMapper(streams, playerProfile); + MapperKey mapperKey = mapperService.register(usess, paellaMapper); + mappers.add(mapperKey); + String baseURI = mapperKey.getUrl(); + mainVC.contextPut("baseURI", baseURI); + } else { + mainVC.contextRemove("id"); + mainVC.contextPut("error", Boolean.valueOf(error)); + retryLink = LinkFactory.createButton("viewer.retry", mainVC, this); + } } } @Override protected void event(UserRequest ureq, Component source, Event event) { - // + if (source == retryLink) { + error = false; + updateUI(ureq.getUserSession()); + } } @Override diff --git a/src/main/java/org/olat/course/nodes/livestream/ui/_content/video.html b/src/main/java/org/olat/course/nodes/livestream/ui/_content/video.html index 38148545150..930d261b813 100644 --- a/src/main/java/org/olat/course/nodes/livestream/ui/_content/video.html +++ b/src/main/java/org/olat/course/nodes/livestream/ui/_content/video.html @@ -1,8 +1,14 @@ -#if($r.isNotNull($id)) -<div class="o_paella_wrapper"> - <div class="o_instruction o_paella_error"> - $r.translate("viewer.error.browser") +#if($r.isNotNull($error)) + <div class="o_instruction"> + $r.translate("viewer.error.stream") + <div class="o_button_group"> + $r.render("viewer.retry") + </div> +#elseif($r.isNotNull($id)) + <div class="o_paella_wrapper"> + <div class="o_instruction o_paella_error"> + $r.translate("viewer.error.browser") + </div> + <iframe id="${id}" allowfullscreen="true" src="${baseURI}" frameborder="0"></iframe> </div> - <iframe id="${id}" allowfullscreen="true" src="${baseURI}" frameborder="0"></iframe> -</div> #end \ No newline at end of file diff --git a/src/main/java/org/olat/course/nodes/livestream/ui/_i18n/LocalStrings_de.properties b/src/main/java/org/olat/course/nodes/livestream/ui/_i18n/LocalStrings_de.properties index bc2a803cfa8..0c3cdbd16fa 100644 --- a/src/main/java/org/olat/course/nodes/livestream/ui/_i18n/LocalStrings_de.properties +++ b/src/main/java/org/olat/course/nodes/livestream/ui/_i18n/LocalStrings_de.properties @@ -42,4 +42,6 @@ table.header.location=$org.olat.commons.calendar\:cal.form.location table.header.subject=$org.olat.commons.calendar\:cal.form.subject table.header.viewers=Zuschauer viewer.error.browser=Der Livestream kann in diesem Browser nicht angezeigt werden. Bitte verwenden Sie einen anderen Browser. +viewer.error.stream=Der Livestream kann nicht angezeigt werden. Vermutlich wird der Livestream noch nicht ausgestrahlt. viewer.no.stream=Aktuell wird kein Livestream ausgestrahlt. +viewer.retry=Erneut starten diff --git a/src/main/java/org/olat/course/nodes/livestream/ui/_i18n/LocalStrings_en.properties b/src/main/java/org/olat/course/nodes/livestream/ui/_i18n/LocalStrings_en.properties index a4e187294fb..b1ad594cc4f 100644 --- a/src/main/java/org/olat/course/nodes/livestream/ui/_i18n/LocalStrings_en.properties +++ b/src/main/java/org/olat/course/nodes/livestream/ui/_i18n/LocalStrings_en.properties @@ -42,4 +42,6 @@ table.header.location=$org.olat.commons.calendar\:cal.form.location table.header.subject=$org.olat.commons.calendar\:cal.form.subject table.header.viewers=Viewers viewer.error.browser=The livestream cannot be displayed in this browser. Please use a different browser. +viewer.error.stream=It is not possible to show the live stream. Probably is the live stream not broadcasted yet. viewer.no.stream=Currently no live stream is broadcasted. +viewer.retry=Try again diff --git a/src/main/java/org/olat/course/nodes/livestream/ui/_i18n/LocalStrings_fr.properties b/src/main/java/org/olat/course/nodes/livestream/ui/_i18n/LocalStrings_fr.properties index 6176341e0d1..4965c241373 100644 --- a/src/main/java/org/olat/course/nodes/livestream/ui/_i18n/LocalStrings_fr.properties +++ b/src/main/java/org/olat/course/nodes/livestream/ui/_i18n/LocalStrings_fr.properties @@ -43,4 +43,6 @@ table.header.location=$org.olat.commons.calendar\:cal.form.location table.header.subject=$org.olat.commons.calendar\:cal.form.subject table.header.viewers=Spectateurs viewer.error.browser=Le flux ne peut \u00EAtre pas \u00EAtre affich\u00E9 dans ce navigateur. Choisissez s'il vous pla\u00EEt un autre navigateur. +viewer.error.stream=Il n'est pas possible d'afficher la vid\u00E9o. La diffusion en direct n'a probablement pas encore commenc\u00E9. viewer.no.stream=Pas de diffusion pour l'instant. +viewer.retry=Essayer \u00E0 nouveau diff --git a/src/main/java/org/olat/course/nodes/livestream/ui/_i18n/LocalStrings_pt_BR.properties b/src/main/java/org/olat/course/nodes/livestream/ui/_i18n/LocalStrings_pt_BR.properties index c8d4bced76d..ca4dca335ec 100644 --- a/src/main/java/org/olat/course/nodes/livestream/ui/_i18n/LocalStrings_pt_BR.properties +++ b/src/main/java/org/olat/course/nodes/livestream/ui/_i18n/LocalStrings_pt_BR.properties @@ -30,4 +30,6 @@ table.header.description=$org.olat.commons.calendar\:cal.form.description table.header.end=$org.olat.commons.calendar\:cal.form.end table.header.location=$org.olat.commons.calendar\:cal.form.location table.header.subject=$org.olat.commons.calendar\:cal.form.subject +viewer.error.stream=N\u00E3o \u00E9 poss\u00EDvel mostrar a transmiss\u00E3o ao vivo. Provavelmente a transmiss\u00E3o n\u00E3o come\u00E7ou ainda. viewer.no.stream=Atualmente, nenhuma transmiss\u00E3o ao vivo est\u00E1 sendo transmitida. +viewer.retry=Tente novamente -- GitLab