]> git.basschouten.com Git - openhab-addons.git/blob
73952f2494aade91f217a7c3f37a7a2688869c9c
[openhab-addons.git] /
1 /**
2  * Copyright (c) 2010-2023 Contributors to the openHAB project
3  *
4  * See the NOTICE file(s) distributed with this work for additional
5  * information.
6  *
7  * This program and the accompanying materials are made available under the
8  * terms of the Eclipse Public License 2.0 which is available at
9  * http://www.eclipse.org/legal/epl-2.0
10  *
11  * SPDX-License-Identifier: EPL-2.0
12  */
13 package org.openhab.binding.pulseaudio.internal;
14
15 import java.util.Collections;
16 import java.util.HashMap;
17 import java.util.Hashtable;
18 import java.util.Map;
19 import java.util.Set;
20 import java.util.stream.Collectors;
21 import java.util.stream.Stream;
22
23 import org.eclipse.jdt.annotation.NonNullByDefault;
24 import org.eclipse.jdt.annotation.Nullable;
25 import org.openhab.binding.pulseaudio.internal.discovery.PulseaudioDeviceDiscoveryService;
26 import org.openhab.binding.pulseaudio.internal.handler.PulseaudioBridgeHandler;
27 import org.openhab.binding.pulseaudio.internal.handler.PulseaudioHandler;
28 import org.openhab.core.audio.utils.AudioSinkUtils;
29 import org.openhab.core.config.core.Configuration;
30 import org.openhab.core.config.discovery.DiscoveryService;
31 import org.openhab.core.thing.Bridge;
32 import org.openhab.core.thing.Thing;
33 import org.openhab.core.thing.ThingTypeUID;
34 import org.openhab.core.thing.ThingUID;
35 import org.openhab.core.thing.binding.BaseThingHandlerFactory;
36 import org.openhab.core.thing.binding.ThingHandler;
37 import org.openhab.core.thing.binding.ThingHandlerFactory;
38 import org.osgi.framework.ServiceRegistration;
39 import org.osgi.service.component.ComponentContext;
40 import org.osgi.service.component.annotations.Activate;
41 import org.osgi.service.component.annotations.Component;
42 import org.osgi.service.component.annotations.Modified;
43 import org.osgi.service.component.annotations.Reference;
44 import org.slf4j.Logger;
45 import org.slf4j.LoggerFactory;
46
47 /**
48  * The {@link PulseaudioHandlerFactory} is responsible for creating things and thing
49  * handlers.
50  *
51  * @author Tobias Bräutigam - Initial contribution
52  */
53 @Component(service = ThingHandlerFactory.class, configurationPid = "binding.pulseaudio")
54 @NonNullByDefault
55 public class PulseaudioHandlerFactory extends BaseThingHandlerFactory {
56     private final Logger logger = LoggerFactory.getLogger(PulseaudioHandlerFactory.class);
57
58     public static final Set<ThingTypeUID> SUPPORTED_THING_TYPES_UIDS = Collections
59             .unmodifiableSet(Stream.concat(PulseaudioBridgeHandler.SUPPORTED_THING_TYPES_UIDS.stream(),
60                     PulseaudioHandler.SUPPORTED_THING_TYPES_UIDS.stream()).collect(Collectors.toSet()));
61
62     private final Map<ThingHandler, ServiceRegistration<?>> discoveryServiceReg = new HashMap<>();
63
64     private PulseAudioBindingConfiguration configuration = new PulseAudioBindingConfiguration();
65
66     private AudioSinkUtils audioSinkUtils;
67
68     @Activate
69     public PulseaudioHandlerFactory(@Reference AudioSinkUtils audioSinkUtils) {
70         this.audioSinkUtils = audioSinkUtils;
71     }
72
73     @Override
74     public boolean supportsThingType(ThingTypeUID thingTypeUID) {
75         return SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID);
76     }
77
78     @Override
79     public @Nullable Thing createThing(ThingTypeUID thingTypeUID, Configuration configuration,
80             @Nullable ThingUID thingUID, @Nullable ThingUID bridgeUID) {
81         if (PulseaudioBridgeHandler.SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID)) {
82             return super.createThing(thingTypeUID, configuration, thingUID, null);
83         }
84         if (PulseaudioHandler.SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID)) {
85             ThingUID deviceUID = getPulseaudioDeviceUID(thingTypeUID, thingUID, configuration, bridgeUID);
86             return super.createThing(thingTypeUID, configuration, deviceUID, bridgeUID);
87         }
88         throw new IllegalArgumentException("The thing type " + thingTypeUID + " is not supported by the binding.");
89     }
90
91     private void registerDeviceDiscoveryService(PulseaudioBridgeHandler paBridgeHandler) {
92         PulseaudioDeviceDiscoveryService discoveryService = new PulseaudioDeviceDiscoveryService(paBridgeHandler);
93         discoveryService.activate();
94         this.discoveryServiceReg.put(paBridgeHandler,
95                 bundleContext.registerService(DiscoveryService.class.getName(), discoveryService, new Hashtable<>()));
96     }
97
98     private ThingUID getPulseaudioDeviceUID(ThingTypeUID thingTypeUID, @Nullable ThingUID thingUID,
99             Configuration configuration, @Nullable ThingUID bridgeUID) {
100         if (thingUID == null) {
101             String name = (String) configuration.get(PulseaudioBindingConstants.DEVICE_PARAMETER_NAME_OR_DESCRIPTION);
102             return new ThingUID(thingTypeUID, name, bridgeUID == null ? null : bridgeUID.getId());
103         }
104         return thingUID;
105     }
106
107     @Override
108     protected void removeHandler(ThingHandler thingHandler) {
109         ServiceRegistration<?> serviceRegistration = this.discoveryServiceReg.get(thingHandler);
110         if (serviceRegistration != null) {
111             PulseaudioDeviceDiscoveryService service = (PulseaudioDeviceDiscoveryService) bundleContext
112                     .getService(serviceRegistration.getReference());
113             if (service != null) {
114                 service.deactivate();
115             }
116             serviceRegistration.unregister();
117         }
118         discoveryServiceReg.remove(thingHandler);
119         super.removeHandler(thingHandler);
120     }
121
122     @Override
123     protected @Nullable ThingHandler createHandler(Thing thing) {
124         ThingTypeUID thingTypeUID = thing.getThingTypeUID();
125
126         if (PulseaudioBridgeHandler.SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID)) {
127             PulseaudioBridgeHandler handler = new PulseaudioBridgeHandler((Bridge) thing, configuration);
128             registerDeviceDiscoveryService(handler);
129             return handler;
130         } else if (PulseaudioHandler.SUPPORTED_THING_TYPES_UIDS.contains(thingTypeUID)) {
131             return new PulseaudioHandler(thing, bundleContext, audioSinkUtils);
132         }
133
134         return null;
135     }
136
137     // The activate component call is used to access the bindings configuration
138     @Activate
139     protected synchronized void activate(ComponentContext componentContext, Map<String, Object> config) {
140         super.activate(componentContext);
141         modified(config);
142     }
143
144     @Modified
145     protected void modified(Map<String, Object> config) {
146         configuration.update(new Configuration(config).as(PulseAudioBindingConfiguration.class));
147         logger.debug("pulseaudio configuration update received ({})", config);
148     }
149 }