/* * 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; 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.types.UnsignedIntegerFourBytes; import org.teleal.cling.support.model.TransportState; 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.RecordMediumWriteStatus; import org.teleal.cling.support.model.RecordQualityMode; import org.teleal.cling.support.model.SeekMode; import org.teleal.cling.support.model.TransportInfo; import org.teleal.cling.support.model.TransportSettings; import org.teleal.cling.support.model.TransportStatus; import org.teleal.cling.support.avtransport.lastchange.AVTransportLastChangeParser; import org.teleal.cling.support.model.StorageMedium; import org.teleal.cling.support.lastchange.LastChange; import java.beans.PropertyChangeSupport; /** * Skeleton of service with "LastChange" eventing support. * * @author Christian Bauer */ @UpnpService( serviceId = @UpnpServiceId("AVTransport"), serviceType = @UpnpServiceType(value = "AVTransport", version = 1), stringConvertibleTypes = LastChange.class ) @UpnpStateVariables({ @UpnpStateVariable( name = "TransportState", sendEvents = false, allowedValuesEnum = TransportState.class), @UpnpStateVariable( name = "TransportStatus", sendEvents = false, allowedValuesEnum = TransportStatus.class), @UpnpStateVariable( name = "PlaybackStorageMedium", sendEvents = false, defaultValue = "NONE", allowedValuesEnum = StorageMedium.class), @UpnpStateVariable( name = "RecordStorageMedium", sendEvents = false, defaultValue = "NOT_IMPLEMENTED", allowedValuesEnum = StorageMedium.class), @UpnpStateVariable( name = "PossiblePlaybackStorageMedia", sendEvents = false, datatype = "string", defaultValue = "NETWORK"), @UpnpStateVariable( name = "PossibleRecordStorageMedia", sendEvents = false, datatype = "string", defaultValue = "NOT_IMPLEMENTED"), @UpnpStateVariable( // TODO name = "CurrentPlayMode", sendEvents = false, defaultValue = "NORMAL", allowedValuesEnum = PlayMode.class), @UpnpStateVariable( // TODO name = "TransportPlaySpeed", sendEvents = false, datatype = "string", defaultValue = "1"), // 1, 1/2, 2, -1, 1/10, etc. @UpnpStateVariable( name = "RecordMediumWriteStatus", sendEvents = false, defaultValue = "NOT_IMPLEMENTED", allowedValuesEnum = RecordMediumWriteStatus.class), @UpnpStateVariable( name = "CurrentRecordQualityMode", sendEvents = false, defaultValue = "NOT_IMPLEMENTED", allowedValuesEnum = RecordQualityMode.class), @UpnpStateVariable( name = "PossibleRecordQualityModes", sendEvents = false, datatype = "string", defaultValue = "NOT_IMPLEMENTED"), @UpnpStateVariable( name = "NumberOfTracks", sendEvents = false, datatype = "ui4", defaultValue = "0"), @UpnpStateVariable( name = "CurrentTrack", sendEvents = false, datatype = "ui4", defaultValue = "0"), @UpnpStateVariable( name = "CurrentTrackDuration", sendEvents = false, datatype = "string"), // H+:MM:SS[.F+] or H+:MM:SS[.F0/F1] @UpnpStateVariable( name = "CurrentMediaDuration", sendEvents = false, datatype = "string", defaultValue = "00:00:00"), @UpnpStateVariable( name = "CurrentTrackMetaData", sendEvents = false, datatype = "string", defaultValue = "NOT_IMPLEMENTED"), @UpnpStateVariable( name = "CurrentTrackURI", sendEvents = false, datatype = "string"), @UpnpStateVariable( name = "AVTransportURI", sendEvents = false, datatype = "string"), @UpnpStateVariable( name = "AVTransportURIMetaData", sendEvents = false, datatype = "string", defaultValue = "NOT_IMPLEMENTED"), @UpnpStateVariable( name = "NextAVTransportURI", sendEvents = false, datatype = "string", defaultValue = "NOT_IMPLEMENTED"), @UpnpStateVariable( name = "NextAVTransportURIMetaData", sendEvents = false, datatype = "string", defaultValue = "NOT_IMPLEMENTED"), @UpnpStateVariable( name = "RelativeTimePosition", sendEvents = false, datatype = "string"), // H+:MM:SS[.F+] or H+:MM:SS[.F0/F1] (in track) @UpnpStateVariable( name = "AbsoluteTimePosition", sendEvents = false, datatype = "string"), // H+:MM:SS[.F+] or H+:MM:SS[.F0/F1] (in media) @UpnpStateVariable( name = "RelativeCounterPosition", sendEvents = false, datatype = "i4", defaultValue = "2147483647"), // Max value means not implemented @UpnpStateVariable( name = "AbsoluteCounterPosition", sendEvents = false, datatype = "i4", defaultValue = "2147483647"), // Max value means not implemented @UpnpStateVariable( name = "CurrentTransportActions", sendEvents = false, datatype = "string"), // Play, Stop, Pause, Seek, Next, Previous and Record @UpnpStateVariable( name = "A_ARG_TYPE_SeekMode", sendEvents = false, allowedValuesEnum = SeekMode.class), // The 'type' of seek we can perform (or should perform) @UpnpStateVariable( name = "A_ARG_TYPE_SeekTarget", sendEvents = false, datatype = "string"), // The actual seek (offset or whatever) value @UpnpStateVariable( name = "A_ARG_TYPE_InstanceID", sendEvents = false, datatype = "ui4") }) public abstract class AbstractAVTransportService { @UpnpStateVariable(eventMaximumRateMilliseconds = 200) final private LastChange lastChange; final protected PropertyChangeSupport propertyChangeSupport; protected AbstractAVTransportService() { this.propertyChangeSupport = new PropertyChangeSupport(this); this.lastChange = new LastChange(new AVTransportLastChangeParser()); } protected AbstractAVTransportService(LastChange lastChange) { this.propertyChangeSupport = new PropertyChangeSupport(this); this.lastChange = lastChange; } protected AbstractAVTransportService(PropertyChangeSupport propertyChangeSupport) { this.propertyChangeSupport = propertyChangeSupport; this.lastChange = new LastChange(new AVTransportLastChangeParser()); } protected AbstractAVTransportService(PropertyChangeSupport propertyChangeSupport, LastChange lastChange) { this.propertyChangeSupport = propertyChangeSupport; this.lastChange = lastChange; } public LastChange getLastChange() { return lastChange; } public void fireLastChange() { getLastChange().fire(getPropertyChangeSupport()); } public PropertyChangeSupport getPropertyChangeSupport() { return propertyChangeSupport; } public static UnsignedIntegerFourBytes getDefaultInstanceID() { return new UnsignedIntegerFourBytes(0); } @UpnpAction public abstract void setAVTransportURI(@UpnpInputArgument(name = "InstanceID") UnsignedIntegerFourBytes instanceId, @UpnpInputArgument(name = "CurrentURI", stateVariable = "AVTransportURI") String currentURI, @UpnpInputArgument(name = "CurrentURIMetaData", stateVariable = "AVTransportURIMetaData") String currentURIMetaData) throws AVTransportException; @UpnpAction public abstract void setNextAVTransportURI(@UpnpInputArgument(name = "InstanceID") UnsignedIntegerFourBytes instanceId, @UpnpInputArgument(name = "NextURI", stateVariable = "AVTransportURI") String nextURI, @UpnpInputArgument(name = "NextURIMetaData", stateVariable = "AVTransportURIMetaData") String nextURIMetaData) throws AVTransportException; @UpnpAction(out = { @UpnpOutputArgument(name = "NrTracks", stateVariable = "NumberOfTracks", getterName = "getNumberOfTracks"), @UpnpOutputArgument(name = "MediaDuration", stateVariable = "CurrentMediaDuration", getterName = "getMediaDuration"), @UpnpOutputArgument(name = "CurrentURI", stateVariable = "AVTransportURI", getterName = "getCurrentURI"), @UpnpOutputArgument(name = "CurrentURIMetaData", stateVariable = "AVTransportURIMetaData", getterName = "getCurrentURIMetaData"), @UpnpOutputArgument(name = "NextURI", stateVariable = "NextAVTransportURI", getterName = "getNextURI"), @UpnpOutputArgument(name = "NextURIMetaData", stateVariable = "NextAVTransportURIMetaData", getterName = "getNextURIMetaData"), @UpnpOutputArgument(name = "PlayMedium", stateVariable = "PlaybackStorageMedium", getterName = "getPlayMedium"), @UpnpOutputArgument(name = "RecordMedium", stateVariable = "RecordStorageMedium", getterName = "getRecordMedium"), @UpnpOutputArgument(name = "WriteStatus", stateVariable = "RecordMediumWriteStatus", getterName = "getWriteStatus") }) public abstract MediaInfo getMediaInfo(@UpnpInputArgument(name = "InstanceID") UnsignedIntegerFourBytes instanceId) throws AVTransportException; @UpnpAction(out = { @UpnpOutputArgument(name = "CurrentTransportState", stateVariable = "TransportState", getterName = "getCurrentTransportState"), @UpnpOutputArgument(name = "CurrentTransportStatus", stateVariable = "TransportStatus", getterName = "getCurrentTransportStatus"), @UpnpOutputArgument(name = "CurrentSpeed", stateVariable = "TransportPlaySpeed", getterName = "getCurrentSpeed") }) public abstract TransportInfo getTransportInfo(@UpnpInputArgument(name = "InstanceID") UnsignedIntegerFourBytes instanceId) throws AVTransportException; @UpnpAction(out = { @UpnpOutputArgument(name = "Track", stateVariable = "CurrentTrack", getterName = "getTrack"), @UpnpOutputArgument(name = "TrackDuration", stateVariable = "CurrentTrackDuration", getterName = "getTrackDuration"), @UpnpOutputArgument(name = "TrackMetaData", stateVariable = "CurrentTrackMetaData", getterName = "getTrackMetaData"), @UpnpOutputArgument(name = "TrackURI", stateVariable = "CurrentTrackURI", getterName = "getTrackURI"), @UpnpOutputArgument(name = "RelTime", stateVariable = "RelativeTimePosition", getterName = "getRelTime"), @UpnpOutputArgument(name = "AbsTime", stateVariable = "AbsoluteTimePosition", getterName = "getAbsTime"), @UpnpOutputArgument(name = "RelCount", stateVariable = "RelativeCounterPosition", getterName = "getRelCount"), @UpnpOutputArgument(name = "AbsCount", stateVariable = "AbsoluteCounterPosition", getterName = "getAbsCount") }) public abstract PositionInfo getPositionInfo(@UpnpInputArgument(name = "InstanceID") UnsignedIntegerFourBytes instanceId) throws AVTransportException; @UpnpAction(out = { @UpnpOutputArgument(name = "PlayMedia", stateVariable = "PossiblePlaybackStorageMedia", getterName = "getPlayMediaString"), @UpnpOutputArgument(name = "RecMedia", stateVariable = "PossibleRecordStorageMedia", getterName = "getRecMediaString"), @UpnpOutputArgument(name = "RecQualityModes", stateVariable = "PossibleRecordQualityModes", getterName = "getRecQualityModesString") }) public abstract DeviceCapabilities getDeviceCapabilities(@UpnpInputArgument(name = "InstanceID") UnsignedIntegerFourBytes instanceId) throws AVTransportException; @UpnpAction(out = { @UpnpOutputArgument(name = "PlayMode", stateVariable = "CurrentPlayMode", getterName = "getPlayMode"), @UpnpOutputArgument(name = "RecQualityMode", stateVariable = "CurrentRecordQualityMode", getterName = "getRecQualityMode") }) public abstract TransportSettings getTransportSettings(@UpnpInputArgument(name = "InstanceID") UnsignedIntegerFourBytes instanceId) throws AVTransportException; @UpnpAction public abstract void stop(@UpnpInputArgument(name = "InstanceID") UnsignedIntegerFourBytes instanceId) throws AVTransportException; @UpnpAction public abstract void play(@UpnpInputArgument(name = "InstanceID") UnsignedIntegerFourBytes instanceId, @UpnpInputArgument(name = "Speed", stateVariable = "TransportPlaySpeed") String speed) throws AVTransportException; @UpnpAction public abstract void pause(@UpnpInputArgument(name = "InstanceID") UnsignedIntegerFourBytes instanceId) throws AVTransportException; @UpnpAction public abstract void record(@UpnpInputArgument(name = "InstanceID") UnsignedIntegerFourBytes instanceId) throws AVTransportException; @UpnpAction public abstract void seek(@UpnpInputArgument(name = "InstanceID") UnsignedIntegerFourBytes instanceId, @UpnpInputArgument(name = "Unit", stateVariable = "A_ARG_TYPE_SeekMode") String unit, @UpnpInputArgument(name = "Target", stateVariable = "A_ARG_TYPE_SeekTarget") String target) throws AVTransportException; @UpnpAction public abstract void next(@UpnpInputArgument(name = "InstanceID") UnsignedIntegerFourBytes instanceId) throws AVTransportException; @UpnpAction public abstract void previous(@UpnpInputArgument(name = "InstanceID") UnsignedIntegerFourBytes instanceId) throws AVTransportException; @UpnpAction public abstract void setPlayMode(@UpnpInputArgument(name = "InstanceID") UnsignedIntegerFourBytes instanceId, @UpnpInputArgument(name = "NewPlayMode", stateVariable = "CurrentPlayMode") String newPlayMode) throws AVTransportException; @UpnpAction public abstract void setRecordQualityMode(@UpnpInputArgument(name = "InstanceID") UnsignedIntegerFourBytes instanceId, @UpnpInputArgument(name = "NewRecordQualityMode", stateVariable = "CurrentRecordQualityMode") String newRecordQualityMode) throws AVTransportException; @UpnpAction(out = @UpnpOutputArgument(name = "Actions")) public abstract String getCurrentTransportActions(@UpnpInputArgument(name = "InstanceID") UnsignedIntegerFourBytes instanceId) throws AVTransportException; }