Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[freebox] Support for more audio streams through the HTTP audio servlet
Browse files Browse the repository at this point in the history
Related to #15113

Signed-off-by: Laurent Garnier <[email protected]>
lolodomo committed Jul 1, 2023

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
1 parent 07e6403 commit d4ac768
Showing 1 changed file with 45 additions and 34 deletions.
Original file line number Diff line number Diff line change
@@ -27,8 +27,9 @@
import org.openhab.core.audio.AudioFormat;
import org.openhab.core.audio.AudioHTTPServer;
import org.openhab.core.audio.AudioSink;
import org.openhab.core.audio.AudioSinkAsync;
import org.openhab.core.audio.AudioStream;
import org.openhab.core.audio.FixedLengthAudioStream;
import org.openhab.core.audio.StreamServed;
import org.openhab.core.audio.URLAudioStream;
import org.openhab.core.audio.UnsupportedAudioFormatException;
import org.openhab.core.audio.UnsupportedAudioStreamException;
@@ -43,9 +44,10 @@
* This makes an AirPlay device to serve as an {@link AudioSink}-
*
* @author Laurent Garnier - Initial contribution for AudioSink and notifications
* @author Laurent Garnier - Support for more audio streams through the HTTP audio servlet
*/
@NonNullByDefault
public class FreeboxAirPlayAudioSink implements AudioSink {
public class FreeboxAirPlayAudioSink extends AudioSinkAsync {

private final Logger logger = LoggerFactory.getLogger(FreeboxAirPlayAudioSink.class);

@@ -59,15 +61,11 @@ public class FreeboxAirPlayAudioSink implements AudioSink {
private static final AudioFormat MP3_320 = new AudioFormat(CONTAINER_NONE, CODEC_MP3, null, null, 320000, null);

private static final Set<AudioFormat> SUPPORTED_FORMATS = new HashSet<>();
private static final HashSet<Class<? extends AudioStream>> SUPPORTED_STREAMS = new HashSet<>();
private static final Set<Class<? extends AudioStream>> SUPPORTED_STREAMS = Set.of(AudioStream.class);
private AudioHTTPServer audioHTTPServer;
private FreeboxThingHandler handler;
private @Nullable String callbackUrl;

static {
SUPPORTED_STREAMS.add(AudioStream.class);
}

public FreeboxAirPlayAudioSink(FreeboxThingHandler handler, AudioHTTPServer audioHTTPServer,
@Nullable String callbackUrl) {
this.handler = handler;
@@ -103,7 +101,7 @@ public String getId() {
}

@Override
public void process(@Nullable AudioStream audioStream)
protected void processAsynchronously(@Nullable AudioStream audioStream)
throws UnsupportedAudioFormatException, UnsupportedAudioStreamException {
if (!ThingHandlerHelper.isHandlerInitialized(handler)
|| ((handler.getThing().getStatus() == ThingStatus.OFFLINE)
@@ -122,35 +120,48 @@ public void process(@Nullable AudioStream audioStream)
return;
}

String url = null;
if (audioStream instanceof URLAudioStream) {
if (audioStream instanceof URLAudioStream urlAudioStream) {
// it is an external URL, we can access it directly
URLAudioStream urlAudioStream = (URLAudioStream) audioStream;
url = urlAudioStream.getURL();
} else {
if (callbackUrl != null) {
// we serve it on our own HTTP server
String relativeUrl;
if (audioStream instanceof FixedLengthAudioStream) {
relativeUrl = audioHTTPServer.serve((FixedLengthAudioStream) audioStream, 20);
} else {
relativeUrl = audioHTTPServer.serve(audioStream);
try {
logger.debug("AirPlay audio sink: process url {}", urlAudioStream.getURL());
handler.playMedia(urlAudioStream.getURL());
} catch (FreeboxException e) {
logger.warn("Audio stream playback failed: {}", e.getMessage());
}
try {
audioStream.close();
} catch (IOException e) {
logger.debug("Exception while closing audioStream");
}
} else if (callbackUrl != null) {
// we serve it on our own HTTP server
StreamServed streamServed;
try {
streamServed = audioHTTPServer.serve(audioStream, 5, true);
} catch (IOException e) {
try {
audioStream.close();
} catch (IOException ex) {
logger.debug("Exception while closing audioStream");
}
url = callbackUrl + relativeUrl;
} else {
logger.warn("We do not have any callback url, so AirPlay device cannot play the audio stream!");
throw new UnsupportedAudioStreamException(
"AirPlay device was not able to handle the audio stream (cache on disk failed).",
audioStream.getClass(), e);
}
streamServed.playEnd().thenRun(() -> this.playbackFinished(audioStream));
try {
logger.debug("AirPlay audio sink: process url {}", callbackUrl + streamServed.url());
handler.playMedia(callbackUrl + streamServed.url());
} catch (FreeboxException e) {
logger.warn("Audio stream playback failed: {}", e.getMessage());
}
} else {
logger.warn("We do not have any callback url, so AirPlay device cannot play the audio stream!");
try {
audioStream.close();
} catch (IOException e) {
logger.debug("Exception while closing audioStream");
}
}
try {
audioStream.close();
} catch (IOException e) {
logger.debug("Exception while closing audioStream", e);
}
try {
logger.debug("AirPlay audio sink: process url {}", url);
handler.playMedia(url);
} catch (FreeboxException e) {
logger.warn("Audio stream playback failed: {}", e.getMessage());
}
}

0 comments on commit d4ac768

Please sign in to comment.