[freeboxos] Align audio sink to freebox binding (#15207)

Related to #15113

Signed-off-by: Laurent Garnier <lg.hc@free.fr>
This commit is contained in:
lolodomo 2023-07-12 11:52:06 +02:00 committed by GitHub
parent 18ae834d68
commit 5c32f80c3b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -15,6 +15,7 @@ package org.openhab.binding.freeboxos.internal.handler;
import static org.openhab.core.audio.AudioFormat.*; import static org.openhab.core.audio.AudioFormat.*;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.util.HashSet; import java.util.HashSet;
import java.util.Locale; import java.util.Locale;
import java.util.Set; import java.util.Set;
@ -47,7 +48,8 @@ import org.slf4j.LoggerFactory;
@NonNullByDefault @NonNullByDefault
public class AirMediaSink extends AudioSinkAsync { public class AirMediaSink extends AudioSinkAsync {
private static final Set<Class<? extends AudioStream>> SUPPORTED_STREAMS = Set.of(AudioStream.class); private static final Set<Class<? extends AudioStream>> SUPPORTED_STREAMS = Set.of(AudioStream.class);
private static final Set<AudioFormat> BASIC_FORMATS = Set.of(WAV, OGG); // OGG seems to not be properly supported (tested with a file produced by VoiceRSS)
private static final Set<AudioFormat> BASIC_FORMATS = Set.of(WAV/* , OGG */);
private static final Set<AudioFormat> ALL_MP3_FORMATS = Set.of( private static final Set<AudioFormat> ALL_MP3_FORMATS = Set.of(
new AudioFormat(CONTAINER_NONE, CODEC_MP3, null, null, 96000, null), new AudioFormat(CONTAINER_NONE, CODEC_MP3, null, null, 96000, null),
new AudioFormat(CONTAINER_NONE, CODEC_MP3, null, null, 112000, null), new AudioFormat(CONTAINER_NONE, CODEC_MP3, null, null, 112000, null),
@ -111,46 +113,69 @@ public class AirMediaSink extends AudioSinkAsync {
@Override @Override
protected void processAsynchronously(@Nullable AudioStream audioStream) protected void processAsynchronously(@Nullable AudioStream audioStream)
throws UnsupportedAudioFormatException, UnsupportedAudioStreamException { throws UnsupportedAudioFormatException, UnsupportedAudioStreamException {
if (thingHandler.getThing().getStatus() == ThingStatus.ONLINE) { if (thingHandler.getThing().getStatus() != ThingStatus.ONLINE) {
try { tryClose(audioStream);
MediaReceiverManager manager = thingHandler.getManager(MediaReceiverManager.class); return;
if (audioStream == null) { }
manager.sendToReceiver(playerName, password, Action.STOP, MediaType.VIDEO);
return;
}
if (audioStream instanceof URLAudioStream urlAudioStream) { if (audioStream == null) {
// it is an external URL, we can access it directly stopMedia();
logger.debug("AirPlay audio sink: process url {}", urlAudioStream.getURL()); return;
playMedia(manager, urlAudioStream.getURL()); }
return;
} String url;
// we serve it on our own HTTP server if (audioStream instanceof URLAudioStream urlAudioStream) {
StreamServed streamServed; // it is an external URL, we can access it directly
try { url = urlAudioStream.getURL();
streamServed = audioHTTPServer.serve(audioStream, 5, true); tryClose(audioStream);
} catch (IOException e) { } else {
try { // we serve it on our own HTTP server
audioStream.close(); logger.debug("audioStream {} {}", audioStream.getClass().getSimpleName(), audioStream.getFormat());
} catch (IOException ex) { StreamServed streamServed;
logger.debug("Exception while closing audioStream"); try {
} streamServed = audioHTTPServer.serve(audioStream, 5, true);
throw new UnsupportedAudioStreamException( } catch (IOException e) {
"AirPlay device was not able to handle the audio stream (cache on disk failed).", tryClose(audioStream);
audioStream.getClass(), e); throw new UnsupportedAudioStreamException(
} "AirPlay device was not able to handle the audio stream (cache on disk failed).",
streamServed.playEnd().thenRun(() -> this.playbackFinished(audioStream)); audioStream.getClass(), e);
logger.debug("AirPlay audio sink: process url {}", callbackUrl + streamServed.url()); }
playMedia(manager, callbackUrl + streamServed.url()); url = callbackUrl + streamServed.url();
} catch (FreeboxException e) { streamServed.playEnd().thenRun(() -> {
logger.warn("Audio stream playback failed: {}", e.getMessage()); stopMedia();
this.playbackFinished(audioStream);
});
}
logger.debug("AirPlay audio sink: process url {}", url);
playMedia(url);
}
private void tryClose(@Nullable InputStream is) {
if (is != null) {
try {
is.close();
} catch (IOException ignored) {
} }
} }
} }
private void playMedia(MediaReceiverManager manager, String url) throws FreeboxException { private void playMedia(String url) {
manager.sendToReceiver(playerName, password, Action.STOP, MediaType.VIDEO); try {
manager.sendToReceiver(playerName, password, Action.START, MediaType.VIDEO, url); MediaReceiverManager manager = thingHandler.getManager(MediaReceiverManager.class);
manager.sendToReceiver(playerName, password, Action.STOP, MediaType.VIDEO);
manager.sendToReceiver(playerName, password, Action.START, MediaType.VIDEO, url);
} catch (FreeboxException e) {
logger.warn("Playing media failed: {}", e.getMessage());
}
}
private void stopMedia() {
try {
MediaReceiverManager manager = thingHandler.getManager(MediaReceiverManager.class);
manager.sendToReceiver(playerName, password, Action.STOP, MediaType.VIDEO);
} catch (FreeboxException e) {
logger.warn("Stopping media failed: {}", e.getMessage());
}
} }
@Override @Override