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 + -
显示快捷键?