avtransportservice.java
来自「android_UPNP_DLNA_控制点」· Java 代码 · 共 309 行
JAVA
309 行
/* * 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.avtransport.impl;import org.teleal.cling.model.ModelUtil;import org.teleal.cling.model.types.ErrorCode;import org.teleal.cling.model.types.UnsignedIntegerFourBytes;import org.teleal.cling.support.avtransport.AVTransportErrorCode;import org.teleal.cling.support.avtransport.AVTransportException;import org.teleal.cling.support.avtransport.AbstractAVTransportService;import org.teleal.cling.support.avtransport.impl.state.AbstractState;import org.teleal.cling.support.lastchange.LastChange;import org.teleal.cling.support.model.AVTransport;import org.teleal.cling.support.model.DeviceCapabilities;import org.teleal.cling.support.model.MediaInfo;import org.teleal.cling.support.model.PlayMode;import org.teleal.cling.support.model.PositionInfo;import org.teleal.cling.support.model.RecordQualityMode;import org.teleal.cling.support.model.SeekMode;import org.teleal.cling.support.model.StorageMedium;import org.teleal.cling.support.model.TransportAction;import org.teleal.cling.support.model.TransportInfo;import org.teleal.cling.support.model.TransportSettings;import org.teleal.common.statemachine.StateMachineBuilder;import org.teleal.common.statemachine.TransitionException;import java.net.URI;import java.util.Map;import java.util.concurrent.ConcurrentHashMap;import java.util.logging.Logger;/** * State-machine based implementation of AVTransport service. * <p> * One logical AVTransport is represented by: * </p> * <ul> * <li> * One {@link org.teleal.cling.support.avtransport.impl.AVTransportStateMachine} * instance that accepts the action method call as a proxy. * </li> * <li> * Each state machine holds several instances of * {@link org.teleal.cling.support.avtransport.impl.state.AbstractState}, created on * instantation of the state machine. The "current" state will be the target of * the action call. It is the state implementation that decides how to handle the * call and what the next state is after a possible transition. * </li> * <li> * Each state has a reference to an implementation of * {@link org.teleal.cling.support.model.AVTransport}, where the state can hold * information about well, the state. * </li> * </ul> * <p> * Simplified, this means that each AVTransport instance ID is typically handled by * one state machine, and the internal state of that machine is stored in an * <code>AVTransport</code>. * </p> * <p> * Override the {@link #createTransport(org.teleal.cling.model.types.UnsignedIntegerFourBytes, org.teleal.cling.support.lastchange.LastChange)} * method to utilize a subclass of <code>AVTransport</code> as your internal state holder. * </p> * * @author Christian Bauer */public class AVTransportService<T extends AVTransport> extends AbstractAVTransportService { final private static Logger log = Logger.getLogger(AVTransportService.class.getName()); final private Map<Long, AVTransportStateMachine> stateMachines = new ConcurrentHashMap(); final Class<? extends AVTransportStateMachine> stateMachineDefinition; final Class<? extends AbstractState> initialState; final Class<? extends AVTransport> transportClass; public AVTransportService(Class<? extends AVTransportStateMachine> stateMachineDefinition, Class<? extends AbstractState> initialState) { this(stateMachineDefinition, initialState, (Class<T>)AVTransport.class); } public AVTransportService(Class<? extends AVTransportStateMachine> stateMachineDefinition, Class<? extends AbstractState> initialState, Class<T> transportClass) { this.stateMachineDefinition = stateMachineDefinition; this.initialState = initialState; this.transportClass = transportClass; } public void setAVTransportURI(UnsignedIntegerFourBytes instanceId, String currentURI, String currentURIMetaData) throws AVTransportException { URI uri; try { uri = new URI(currentURI); } catch (Exception ex) { throw new AVTransportException( ErrorCode.INVALID_ARGS, "CurrentURI can not be null or malformed" ); } try { AVTransportStateMachine transportStateMachine = findStateMachine(instanceId, true); transportStateMachine.setTransportURI(uri, currentURIMetaData); } catch (TransitionException ex) { throw new AVTransportException(AVTransportErrorCode.TRANSITION_NOT_AVAILABLE, ex.getMessage()); } } public void setNextAVTransportURI(UnsignedIntegerFourBytes instanceId, String nextURI, String nextURIMetaData) throws AVTransportException { URI uri; try { uri = new URI(nextURI); } catch (Exception ex) { throw new AVTransportException( ErrorCode.INVALID_ARGS, "NextURI can not be null or malformed" ); } try { AVTransportStateMachine transportStateMachine = findStateMachine(instanceId, true); transportStateMachine.setNextTransportURI(uri, nextURIMetaData); } catch (TransitionException ex) { throw new AVTransportException(AVTransportErrorCode.TRANSITION_NOT_AVAILABLE, ex.getMessage()); } } public void setPlayMode(UnsignedIntegerFourBytes instanceId, String newPlayMode) throws AVTransportException { AVTransport transport = findStateMachine(instanceId).getCurrentState().getTransport(); try { transport.setTransportSettings( new TransportSettings( PlayMode.valueOf(newPlayMode), transport.getTransportSettings().getRecQualityMode() ) ); } catch (IllegalArgumentException ex) { throw new AVTransportException( AVTransportErrorCode.PLAYMODE_NOT_SUPPORTED, "Unsupported play mode: " + newPlayMode ); } } public void setRecordQualityMode(UnsignedIntegerFourBytes instanceId, String newRecordQualityMode) throws AVTransportException { AVTransport transport = findStateMachine(instanceId).getCurrentState().getTransport(); try { transport.setTransportSettings( new TransportSettings( transport.getTransportSettings().getPlayMode(), RecordQualityMode.valueOrExceptionOf(newRecordQualityMode) ) ); } catch (IllegalArgumentException ex) { throw new AVTransportException( AVTransportErrorCode.RECORDQUALITYMODE_NOT_SUPPORTED, "Unsupported record quality mode: " + newRecordQualityMode ); } } public MediaInfo getMediaInfo(UnsignedIntegerFourBytes instanceId) throws AVTransportException { return findStateMachine(instanceId).getCurrentState().getTransport().getMediaInfo(); } public TransportInfo getTransportInfo(UnsignedIntegerFourBytes instanceId) throws AVTransportException { return findStateMachine(instanceId).getCurrentState().getTransport().getTransportInfo(); } public PositionInfo getPositionInfo(UnsignedIntegerFourBytes instanceId) throws AVTransportException { return findStateMachine(instanceId).getCurrentState().getTransport().getPositionInfo(); } public DeviceCapabilities getDeviceCapabilities(UnsignedIntegerFourBytes instanceId) throws AVTransportException { return findStateMachine(instanceId).getCurrentState().getTransport().getDeviceCapabilities(); } public TransportSettings getTransportSettings(UnsignedIntegerFourBytes instanceId) throws AVTransportException { return findStateMachine(instanceId).getCurrentState().getTransport().getTransportSettings(); } public String getCurrentTransportActions(UnsignedIntegerFourBytes instanceId) throws AVTransportException { AVTransportStateMachine stateMachine = findStateMachine(instanceId); try { TransportAction[] actions = stateMachine.getCurrentState().getCurrentTransportActions(); return ModelUtil.toCommaSeparatedList(actions); } catch (TransitionException ex) { return ""; // TODO: Empty string is not defined in spec but seems reasonable for no available action? } } public void stop(UnsignedIntegerFourBytes instanceId) throws AVTransportException { try { findStateMachine(instanceId).stop(); } catch (TransitionException ex) { throw new AVTransportException(AVTransportErrorCode.TRANSITION_NOT_AVAILABLE, ex.getMessage()); } } public void play(UnsignedIntegerFourBytes instanceId, String speed) throws AVTransportException { try { findStateMachine(instanceId).play(speed); } catch (TransitionException ex) { throw new AVTransportException(AVTransportErrorCode.TRANSITION_NOT_AVAILABLE, ex.getMessage()); } } public void pause(UnsignedIntegerFourBytes instanceId) throws AVTransportException { try { findStateMachine(instanceId).pause(); } catch (TransitionException ex) { throw new AVTransportException(AVTransportErrorCode.TRANSITION_NOT_AVAILABLE, ex.getMessage()); } } public void record(UnsignedIntegerFourBytes instanceId) throws AVTransportException { try { findStateMachine(instanceId).record(); } catch (TransitionException ex) { throw new AVTransportException(AVTransportErrorCode.TRANSITION_NOT_AVAILABLE, ex.getMessage()); } } public void seek(UnsignedIntegerFourBytes instanceId, String unit, String target) throws AVTransportException { SeekMode seekMode; try { seekMode = SeekMode.valueOrExceptionOf(unit); } catch (IllegalArgumentException ex) { throw new AVTransportException( AVTransportErrorCode.SEEKMODE_NOT_SUPPORTED, "Unsupported seek mode: " + unit ); } try { findStateMachine(instanceId).seek(seekMode, target); } catch (TransitionException ex) { throw new AVTransportException(AVTransportErrorCode.TRANSITION_NOT_AVAILABLE, ex.getMessage()); } } public void next(UnsignedIntegerFourBytes instanceId) throws AVTransportException { try { findStateMachine(instanceId).next(); } catch (TransitionException ex) { throw new AVTransportException(AVTransportErrorCode.TRANSITION_NOT_AVAILABLE, ex.getMessage()); } } public void previous(UnsignedIntegerFourBytes instanceId) throws AVTransportException { try { findStateMachine(instanceId).previous(); } catch (TransitionException ex) { throw new AVTransportException(AVTransportErrorCode.TRANSITION_NOT_AVAILABLE, ex.getMessage()); } } protected AVTransportStateMachine findStateMachine(UnsignedIntegerFourBytes instanceId) throws AVTransportException { return findStateMachine(instanceId, true); } protected AVTransportStateMachine findStateMachine(UnsignedIntegerFourBytes instanceId, boolean createDefaultTransport) throws AVTransportException { synchronized (stateMachines) { long id = instanceId.getValue(); AVTransportStateMachine stateMachine = stateMachines.get(id); if (stateMachine == null && id == 0 && createDefaultTransport) { log.fine("Creating default transport instance with ID '0'"); stateMachine = createStateMachine(instanceId); stateMachines.put(id, stateMachine); } else if (stateMachine == null) { throw new AVTransportException(AVTransportErrorCode.INVALID_INSTANCE_ID); } log.fine("Found transport control with ID '" + id + "'"); return stateMachine; } } protected AVTransportStateMachine createStateMachine(UnsignedIntegerFourBytes instanceId) { // Create a proxy that delegates all calls to the right state implementation, working on the T state return StateMachineBuilder.build( stateMachineDefinition, initialState, new Class[]{transportClass}, new Object[]{createTransport(instanceId, getLastChange())} ); } protected AVTransport createTransport(UnsignedIntegerFourBytes instanceId, LastChange lastChange) { return new AVTransport(instanceId, lastChange, StorageMedium.NETWORK); }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?