]> git.basschouten.com Git - openhab-addons.git/blob
dfb66deb438f1433c418d622f6fdd43d5c0452e2
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2021 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
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
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.binding.squeezebox.internal;
14
15 import java.util.HashSet;
16 import java.util.Locale;
17 import java.util.Set;
18
19 import org.apache.commons.lang.StringUtils;
20 import org.openhab.binding.squeezebox.internal.handler.SqueezeBoxPlayerHandler;
21 import org.openhab.core.audio.AudioFormat;
22 import org.openhab.core.audio.AudioHTTPServer;
23 import org.openhab.core.audio.AudioSink;
24 import org.openhab.core.audio.AudioStream;
25 import org.openhab.core.audio.FileAudioStream;
26 import org.openhab.core.audio.FixedLengthAudioStream;
27 import org.openhab.core.audio.URLAudioStream;
28 import org.openhab.core.audio.UnsupportedAudioFormatException;
29 import org.openhab.core.audio.UnsupportedAudioStreamException;
30 import org.openhab.core.audio.utils.AudioStreamUtils;
31 import org.openhab.core.library.types.PercentType;
32 import org.openhab.core.library.types.StringType;
33 import org.slf4j.Logger;
34 import org.slf4j.LoggerFactory;
35
36 /**
37  * This makes a SqueezeBox Player serve as an {@link AudioSink}-
38  *
39  * @author Mark Hilbush - Initial contribution
40  * @author Mark Hilbush - Add callbackUrl
41  */
42 public class SqueezeBoxAudioSink implements AudioSink {
43     private final Logger logger = LoggerFactory.getLogger(SqueezeBoxAudioSink.class);
44
45     private static final HashSet<AudioFormat> SUPPORTED_FORMATS = new HashSet<>();
46     private static final HashSet<Class<? extends AudioStream>> SUPPORTED_STREAMS = new HashSet<>();
47
48     // Needed because Squeezebox does multiple requests for the stream
49     private static final int STREAM_TIMEOUT = 15;
50
51     private String callbackUrl;
52
53     static {
54         SUPPORTED_FORMATS.add(AudioFormat.WAV);
55         SUPPORTED_FORMATS.add(AudioFormat.MP3);
56
57         SUPPORTED_STREAMS.add(FixedLengthAudioStream.class);
58         SUPPORTED_STREAMS.add(URLAudioStream.class);
59     }
60
61     private AudioHTTPServer audioHTTPServer;
62     private SqueezeBoxPlayerHandler playerHandler;
63
64     public SqueezeBoxAudioSink(SqueezeBoxPlayerHandler playerHandler, AudioHTTPServer audioHTTPServer,
65             String callbackUrl) {
66         this.playerHandler = playerHandler;
67         this.audioHTTPServer = audioHTTPServer;
68         this.callbackUrl = callbackUrl;
69         if (StringUtils.isNotEmpty(callbackUrl)) {
70             logger.debug("SqueezeBox AudioSink created with callback URL {}", callbackUrl);
71         }
72     }
73
74     @Override
75     public String getId() {
76         return playerHandler.getThing().getUID().toString();
77     }
78
79     @Override
80     public String getLabel(Locale locale) {
81         return playerHandler.getThing().getLabel();
82     }
83
84     @Override
85     public void process(AudioStream audioStream)
86             throws UnsupportedAudioFormatException, UnsupportedAudioStreamException {
87         AudioFormat format = audioStream.getFormat();
88         if (!AudioFormat.WAV.isCompatible(format) && !AudioFormat.MP3.isCompatible(format)) {
89             throw new UnsupportedAudioFormatException("Currently only MP3 and WAV formats are supported: ", format);
90         }
91
92         String url;
93         if (audioStream instanceof URLAudioStream) {
94             url = ((URLAudioStream) audioStream).getURL();
95         } else if (audioStream instanceof FixedLengthAudioStream) {
96             // Since Squeezebox will make multiple requests for the stream, set a timeout on the stream
97             url = audioHTTPServer.serve((FixedLengthAudioStream) audioStream, STREAM_TIMEOUT).toString();
98
99             if (AudioFormat.WAV.isCompatible(format)) {
100                 url += AudioStreamUtils.EXTENSION_SEPARATOR + FileAudioStream.WAV_EXTENSION;
101             } else if (AudioFormat.MP3.isCompatible(format)) {
102                 url += AudioStreamUtils.EXTENSION_SEPARATOR + FileAudioStream.MP3_EXTENSION;
103             }
104
105             // Form the URL for streaming the notification from the OH2 web server
106             // Use the callback URL if it is set in the binding configuration
107             String host = StringUtils.isEmpty(callbackUrl) ? playerHandler.getHostAndPort() : callbackUrl;
108             if (host == null) {
109                 logger.warn("Unable to get host/port from which to stream notification");
110                 return;
111             }
112             url = host + url;
113         } else {
114             throw new UnsupportedAudioStreamException(
115                     "SqueezeBox can only handle URLAudioStream or FixedLengthAudioStreams.", null);
116         }
117
118         logger.debug("Processing audioStream {} of format {}", url, format);
119         playerHandler.playNotificationSoundURI(new StringType(url));
120     }
121
122     @Override
123     public Set<AudioFormat> getSupportedFormats() {
124         return SUPPORTED_FORMATS;
125     }
126
127     @Override
128     public Set<Class<? extends AudioStream>> getSupportedStreams() {
129         return SUPPORTED_STREAMS;
130     }
131
132     @Override
133     public PercentType getVolume() {
134         return playerHandler.getNotificationSoundVolume();
135     }
136
137     @Override
138     public void setVolume(PercentType volume) {
139         playerHandler.setNotificationSoundVolume(volume);
140     }
141 }