[pulseaudio] Add "idle timeout" to Pulseaudio audio sink (#10731)
* Add "idle timeout" to pulseaudio audio sink to allow the sink to disconnect after being idle Signed-off-by: Timo Litzius <dev@dbzman-online.eu>
This commit is contained in:
parent
6d68746b60
commit
7109475929
bundles/org.openhab.binding.pulseaudio/src/main
java/org/openhab/binding/pulseaudio/internal
resources/OH-INF/thing
@ -18,6 +18,8 @@ import java.net.Socket;
|
||||
import java.util.HashSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import javazoom.spi.mpeg.sampled.convert.MpegFormatConversionProvider;
|
||||
import javazoom.spi.mpeg.sampled.file.MpegAudioFileReader;
|
||||
|
||||
@ -52,17 +54,21 @@ public class PulseAudioAudioSink implements AudioSink {
|
||||
private static final HashSet<Class<? extends AudioStream>> SUPPORTED_STREAMS = new HashSet<>();
|
||||
|
||||
private PulseaudioHandler pulseaudioHandler;
|
||||
private ScheduledExecutorService scheduler;
|
||||
|
||||
private @Nullable Socket clientSocket;
|
||||
|
||||
private boolean isIdle = true;
|
||||
|
||||
static {
|
||||
SUPPORTED_FORMATS.add(AudioFormat.WAV);
|
||||
SUPPORTED_FORMATS.add(AudioFormat.MP3);
|
||||
SUPPORTED_STREAMS.add(FixedLengthAudioStream.class);
|
||||
}
|
||||
|
||||
public PulseAudioAudioSink(PulseaudioHandler pulseaudioHandler) {
|
||||
public PulseAudioAudioSink(PulseaudioHandler pulseaudioHandler, ScheduledExecutorService scheduler) {
|
||||
this.pulseaudioHandler = pulseaudioHandler;
|
||||
this.scheduler = scheduler;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -120,11 +126,14 @@ public class PulseAudioAudioSink implements AudioSink {
|
||||
* Disconnect the socket to pulseaudio simple protocol
|
||||
*/
|
||||
public void disconnect() {
|
||||
if (clientSocket != null) {
|
||||
if (clientSocket != null && isIdle) {
|
||||
logger.debug("Disconnecting");
|
||||
try {
|
||||
clientSocket.close();
|
||||
} catch (IOException e) {
|
||||
}
|
||||
} else {
|
||||
logger.debug("Stream still running or socket not open");
|
||||
}
|
||||
}
|
||||
|
||||
@ -153,6 +162,7 @@ public class PulseAudioAudioSink implements AudioSink {
|
||||
connectIfNeeded();
|
||||
if (audioInputStream != null && clientSocket != null) {
|
||||
// send raw audio to the socket and to pulse audio
|
||||
isIdle = false;
|
||||
audioInputStream.transferTo(clientSocket.getOutputStream());
|
||||
break;
|
||||
}
|
||||
@ -178,9 +188,16 @@ public class PulseAudioAudioSink implements AudioSink {
|
||||
audioInputStream.close();
|
||||
}
|
||||
audioStream.close();
|
||||
scheduleDisconnect();
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
isIdle = true;
|
||||
}
|
||||
|
||||
public void scheduleDisconnect() {
|
||||
logger.debug("Scheduling disconnect");
|
||||
scheduler.schedule(this::disconnect, pulseaudioHandler.getIdleTimeout(), TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -53,6 +53,7 @@ public class PulseaudioBindingConstants {
|
||||
public static final String DEVICE_PARAMETER_NAME = "name";
|
||||
public static final String DEVICE_PARAMETER_AUDIO_SINK_ACTIVATION = "activateSimpleProtocolSink";
|
||||
public static final String DEVICE_PARAMETER_AUDIO_SINK_PORT = "simpleProtocolSinkPort";
|
||||
public static final String DEVICE_PARAMETER_AUDIO_SINK_IDLE_TIMEOUT = "simpleProtocolSinkIdleTimeout";
|
||||
|
||||
public static final String MODULE_SIMPLE_PROTOCOL_TCP_NAME = "module-simple-protocol-tcp";
|
||||
public static final int MODULE_SIMPLE_PROTOCOL_TCP_DEFAULT_PORT = 4711;
|
||||
|
@ -118,7 +118,7 @@ public class PulseaudioHandler extends BaseThingHandler implements DeviceStatusL
|
||||
public void run() {
|
||||
// Register the sink as an audio sink in openhab
|
||||
logger.trace("Registering an audio sink for pulse audio sink thing {}", thing.getUID());
|
||||
PulseAudioAudioSink audioSink = new PulseAudioAudioSink(thisHandler);
|
||||
PulseAudioAudioSink audioSink = new PulseAudioAudioSink(thisHandler, scheduler);
|
||||
setAudioSink(audioSink);
|
||||
try {
|
||||
audioSink.connectIfNeeded();
|
||||
@ -128,6 +128,8 @@ public class PulseaudioHandler extends BaseThingHandler implements DeviceStatusL
|
||||
} catch (InterruptedException i) {
|
||||
logger.info("Interrupted during sink audio connection: {}", i.getMessage());
|
||||
return;
|
||||
} finally {
|
||||
audioSink.scheduleDisconnect();
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
ServiceRegistration<AudioSink> reg = (ServiceRegistration<AudioSink>) bundleContext
|
||||
@ -367,6 +369,11 @@ public class PulseaudioHandler extends BaseThingHandler implements DeviceStatusL
|
||||
.orElse(simpleTcpPortPref);
|
||||
}
|
||||
|
||||
public int getIdleTimeout() {
|
||||
return ((BigDecimal) getThing().getConfiguration()
|
||||
.get(PulseaudioBindingConstants.DEVICE_PARAMETER_AUDIO_SINK_IDLE_TIMEOUT)).intValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDeviceRemoved(PulseaudioBridgeHandler bridge, AbstractAudioDeviceConfig device) {
|
||||
if (device.getPaName().equals(name)) {
|
||||
|
@ -33,6 +33,13 @@
|
||||
<description>Default Port to allocate for use by module-simple-protocol-tcp on the pulseaudio server</description>
|
||||
<default>4711</default>
|
||||
</parameter>
|
||||
<parameter name="simpleProtocolSinkIdleTimeout" type="integer" required="false">
|
||||
<label>Idle Timeout</label>
|
||||
<description>Timeout in ms after which the connection will be closed when no stream is running. This ensures that
|
||||
your speaker is not on all the time and the pulseaudio sink can go to idle mode.
|
||||
</description>
|
||||
<default>30000</default>
|
||||
</parameter>
|
||||
</config-description>
|
||||
</thing-type>
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user