Skip to content

Commit

Permalink
[freeboxos] Align audio sink to freebox binding
Browse files Browse the repository at this point in the history
Related to openhab#15113

Signed-off-by: Laurent Garnier <lg.hc@free.fr>
  • Loading branch information
lolodomo committed Jul 8, 2023
1 parent de1eebd commit 417c5b0
Showing 1 changed file with 61 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import static org.openhab.core.audio.AudioFormat.*;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;
Expand Down Expand Up @@ -47,7 +48,8 @@
@NonNullByDefault
public class AirMediaSink extends AudioSinkAsync {
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(
new AudioFormat(CONTAINER_NONE, CODEC_MP3, null, null, 96000, null),
new AudioFormat(CONTAINER_NONE, CODEC_MP3, null, null, 112000, null),
Expand Down Expand Up @@ -111,46 +113,69 @@ public String getId() {
@Override
protected void processAsynchronously(@Nullable AudioStream audioStream)
throws UnsupportedAudioFormatException, UnsupportedAudioStreamException {
if (thingHandler.getThing().getStatus() == ThingStatus.ONLINE) {
if (thingHandler.getThing().getStatus() != ThingStatus.ONLINE) {
tryClose(audioStream);
return;
}

if (audioStream == null) {
stopMedia();
return;
}

String url;
if (audioStream instanceof URLAudioStream urlAudioStream) {
// it is an external URL, we can access it directly
url = urlAudioStream.getURL();
tryClose(audioStream);
} else {
// we serve it on our own HTTP server
logger.debug("audioStream {} {}", audioStream.getClass().getSimpleName(), audioStream.getFormat());
StreamServed streamServed;
try {
MediaReceiverManager manager = thingHandler.getManager(MediaReceiverManager.class);
if (audioStream == null) {
manager.sendToReceiver(playerName, password, Action.STOP, MediaType.VIDEO);
return;
}

if (audioStream instanceof URLAudioStream urlAudioStream) {
// it is an external URL, we can access it directly
logger.debug("AirPlay audio sink: process url {}", urlAudioStream.getURL());
playMedia(manager, urlAudioStream.getURL());
return;
}
// 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");
}
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));
logger.debug("AirPlay audio sink: process url {}", callbackUrl + streamServed.url());
playMedia(manager, callbackUrl + streamServed.url());
} catch (FreeboxException e) {
logger.warn("Audio stream playback failed: {}", e.getMessage());
streamServed = audioHTTPServer.serve(audioStream, 5, true);
} catch (IOException e) {
tryClose(audioStream);
throw new UnsupportedAudioStreamException(
"AirPlay device was not able to handle the audio stream (cache on disk failed).",
audioStream.getClass(), e);
}
url = callbackUrl + streamServed.url();
streamServed.playEnd().thenRun(() -> {
stopMedia();
this.playbackFinished(audioStream);
});
}
logger.debug("AirPlay audio sink: process url {}", url);
playMedia(url);
}

private void playMedia(MediaReceiverManager manager, String url) throws FreeboxException {
manager.sendToReceiver(playerName, password, Action.STOP, MediaType.VIDEO);
manager.sendToReceiver(playerName, password, Action.START, MediaType.VIDEO, url);
private void tryClose(@Nullable InputStream is) {
if (is != null) {
try {
is.close();
} catch (IOException ignored) {
}
}
}

private void playMedia(String url) {
try {
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
Expand Down

0 comments on commit 417c5b0

Please sign in to comment.