View Javadoc
1   /*
2    * Copyright (C) 2013 4th Line GmbH, Switzerland
3    *
4    * The contents of this file are subject to the terms of either the GNU
5    * Lesser General Public License Version 2 or later ("LGPL") or the
6    * Common Development and Distribution License Version 1 or later
7    * ("CDDL") (collectively, the "License"). You may not use this file
8    * except in compliance with the License. See LICENSE.txt for more
9    * information.
10   *
11   * This program is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14   */
15  
16  package org.fourthline.cling.support.renderingcontrol;
17  
18  import org.fourthline.cling.binding.annotations.UpnpAction;
19  import org.fourthline.cling.binding.annotations.UpnpInputArgument;
20  import org.fourthline.cling.binding.annotations.UpnpOutputArgument;
21  import org.fourthline.cling.binding.annotations.UpnpService;
22  import org.fourthline.cling.binding.annotations.UpnpServiceId;
23  import org.fourthline.cling.binding.annotations.UpnpServiceType;
24  import org.fourthline.cling.binding.annotations.UpnpStateVariable;
25  import org.fourthline.cling.binding.annotations.UpnpStateVariables;
26  import org.fourthline.cling.model.types.ErrorCode;
27  import org.fourthline.cling.model.types.UnsignedIntegerFourBytes;
28  import org.fourthline.cling.model.types.UnsignedIntegerTwoBytes;
29  import org.fourthline.cling.support.lastchange.LastChange;
30  import org.fourthline.cling.support.lastchange.LastChangeDelegator;
31  import org.fourthline.cling.support.model.Channel;
32  import org.fourthline.cling.support.model.PresetName;
33  import org.fourthline.cling.support.model.VolumeDBRange;
34  import org.fourthline.cling.support.renderingcontrol.lastchange.ChannelLoudness;
35  import org.fourthline.cling.support.renderingcontrol.lastchange.ChannelMute;
36  import org.fourthline.cling.support.renderingcontrol.lastchange.ChannelVolume;
37  import org.fourthline.cling.support.renderingcontrol.lastchange.ChannelVolumeDB;
38  import org.fourthline.cling.support.renderingcontrol.lastchange.RenderingControlLastChangeParser;
39  import org.fourthline.cling.support.renderingcontrol.lastchange.RenderingControlVariable;
40  
41  import java.beans.PropertyChangeSupport;
42  
43  /**
44   *
45   */
46  @UpnpService(
47          serviceId = @UpnpServiceId("RenderingControl"),
48          serviceType = @UpnpServiceType(value = "RenderingControl", version = 1),
49          stringConvertibleTypes = LastChange.class
50  )
51  @UpnpStateVariables({
52          @UpnpStateVariable(
53                  name = "PresetNameList",
54                  sendEvents = false,
55                  datatype = "string"),
56          @UpnpStateVariable(
57                  name = "Mute",
58                  sendEvents = false,
59                  datatype = "boolean"),
60          @UpnpStateVariable(
61                  name = "Volume",
62                  sendEvents = false,
63                  datatype = "ui2",
64                  allowedValueMinimum = 0,
65                  allowedValueMaximum = 100),
66          @UpnpStateVariable(
67                  name = "VolumeDB",
68                  sendEvents = false,
69                  datatype = "i2",
70                  allowedValueMinimum = -36864,
71                  allowedValueMaximum = 32767),
72          @UpnpStateVariable(
73                  name = "Loudness",
74                  sendEvents = false,
75                  datatype = "boolean"),
76          @UpnpStateVariable(
77                  name = "A_ARG_TYPE_Channel",
78                  sendEvents = false,
79                  allowedValuesEnum = Channel.class),
80          @UpnpStateVariable(
81                  name = "A_ARG_TYPE_PresetName",
82                  sendEvents = false,
83                  allowedValuesEnum = PresetName.class),
84          @UpnpStateVariable(
85                  name = "A_ARG_TYPE_InstanceID",
86                  sendEvents = false,
87                  datatype = "ui4")
88  
89  })
90  public abstract class AbstractAudioRenderingControl implements LastChangeDelegator {
91  
92      @UpnpStateVariable(eventMaximumRateMilliseconds = 200)
93      final private LastChange lastChange;
94  
95      final protected PropertyChangeSupport propertyChangeSupport;
96  
97      protected AbstractAudioRenderingControl() {
98          this.propertyChangeSupport = new PropertyChangeSupport(this);
99          this.lastChange = new LastChange(new RenderingControlLastChangeParser());
100     }
101 
102     protected AbstractAudioRenderingControl(LastChange lastChange) {
103         this.propertyChangeSupport = new PropertyChangeSupport(this);
104         this.lastChange = lastChange;
105     }
106 
107     protected AbstractAudioRenderingControl(PropertyChangeSupport propertyChangeSupport) {
108         this.propertyChangeSupport = propertyChangeSupport;
109         this.lastChange = new LastChange(new RenderingControlLastChangeParser());
110     }
111 
112     protected AbstractAudioRenderingControl(PropertyChangeSupport propertyChangeSupport, LastChange lastChange) {
113         this.propertyChangeSupport = propertyChangeSupport;
114         this.lastChange = lastChange;
115     }
116 
117     @Override
118     public LastChange getLastChange() {
119         return lastChange;
120     }
121 
122     @Override
123     public void appendCurrentState(LastChange lc, UnsignedIntegerFourBytes instanceId) throws Exception {
124         for (Channel channel : getCurrentChannels()) {
125             String channelString = channel.name();
126             lc.setEventedValue(
127                     instanceId,
128                     new RenderingControlVariable.Mute(new ChannelMute(channel, getMute(instanceId, channelString))),
129                     new RenderingControlVariable.Loudness(new ChannelLoudness(channel, getLoudness(instanceId, channelString))),
130                     new RenderingControlVariable.Volume(new ChannelVolume(channel, getVolume(instanceId, channelString).getValue().intValue())),
131                     new RenderingControlVariable.VolumeDB(new ChannelVolumeDB(channel, getVolumeDB(instanceId, channelString))),
132                     new RenderingControlVariable.PresetNameList(PresetName.FactoryDefaults.name())
133             );
134         }
135     }
136 
137     public PropertyChangeSupport getPropertyChangeSupport() {
138         return propertyChangeSupport;
139     }
140 
141     public static UnsignedIntegerFourBytes getDefaultInstanceID() {
142         return new UnsignedIntegerFourBytes(0);
143     }
144 
145     @UpnpAction(out = @UpnpOutputArgument(name = "CurrentPresetNameList", stateVariable = "PresetNameList"))
146     public String listPresets(@UpnpInputArgument(name = "InstanceID") UnsignedIntegerFourBytes instanceId) throws RenderingControlException {
147         return PresetName.FactoryDefaults.toString();
148     }
149 
150     @UpnpAction
151     public void selectPreset(@UpnpInputArgument(name = "InstanceID") UnsignedIntegerFourBytes instanceId,
152                              @UpnpInputArgument(name = "PresetName") String presetName) throws RenderingControlException {
153     }
154 
155     @UpnpAction(out = @UpnpOutputArgument(name = "CurrentMute", stateVariable = "Mute"))
156     public abstract boolean getMute(@UpnpInputArgument(name = "InstanceID") UnsignedIntegerFourBytes instanceId,
157                                     @UpnpInputArgument(name = "Channel") String channelName) throws RenderingControlException;
158 
159     @UpnpAction
160     public abstract void setMute(@UpnpInputArgument(name = "InstanceID") UnsignedIntegerFourBytes instanceId,
161                                  @UpnpInputArgument(name = "Channel") String channelName,
162                                  @UpnpInputArgument(name = "DesiredMute", stateVariable = "Mute") boolean desiredMute) throws RenderingControlException;
163 
164     @UpnpAction(out = @UpnpOutputArgument(name = "CurrentVolume", stateVariable = "Volume"))
165     public abstract UnsignedIntegerTwoBytes getVolume(@UpnpInputArgument(name = "InstanceID") UnsignedIntegerFourBytes instanceId,
166                                                       @UpnpInputArgument(name = "Channel") String channelName) throws RenderingControlException;
167 
168     @UpnpAction
169     public abstract void setVolume(@UpnpInputArgument(name = "InstanceID") UnsignedIntegerFourBytes instanceId,
170                                    @UpnpInputArgument(name = "Channel") String channelName,
171                                    @UpnpInputArgument(name = "DesiredVolume", stateVariable = "Volume") UnsignedIntegerTwoBytes desiredVolume) throws RenderingControlException;
172 
173     @UpnpAction(out = @UpnpOutputArgument(name = "CurrentVolume", stateVariable = "VolumeDB"))
174     public Integer getVolumeDB(@UpnpInputArgument(name = "InstanceID") UnsignedIntegerFourBytes instanceId,
175                              @UpnpInputArgument(name = "Channel") String channelName) throws RenderingControlException {
176         return 0;
177     }
178 
179     @UpnpAction
180     public void setVolumeDB(@UpnpInputArgument(name = "InstanceID") UnsignedIntegerFourBytes instanceId,
181                             @UpnpInputArgument(name = "Channel") String channelName,
182                             @UpnpInputArgument(name = "DesiredVolume", stateVariable = "VolumeDB") Integer  desiredVolumeDB) throws RenderingControlException {
183         /*
184         VolumeDB volumeDB = new VolumeDB();
185         volumeDB.setChannel(channelName);
186         volumeDB.setVal(new BigInteger(desiredVolumeDB.toString()));
187         */
188     }
189 
190     @UpnpAction(out = {
191             @UpnpOutputArgument(name = "MinValue", stateVariable = "VolumeDB", getterName = "getMinValue"),
192             @UpnpOutputArgument(name = "MaxValue", stateVariable = "VolumeDB", getterName = "getMaxValue")
193     })
194     public VolumeDBRange getVolumeDBRange(@UpnpInputArgument(name = "InstanceID") UnsignedIntegerFourBytes instanceId,
195                                           @UpnpInputArgument(name = "Channel") String channelName) throws RenderingControlException {
196         return new VolumeDBRange(0, 0);
197     }
198 
199     @UpnpAction(out = @UpnpOutputArgument(name = "CurrentLoudness", stateVariable = "Loudness"))
200     public boolean getLoudness(@UpnpInputArgument(name = "InstanceID") UnsignedIntegerFourBytes instanceId,
201                                @UpnpInputArgument(name = "Channel") String channelName) throws RenderingControlException {
202         return false;
203     }
204 
205     @UpnpAction
206     public void setLoudness(@UpnpInputArgument(name = "InstanceID") UnsignedIntegerFourBytes instanceId,
207                             @UpnpInputArgument(name = "Channel") String channelName,
208                             @UpnpInputArgument(name = "DesiredLoudness", stateVariable = "Loudness") boolean desiredLoudness) throws RenderingControlException {
209 /*
210         Loudness loudness = new Loudness();
211         loudness.setChannel(channelName);
212         loudness.setVal(desiredLoudness);
213 */
214     }
215 
216     protected abstract Channel[] getCurrentChannels();
217 
218     protected Channel getChannel(String channelName) throws RenderingControlException {
219         try {
220             return Channel.valueOf(channelName);
221         } catch (IllegalArgumentException ex) {
222             throw new RenderingControlException(ErrorCode.ARGUMENT_VALUE_INVALID, "Unsupported audio channel: " + channelName);
223         }
224     }
225 
226 }