Skip to content

Commit 0562b0a

Browse files
authoredAug 10, 2024··
[freeboxos] Fix start/stop audio sink (openhab#17223)
* [freeboxos] Fix start/stop audio sink Fix openhab#17208 Signed-off-by: Laurent Garnier <lg.hc@free.fr>
1 parent 39eca04 commit 0562b0a

File tree

2 files changed

+57
-31
lines changed

2 files changed

+57
-31
lines changed
 

‎bundles/org.openhab.binding.freeboxos/src/main/java/org/openhab/binding/freeboxos/internal/handler/ApiConsumerHandler.java

+41-31
Original file line numberDiff line numberDiff line change
@@ -87,40 +87,62 @@ private void initializeOnceBridgeOnline(FreeboxOsHandler bridgeHandler) {
8787
Map<String, String> properties = editProperties();
8888
try {
8989
initializeProperties(properties);
90-
checkAirMediaCapabilities(properties);
9190
updateProperties(properties);
9291
} catch (FreeboxException e) {
9392
logger.warn("Error getting thing {} properties: {}", thing.getUID(), e.getMessage());
9493
}
9594

96-
boolean isAudioReceiver = Boolean.parseBoolean(properties.get(MediaType.AUDIO.name()));
97-
if (isAudioReceiver) {
98-
configureMediaSink(bridgeHandler, properties.getOrDefault(Source.UPNP.name(), ""));
99-
}
100-
10195
startRefreshJob();
10296
}
10397

104-
private void configureMediaSink(FreeboxOsHandler bridgeHandler, String upnpName) {
98+
protected void configureMediaSink() {
10599
try {
100+
String upnpName = editProperties().getOrDefault(Source.UPNP.name(), "");
106101
Receiver receiver = getManager(MediaReceiverManager.class).getReceiver(upnpName);
107-
if (receiver != null && reg == null) {
108-
ApiConsumerConfiguration config = getConfig().as(ApiConsumerConfiguration.class);
109-
String callbackURL = bridgeHandler.getCallbackURL();
110-
if (!config.password.isEmpty() || !receiver.passwordProtected()) {
111-
reg = bridgeHandler.getBundleContext().registerService(
112-
AudioSink.class.getName(), new AirMediaSink(this, bridgeHandler.getAudioHTTPServer(),
113-
callbackURL, receiver.name(), config.password, config.acceptAllMp3),
114-
new Hashtable<>());
115-
} else {
116-
logger.info("A password needs to be configured to enable Air Media capability.");
117-
}
102+
if (receiver != null) {
103+
Map<String, String> properties = editProperties();
104+
receiver.capabilities().entrySet()
105+
.forEach(entry -> properties.put(entry.getKey().name(), entry.getValue().toString()));
106+
updateProperties(properties);
107+
108+
startAudioSink(receiver);
109+
} else {
110+
stopAudioSink();
118111
}
119112
} catch (FreeboxException e) {
120113
logger.warn("Unable to retrieve Media Receivers: {}", e.getMessage());
121114
}
122115
}
123116

117+
private void startAudioSink(Receiver receiver) {
118+
FreeboxOsHandler bridgeHandler = checkBridgeHandler();
119+
// Only video and photo is supported by the API so use VIDEO capability for audio
120+
Boolean isAudioReceiver = receiver.capabilities().get(MediaType.VIDEO);
121+
if (reg == null && bridgeHandler != null && isAudioReceiver != null && isAudioReceiver.booleanValue()) {
122+
ApiConsumerConfiguration config = getConfig().as(ApiConsumerConfiguration.class);
123+
String callbackURL = bridgeHandler.getCallbackURL();
124+
if (!config.password.isEmpty() || !receiver.passwordProtected()) {
125+
reg = bridgeHandler.getBundleContext()
126+
.registerService(
127+
AudioSink.class.getName(), new AirMediaSink(this, bridgeHandler.getAudioHTTPServer(),
128+
callbackURL, receiver.name(), config.password, config.acceptAllMp3),
129+
new Hashtable<>());
130+
logger.debug("Audio sink registered for {}.", receiver.name());
131+
} else {
132+
logger.warn("A password needs to be configured to enable Air Media capability.");
133+
}
134+
}
135+
}
136+
137+
private void stopAudioSink() {
138+
ServiceRegistration<?> localReg = reg;
139+
if (localReg != null) {
140+
localReg.unregister();
141+
logger.debug("Audio sink unregistered");
142+
reg = null;
143+
}
144+
}
145+
124146
public <T extends RestManager> T getManager(Class<T> clazz) throws FreeboxException {
125147
FreeboxOsHandler handler = checkBridgeHandler();
126148
if (handler != null) {
@@ -159,15 +181,6 @@ public void handleCommand(ChannelUID channelUID, Command command) {
159181
}
160182
}
161183

162-
private void checkAirMediaCapabilities(Map<String, String> properties) throws FreeboxException {
163-
String upnpName = properties.getOrDefault(Source.UPNP.name(), "");
164-
Receiver receiver = getManager(MediaReceiverManager.class).getReceiver(upnpName);
165-
if (receiver != null) {
166-
receiver.capabilities().entrySet()
167-
.forEach(entry -> properties.put(entry.getKey().name(), entry.getValue().toString()));
168-
}
169-
}
170-
171184
private @Nullable FreeboxOsHandler checkBridgeHandler() {
172185
Bridge bridge = getBridge();
173186
if (bridge != null) {
@@ -192,10 +205,7 @@ private void checkAirMediaCapabilities(Map<String, String> properties) throws Fr
192205
@Override
193206
public void dispose() {
194207
stopJobs();
195-
ServiceRegistration<?> localReg = reg;
196-
if (localReg != null) {
197-
localReg.unregister();
198-
}
208+
stopAudioSink();
199209
super.dispose();
200210
}
201211

‎bundles/org.openhab.binding.freeboxos/src/main/java/org/openhab/binding/freeboxos/internal/handler/HostHandler.java

+16
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ public class HostHandler extends ApiConsumerHandler {
4646
// We start in pull mode and switch to push after a first update...
4747
protected boolean pushSubscribed = false;
4848

49+
protected boolean reachable;
50+
51+
private int tryConfigureMediaSink = 1;
52+
4953
public HostHandler(Thing thing) {
5054
super(thing);
5155
statusDrivenByBridge = false;
@@ -78,6 +82,11 @@ protected void cancelPushSubscription() {
7882

7983
@Override
8084
protected void internalPoll() throws FreeboxException {
85+
if (tryConfigureMediaSink > 0) {
86+
configureMediaSink();
87+
tryConfigureMediaSink--;
88+
}
89+
8190
if (pushSubscribed) {
8291
return;
8392
}
@@ -109,6 +118,13 @@ public void updateConnectivityChannels(LanHost host) {
109118
updateChannelDateTimeState(CONNECTIVITY, LAST_SEEN, host.getLastSeen());
110119
updateChannelString(CONNECTIVITY, IP_ADDRESS, host.getIpv4());
111120
updateStatus(host.reachable() ? ThingStatus.ONLINE : ThingStatus.OFFLINE);
121+
// We will check and configure audio sink only when the host reachability changed
122+
if (reachable != host.reachable()) {
123+
reachable = host.reachable();
124+
// It can take time until the Media Receiver API returns the receiver after it becomes reachable.
125+
// So this will be checked during the next 2 polls.
126+
tryConfigureMediaSink = 2;
127+
}
112128
}
113129

114130
public void wol() {

0 commit comments

Comments
 (0)
Please sign in to comment.