/* * Copyright (C) 2010 Teleal GmbH, Switzerland * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.teleal.cling.support.connectionmanager; import org.teleal.cling.binding.annotations.UpnpAction; import org.teleal.cling.binding.annotations.UpnpInputArgument; import org.teleal.cling.binding.annotations.UpnpOutputArgument; import org.teleal.cling.binding.annotations.UpnpService; import org.teleal.cling.binding.annotations.UpnpServiceId; import org.teleal.cling.binding.annotations.UpnpServiceType; import org.teleal.cling.binding.annotations.UpnpStateVariable; import org.teleal.cling.binding.annotations.UpnpStateVariables; import org.teleal.cling.model.ServiceReference; import org.teleal.cling.model.action.ActionException; import org.teleal.cling.model.types.UnsignedIntegerFourBytes; import org.teleal.cling.model.types.csv.CSV; import org.teleal.cling.model.types.csv.CSVUnsignedIntegerFourBytes; import org.teleal.cling.support.model.ConnectionInfo; import org.teleal.cling.support.model.ProtocolInfo; import org.teleal.cling.support.model.ProtocolInfos; import java.beans.PropertyChangeSupport; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.logging.Logger; /** * Base for connection management, implements the connection ID "0" behavior. * * @author Christian Bauer * @author Alessio Gaeta */ @UpnpService( serviceId = @UpnpServiceId("ConnectionManager"), serviceType = @UpnpServiceType(value = "ConnectionManager", version = 1), stringConvertibleTypes = {ProtocolInfo.class, ProtocolInfos.class, ServiceReference.class} ) @UpnpStateVariables({ @UpnpStateVariable(name = "SourceProtocolInfo", datatype = "string"), @UpnpStateVariable(name = "SinkProtocolInfo", datatype = "string"), @UpnpStateVariable(name = "CurrentConnectionIDs", datatype = "string"), @UpnpStateVariable(name = "A_ARG_TYPE_ConnectionStatus", allowedValuesEnum = ConnectionInfo.Status.class, sendEvents = false), @UpnpStateVariable(name = "A_ARG_TYPE_ConnectionManager", datatype = "string", sendEvents = false), @UpnpStateVariable(name = "A_ARG_TYPE_Direction", allowedValuesEnum = ConnectionInfo.Direction.class, sendEvents = false), @UpnpStateVariable(name = "A_ARG_TYPE_ProtocolInfo", datatype = "string", sendEvents = false), @UpnpStateVariable(name = "A_ARG_TYPE_ConnectionID", datatype = "i4", sendEvents = false), @UpnpStateVariable(name = "A_ARG_TYPE_AVTransportID", datatype = "i4", sendEvents = false), @UpnpStateVariable(name = "A_ARG_TYPE_RcsID", datatype = "i4", sendEvents = false) }) public class ConnectionManagerService { final private static Logger log = Logger.getLogger(ConnectionManagerService.class.getName()); final protected PropertyChangeSupport propertyChangeSupport; final protected Map<Integer, ConnectionInfo> activeConnections = new ConcurrentHashMap(); final protected ProtocolInfos sourceProtocolInfo; final protected ProtocolInfos sinkProtocolInfo; /** * Creates a default "active" connection with identifier "0". */ public ConnectionManagerService() { this(new ConnectionInfo()); } /** * Creates a default "active" connection with identifier "0". */ public ConnectionManagerService(ProtocolInfos sourceProtocolInfo, ProtocolInfos sinkProtocolInfo) { this(sourceProtocolInfo, sinkProtocolInfo, new ConnectionInfo()); } public ConnectionManagerService(ConnectionInfo... activeConnections) { this(null, new ProtocolInfos(), new ProtocolInfos(), activeConnections); } public ConnectionManagerService(ProtocolInfos sourceProtocolInfo, ProtocolInfos sinkProtocolInfo, ConnectionInfo... activeConnections) { this(null, sourceProtocolInfo, sinkProtocolInfo, activeConnections); } public ConnectionManagerService(PropertyChangeSupport propertyChangeSupport, ProtocolInfos sourceProtocolInfo, ProtocolInfos sinkProtocolInfo, ConnectionInfo... activeConnections) { this.propertyChangeSupport = propertyChangeSupport == null ? new PropertyChangeSupport(this) : propertyChangeSupport; this.sourceProtocolInfo = sourceProtocolInfo; this.sinkProtocolInfo = sinkProtocolInfo; for (ConnectionInfo activeConnection : activeConnections) { this.activeConnections.put(activeConnection.getConnectionID(), activeConnection); } } public PropertyChangeSupport getPropertyChangeSupport() { return propertyChangeSupport; } @UpnpAction(out = { @UpnpOutputArgument(name = "RcsID", getterName = "getRcsID"), @UpnpOutputArgument(name = "AVTransportID", getterName = "getAvTransportID"), @UpnpOutputArgument(name = "ProtocolInfo", getterName = "getProtocolInfo"), @UpnpOutputArgument(name = "PeerConnectionManager", stateVariable = "A_ARG_TYPE_ConnectionManager", getterName = "getPeerConnectionManager"), @UpnpOutputArgument(name = "PeerConnectionID", stateVariable = "A_ARG_TYPE_ConnectionID", getterName = "getPeerConnectionID"), @UpnpOutputArgument(name = "Direction", getterName = "getDirection"), @UpnpOutputArgument(name = "Status", stateVariable = "A_ARG_TYPE_ConnectionStatus", getterName = "getConnectionStatus") }) synchronized public ConnectionInfo getCurrentConnectionInfo(@UpnpInputArgument(name = "ConnectionID") int connectionId) throws ActionException { log.fine("Getting connection information of connection ID: " + connectionId); ConnectionInfo info; if ((info = activeConnections.get(connectionId)) == null) { throw new ConnectionManagerException( ConnectionManagerErrorCode.INVALID_CONNECTION_REFERENCE, "Non-active connection ID: " + connectionId ); } return info; } @UpnpAction(out = { @UpnpOutputArgument(name = "ConnectionIDs") }) synchronized public CSV<UnsignedIntegerFourBytes> getCurrentConnectionIDs() { CSV<UnsignedIntegerFourBytes> csv = new CSVUnsignedIntegerFourBytes(); for (Integer connectionID : activeConnections.keySet()) { csv.add(new UnsignedIntegerFourBytes(connectionID)); } log.fine("Returning current connection IDs: " + csv.size()); return csv; } @UpnpAction(out = { @UpnpOutputArgument(name = "Source", stateVariable = "SourceProtocolInfo", getterName = "getSourceProtocolInfo"), @UpnpOutputArgument(name = "Sink", stateVariable = "SinkProtocolInfo", getterName = "getSinkProtocolInfo") }) synchronized public void getProtocolInfo() throws ActionException { // NOOP } synchronized public ProtocolInfos getSourceProtocolInfo() { return sourceProtocolInfo; } synchronized public ProtocolInfos getSinkProtocolInfo() { return sinkProtocolInfo; } }