/** * Copyright (c) 2014-2017 by the respective copyright holders. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html */ package org.eclipse.smarthome.io.webaudio.internal; import java.io.IOException; import java.util.HashSet; import java.util.Locale; import java.util.Set; import org.apache.commons.io.IOUtils; import org.eclipse.smarthome.core.audio.AudioFormat; import org.eclipse.smarthome.core.audio.AudioHTTPServer; import org.eclipse.smarthome.core.audio.AudioSink; import org.eclipse.smarthome.core.audio.AudioStream; import org.eclipse.smarthome.core.audio.FixedLengthAudioStream; import org.eclipse.smarthome.core.audio.URLAudioStream; import org.eclipse.smarthome.core.audio.UnsupportedAudioFormatException; import org.eclipse.smarthome.core.events.EventPublisher; import org.eclipse.smarthome.core.library.types.PercentType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * This is an audio sink that publishes an event through SSE and temporarily serves the stream via HTTP for web players * to pick it up. * * @author Kai Kreuzer - Initial contribution and API */ public class SSEAudioSink implements AudioSink { private final Logger logger = LoggerFactory.getLogger(SSEAudioSink.class); private static final HashSet<AudioFormat> supportedFormats = new HashSet<>(); static { supportedFormats.add(AudioFormat.WAV); supportedFormats.add(AudioFormat.MP3); } private AudioHTTPServer audioHTTPServer; private EventPublisher eventPublisher; @Override public void process(AudioStream audioStream) throws UnsupportedAudioFormatException { logger.debug("Received audio stream of format {}", audioStream.getFormat()); if (audioStream instanceof URLAudioStream) { // it is an external URL, so we can directly pass this on. URLAudioStream urlAudioStream = (URLAudioStream) audioStream; sendEvent(urlAudioStream.getURL()); IOUtils.closeQuietly(audioStream); } else { // we serve it on our own HTTP server if (audioStream instanceof FixedLengthAudioStream) { // we need to serve it for a while and make it available to multiple clients, hence // only FixedLengthAudioStreams are supported String url = audioHTTPServer.serve((FixedLengthAudioStream) audioStream, 10).toString(); sendEvent(url); } else { logger.warn("Only FixedLengthAudioStream are supported for the web audio sink."); IOUtils.closeQuietly(audioStream); } } } private void sendEvent(String url) { PlayURLEvent event = WebAudioEventFactory.createPlayURLEvent(url); eventPublisher.post(event); } @Override public Set<AudioFormat> getSupportedFormats() { return supportedFormats; } @Override public String getId() { return "webaudio"; } @Override public String getLabel(Locale locale) { return "Web Audio"; } @Override public PercentType getVolume() throws IOException { return PercentType.HUNDRED; } @Override public void setVolume(final PercentType volume) throws IOException { throw new IOException("Web Audio sink does not support volume level changes."); } protected void setEventPublisher(EventPublisher eventPublisher) { this.eventPublisher = eventPublisher; } protected void unsetEventPublisher(EventPublisher eventPublisher) { this.eventPublisher = null; } protected void setAudioHTTPServer(AudioHTTPServer audioHTTPServer) { this.audioHTTPServer = audioHTTPServer; } protected void unsetAudioHTTPServer(AudioHTTPServer audioHTTPServer) { this.audioHTTPServer = null; } }