2 * Copyright (c) 2010-2023 Contributors to the openHAB project
4 * See the NOTICE file(s) distributed with this work for additional
7 * This program and the accompanying materials are made available under the
8 * terms of the Eclipse Public License 2.0 which is available at
9 * http://www.eclipse.org/legal/epl-2.0
11 * SPDX-License-Identifier: EPL-2.0
13 package org.openhab.binding.squeezebox.internal;
15 import java.util.HashSet;
16 import java.util.Locale;
19 import org.openhab.binding.squeezebox.internal.handler.SqueezeBoxPlayerHandler;
20 import org.openhab.core.audio.AudioFormat;
21 import org.openhab.core.audio.AudioHTTPServer;
22 import org.openhab.core.audio.AudioSink;
23 import org.openhab.core.audio.AudioStream;
24 import org.openhab.core.audio.FileAudioStream;
25 import org.openhab.core.audio.FixedLengthAudioStream;
26 import org.openhab.core.audio.URLAudioStream;
27 import org.openhab.core.audio.UnsupportedAudioFormatException;
28 import org.openhab.core.audio.UnsupportedAudioStreamException;
29 import org.openhab.core.audio.utils.AudioStreamUtils;
30 import org.openhab.core.library.types.PercentType;
31 import org.openhab.core.library.types.StringType;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
36 * This makes a SqueezeBox Player serve as an {@link AudioSink}-
38 * @author Mark Hilbush - Initial contribution
39 * @author Mark Hilbush - Add callbackUrl
41 public class SqueezeBoxAudioSink implements AudioSink {
42 private final Logger logger = LoggerFactory.getLogger(SqueezeBoxAudioSink.class);
44 private static final HashSet<AudioFormat> SUPPORTED_FORMATS = new HashSet<>();
45 private static final HashSet<Class<? extends AudioStream>> SUPPORTED_STREAMS = new HashSet<>();
47 // Needed because Squeezebox does multiple requests for the stream
48 private static final int STREAM_TIMEOUT = 15;
50 private String callbackUrl;
53 SUPPORTED_FORMATS.add(AudioFormat.WAV);
54 SUPPORTED_FORMATS.add(AudioFormat.MP3);
56 SUPPORTED_STREAMS.add(FixedLengthAudioStream.class);
57 SUPPORTED_STREAMS.add(URLAudioStream.class);
60 private AudioHTTPServer audioHTTPServer;
61 private SqueezeBoxPlayerHandler playerHandler;
63 public SqueezeBoxAudioSink(SqueezeBoxPlayerHandler playerHandler, AudioHTTPServer audioHTTPServer,
65 this.playerHandler = playerHandler;
66 this.audioHTTPServer = audioHTTPServer;
67 this.callbackUrl = callbackUrl;
68 if (callbackUrl != null && !callbackUrl.isEmpty()) {
69 logger.debug("SqueezeBox AudioSink created with callback URL: {}", callbackUrl);
74 public String getId() {
75 return playerHandler.getThing().getUID().toString();
79 public String getLabel(Locale locale) {
80 return playerHandler.getThing().getLabel();
84 public void process(AudioStream audioStream)
85 throws UnsupportedAudioFormatException, UnsupportedAudioStreamException {
86 AudioFormat format = audioStream.getFormat();
87 if (!AudioFormat.WAV.isCompatible(format) && !AudioFormat.MP3.isCompatible(format)) {
88 throw new UnsupportedAudioFormatException("Currently only MP3 and WAV formats are supported: ", format);
92 if (audioStream instanceof URLAudioStream) {
93 url = ((URLAudioStream) audioStream).getURL();
94 } else if (audioStream instanceof FixedLengthAudioStream) {
95 // Since Squeezebox will make multiple requests for the stream, set a timeout on the stream
96 url = audioHTTPServer.serve((FixedLengthAudioStream) audioStream, STREAM_TIMEOUT).toString();
98 if (AudioFormat.WAV.isCompatible(format)) {
99 url += AudioStreamUtils.EXTENSION_SEPARATOR + FileAudioStream.WAV_EXTENSION;
100 } else if (AudioFormat.MP3.isCompatible(format)) {
101 url += AudioStreamUtils.EXTENSION_SEPARATOR + FileAudioStream.MP3_EXTENSION;
104 // Form the URL for streaming the notification from the OH2 web server
105 // Use the callback URL if it is set in the binding configuration
106 String host = callbackUrl == null || callbackUrl.isEmpty() ? playerHandler.getHostAndPort() : callbackUrl;
108 logger.warn("Unable to get host/port from which to stream notification");
113 throw new UnsupportedAudioStreamException(
114 "SqueezeBox can only handle URLAudioStream or FixedLengthAudioStreams.", null);
117 logger.debug("Processing audioStream {} of format {}", url, format);
118 playerHandler.playNotificationSoundURI(new StringType(url));
122 public Set<AudioFormat> getSupportedFormats() {
123 return SUPPORTED_FORMATS;
127 public Set<Class<? extends AudioStream>> getSupportedStreams() {
128 return SUPPORTED_STREAMS;
132 public PercentType getVolume() {
133 return playerHandler.getNotificationSoundVolume();
137 public void setVolume(PercentType volume) {
138 playerHandler.setNotificationSoundVolume(volume);