]> git.basschouten.com Git - openhab-addons.git/blob
7a7425699299d45f04f6e30e4731499b3a8c1fee
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 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.upnpcontrol.internal.audiosink;
14
15 import java.io.IOException;
16 import java.util.Locale;
17 import java.util.Set;
18
19 import org.eclipse.jdt.annotation.NonNullByDefault;
20 import org.eclipse.jdt.annotation.Nullable;
21 import org.openhab.binding.upnpcontrol.internal.handler.UpnpRendererHandler;
22 import org.openhab.core.audio.AudioFormat;
23 import org.openhab.core.audio.AudioHTTPServer;
24 import org.openhab.core.audio.AudioSinkAsync;
25 import org.openhab.core.audio.AudioStream;
26 import org.openhab.core.audio.StreamServed;
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.library.types.PercentType;
31 import org.slf4j.Logger;
32 import org.slf4j.LoggerFactory;
33
34 /**
35  *
36  * @author Mark Herwege - Initial contribution
37  * @author Laurent Garnier - Support for more audio streams through the HTTP audio servlet
38  */
39 @NonNullByDefault
40 public class UpnpAudioSink extends AudioSinkAsync {
41
42     private final Logger logger = LoggerFactory.getLogger(UpnpAudioSink.class);
43
44     private static final Set<Class<? extends AudioStream>> SUPPORTED_STREAMS = Set.of(AudioStream.class);
45     protected UpnpRendererHandler handler;
46     protected AudioHTTPServer audioHTTPServer;
47     protected String callbackUrl;
48
49     public UpnpAudioSink(UpnpRendererHandler handler, AudioHTTPServer audioHTTPServer, String callbackUrl) {
50         this.handler = handler;
51         this.audioHTTPServer = audioHTTPServer;
52         this.callbackUrl = callbackUrl;
53     }
54
55     @Override
56     public String getId() {
57         return handler.getThing().getUID().toString();
58     }
59
60     @Override
61     public @Nullable String getLabel(@Nullable Locale locale) {
62         return handler.getThing().getLabel();
63     }
64
65     @Override
66     protected void processAsynchronously(@Nullable AudioStream audioStream)
67             throws UnsupportedAudioFormatException, UnsupportedAudioStreamException {
68         if (audioStream == null) {
69             stopMedia();
70             return;
71         }
72
73         if (audioStream instanceof URLAudioStream urlAudioStream) {
74             playMedia(urlAudioStream.getURL());
75             try {
76                 audioStream.close();
77             } catch (IOException e) {
78             }
79         } else if (!callbackUrl.isEmpty()) {
80             StreamServed streamServed;
81             try {
82                 streamServed = audioHTTPServer.serve(audioStream, 5, true);
83             } catch (IOException e) {
84                 try {
85                     audioStream.close();
86                 } catch (IOException ex) {
87                 }
88                 throw new UnsupportedAudioStreamException(
89                         handler.getUDN() + " was not able to handle the audio stream (cache on disk failed).",
90                         audioStream.getClass(), e);
91             }
92             streamServed.playEnd().thenRun(() -> this.playbackFinished(audioStream));
93             playMedia(callbackUrl + streamServed.url());
94         } else {
95             logger.warn("We do not have any callback url, so {} cannot play the audio stream!", handler.getUDN());
96             try {
97                 audioStream.close();
98             } catch (IOException e) {
99             }
100         }
101     }
102
103     @Override
104     public Set<AudioFormat> getSupportedFormats() {
105         return handler.getSupportedAudioFormats();
106     }
107
108     @Override
109     public Set<Class<? extends AudioStream>> getSupportedStreams() {
110         return SUPPORTED_STREAMS;
111     }
112
113     @Override
114     public PercentType getVolume() throws IOException {
115         return handler.getCurrentVolume();
116     }
117
118     @Override
119     public void setVolume(@Nullable PercentType volume) throws IOException {
120         if (volume != null) {
121             handler.setVolume(volume);
122         }
123     }
124
125     protected void stopMedia() {
126         handler.stop();
127     }
128
129     protected void playMedia(String url) {
130         String newUrl = url;
131         if (!url.startsWith("x-") && !url.startsWith("http")) {
132             newUrl = "x-file-cifs:" + url;
133         }
134         handler.setCurrentURI(newUrl, "");
135         handler.play();
136     }
137 }