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  package example.mediarenderer;
16  
17  import org.fourthline.cling.controlpoint.SubscriptionCallback;
18  import org.fourthline.cling.mock.MockUpnpService;
19  import org.fourthline.cling.model.gena.CancelReason;
20  import org.fourthline.cling.model.gena.GENASubscription;
21  import org.fourthline.cling.model.message.UpnpResponse;
22  import org.fourthline.cling.model.meta.LocalDevice;
23  import org.fourthline.cling.model.meta.LocalService;
24  import org.fourthline.cling.model.state.StateVariableValue;
25  import org.fourthline.cling.model.types.UnsignedIntegerFourBytes;
26  import org.fourthline.cling.model.types.UnsignedIntegerTwoBytes;
27  import org.fourthline.cling.support.avtransport.lastchange.AVTransportLastChangeParser;
28  import org.fourthline.cling.support.avtransport.lastchange.AVTransportVariable;
29  import org.fourthline.cling.support.contentdirectory.DIDLParser;
30  import org.fourthline.cling.support.lastchange.Event;
31  import org.fourthline.cling.support.lastchange.LastChange;
32  import org.fourthline.cling.support.lastchange.LastChangeParser;
33  import org.fourthline.cling.support.model.Channel;
34  import org.fourthline.cling.support.model.DIDLContent;
35  import org.fourthline.cling.support.model.PlayMode;
36  import org.fourthline.cling.support.model.RecordMediumWriteStatus;
37  import org.fourthline.cling.support.model.RecordQualityMode;
38  import org.fourthline.cling.support.model.StorageMedium;
39  import org.fourthline.cling.support.model.TransportAction;
40  import org.fourthline.cling.support.model.TransportState;
41  import org.fourthline.cling.support.model.TransportStatus;
42  import org.fourthline.cling.support.renderingcontrol.lastchange.ChannelVolume;
43  import org.fourthline.cling.support.renderingcontrol.lastchange.RenderingControlLastChangeParser;
44  import org.fourthline.cling.support.renderingcontrol.lastchange.RenderingControlVariable;
45  import org.testng.annotations.Test;
46  
47  import java.beans.PropertyChangeEvent;
48  import java.beans.PropertyChangeListener;
49  import java.beans.PropertyChangeSupport;
50  import java.util.ArrayList;
51  import java.util.List;
52  import java.util.Map;
53  
54  import static org.testng.Assert.assertEquals;
55  
56  public class LastChangeTest {
57  
58      @Test
59      public void setFireGet() throws Exception {
60  
61          LastChange lc = new LastChange(new RenderingControlLastChangeParser());
62  
63          lc.setEventedValue(0, new RenderingControlVariable.PresetNameList("foo"));
64          lc.setEventedValue(0, new RenderingControlVariable.PresetNameList("foobar")); // Double set!
65  
66          lc.setEventedValue(
67                  0,
68                  new RenderingControlVariable.Volume(
69                          new ChannelVolume(Channel.Master, 123)
70                  )
71          );
72  
73          lc.setEventedValue(1, new RenderingControlVariable.Brightness(new UnsignedIntegerTwoBytes(456)));
74  
75          final String[] lcValue = new String[1];
76          PropertyChangeSupport pcs = new PropertyChangeSupport(this);
77          pcs.addPropertyChangeListener(new PropertyChangeListener() {
78              public void propertyChange(PropertyChangeEvent ev) {
79                  if (ev.getPropertyName().equals("LastChange"))
80                      lcValue[0] = (String) ev.getNewValue();
81              }
82          });
83          lc.fire(pcs);
84  
85          // Check it's clear
86          assertEquals(
87                  lc.getEventedValue(0, RenderingControlVariable.PresetNameList.class),
88                  null
89          );
90          assertEquals(lc.toString(), "");
91  
92          // Set something again, it's not fired, so it has no consequence on further assertions
93          lc.setEventedValue(0, new RenderingControlVariable.PresetNameList("foo"));
94  
95          // Read the XML string instead
96          lc = new LastChange(new RenderingControlLastChangeParser(), lcValue[0]);
97  
98          assertEquals(
99                  lc.getEventedValue(0, RenderingControlVariable.PresetNameList.class).getValue(),
100                 "foobar"
101         );
102 
103         assertEquals(
104                 lc.getEventedValue(0, RenderingControlVariable.Volume.class).getValue().getChannel(),
105                 Channel.Master
106         );
107         assertEquals(
108                 lc.getEventedValue(0, RenderingControlVariable.Volume.class).getValue().getVolume(),
109                 new Integer(123)
110         );
111 
112         assertEquals(
113                 lc.getEventedValue(1, RenderingControlVariable.Brightness.class).getValue(),
114                 new UnsignedIntegerTwoBytes(456)
115         );
116 
117     }
118 
119     @Test
120     public void parseLastChangeXML() throws Exception {
121 
122         LastChangeParser avTransportParser = new AVTransportLastChangeParser();
123 
124         Event event = avTransportParser.parseResource("org/fourthline/cling/test/support/lastchange/samples/avtransport-roku.xml");
125         assertEquals(event.getInstanceIDs().size(), 1);
126         UnsignedIntegerFourBytes instanceId = new UnsignedIntegerFourBytes(0);
127         assertEquals(
128                 event.getEventedValue(instanceId, AVTransportVariable.TransportState.class).getValue(),
129                 TransportState.STOPPED
130         );
131 
132         String trackMetaDataXML = event.getEventedValue(instanceId, AVTransportVariable.CurrentTrackMetaData.class).getValue();
133         DIDLContent trackMetaData = new DIDLParser().parse(trackMetaDataXML);
134         assertEquals(trackMetaData.getContainers().size(), 0);
135         assertEquals(trackMetaData.getItems().size(), 1);
136     }
137 
138     @Test
139     public void getInitialEventAVTransport() throws Exception {
140 
141         MockUpnpService upnpService = new MockUpnpService();
142 
143         final List<Boolean> testAssertions = new ArrayList<>();
144 
145         LocalDevice device = MediaRendererSampleData.createDevice();
146         upnpService.getRegistry().addDevice(device);
147 
148         LocalService service = device.getServices()[0];
149 
150         SubscriptionCallback callback = new SubscriptionCallback(service, 600) {
151 
152             @Override
153             public void established(GENASubscription sub) {
154             }
155 
156             @Override
157             protected void failed(GENASubscription subscription,
158                                   UpnpResponse responseStatus,
159                                   Exception exception,
160                                   String defaultMsg) {
161                 throw new RuntimeException(defaultMsg, exception);
162             }
163 
164             @Override
165             public void ended(GENASubscription sub,
166                               CancelReason reason,
167                               UpnpResponse response) {
168             }
169 
170             public void eventReceived(GENASubscription sub) {
171 
172                 Map<String, StateVariableValue> values = sub.getCurrentValues();
173                 String lastChangeString = values.get("LastChange").toString();
174 
175                 try {
176                     LastChange lastChange = new LastChange(
177                             new AVTransportLastChangeParser(),
178                             lastChangeString
179                     );
180                     assertEquals(lastChange.getInstanceIDs().length, 1);
181                     assertEquals(lastChange.getEventedValue(0, AVTransportVariable.AVTransportURI.class).getValue(), null);
182                     assertEquals(lastChange.getEventedValue(0, AVTransportVariable.AVTransportURIMetaData.class).getValue(), null);
183                     assertEquals(lastChange.getEventedValue(0, AVTransportVariable.CurrentMediaDuration.class).getValue(), "00:00:00");
184                     assertEquals(lastChange.getEventedValue(0, AVTransportVariable.CurrentPlayMode.class).getValue(), PlayMode.NORMAL);
185                     assertEquals(lastChange.getEventedValue(0, AVTransportVariable.CurrentRecordQualityMode.class).getValue(), RecordQualityMode.NOT_IMPLEMENTED);
186                     assertEquals(lastChange.getEventedValue(0, AVTransportVariable.CurrentTrack.class).getValue(), new UnsignedIntegerFourBytes(0));
187                     assertEquals(lastChange.getEventedValue(0, AVTransportVariable.CurrentTrackDuration.class).getValue(), "00:00:00");
188                     assertEquals(lastChange.getEventedValue(0, AVTransportVariable.CurrentTrackMetaData.class).getValue(), "NOT_IMPLEMENTED");
189                     assertEquals(lastChange.getEventedValue(0, AVTransportVariable.CurrentTrackURI.class).getValue(), null);
190                     assertEquals(lastChange.getEventedValue(0, AVTransportVariable.CurrentTransportActions.class).getValue(), new TransportAction[]{TransportAction.Stop});
191                     assertEquals(lastChange.getEventedValue(0, AVTransportVariable.NextAVTransportURI.class).getValue().toString(), "NOT_IMPLEMENTED"); // TODO: That's weird
192                     assertEquals(lastChange.getEventedValue(0, AVTransportVariable.NumberOfTracks.class).getValue(), new UnsignedIntegerFourBytes(0));
193                     assertEquals(lastChange.getEventedValue(0, AVTransportVariable.PossiblePlaybackStorageMedia.class).getValue(), new StorageMedium[]{StorageMedium.NETWORK});
194                     assertEquals(lastChange.getEventedValue(0, AVTransportVariable.PossibleRecordQualityModes.class).getValue(), new RecordQualityMode[]{RecordQualityMode.NOT_IMPLEMENTED});
195                     assertEquals(lastChange.getEventedValue(0, AVTransportVariable.PossibleRecordStorageMedia.class).getValue(), new StorageMedium[]{StorageMedium.NOT_IMPLEMENTED});
196                     assertEquals(lastChange.getEventedValue(0, AVTransportVariable.RecordMediumWriteStatus.class).getValue(), RecordMediumWriteStatus.NOT_IMPLEMENTED);
197                     assertEquals(lastChange.getEventedValue(0, AVTransportVariable.RecordStorageMedium.class).getValue(), StorageMedium.NOT_IMPLEMENTED);
198                     assertEquals(lastChange.getEventedValue(0, AVTransportVariable.TransportPlaySpeed.class).getValue(), "1");
199                     assertEquals(lastChange.getEventedValue(0, AVTransportVariable.TransportState.class).getValue(), TransportState.NO_MEDIA_PRESENT);
200                     assertEquals(lastChange.getEventedValue(0, AVTransportVariable.TransportStatus.class).getValue(), TransportStatus.OK);
201 
202                     testAssertions.add(true);
203 
204                 } catch (Exception ex) {
205                     throw new RuntimeException(ex);
206                 }
207             }
208 
209             public void eventsMissed(GENASubscription sub, int numberOfMissedEvents) {
210             }
211 
212         };
213 
214         upnpService.getControlPoint().execute(callback);
215 
216         assertEquals(testAssertions.size(), 1);
217         for (Boolean testAssertion : testAssertions) {
218             assert testAssertion;
219         }
220     }
221 
222     @Test
223     public void getInitialEventRenderingControl() throws Exception {
224 
225         MockUpnpService upnpService = new MockUpnpService();
226 
227         final List<Boolean> testAssertions = new ArrayList<>();
228 
229         LocalDevice device = MediaRendererSampleData.createDevice();
230         upnpService.getRegistry().addDevice(device);
231 
232         LocalService service = device.getServices()[1];
233 
234         SubscriptionCallback callback = new SubscriptionCallback(service, 600) {
235 
236             @Override
237             public void established(GENASubscription sub) {
238             }
239 
240             @Override
241             protected void failed(GENASubscription subscription,
242                                   UpnpResponse responseStatus,
243                                   Exception exception,
244                                   String defaultMsg) {
245                 throw new RuntimeException(defaultMsg, exception);
246             }
247 
248             @Override
249             public void ended(GENASubscription sub,
250                               CancelReason reason,
251                               UpnpResponse response) {
252             }
253 
254             public void eventReceived(GENASubscription sub) {
255 
256                 Map<String, StateVariableValue> values = sub.getCurrentValues();
257                 String lastChangeString = values.get("LastChange").toString();
258 
259                 try {
260                     LastChange lastChange = new LastChange(
261                             new RenderingControlLastChangeParser(),
262                             lastChangeString
263                     );
264                     assertEquals(lastChange.getInstanceIDs().length, 1);
265                     assertEquals(lastChange.getEventedValue(0, RenderingControlVariable.Mute.class).getValue().getChannel(), Channel.Master);
266                     assertEquals(lastChange.getEventedValue(0, RenderingControlVariable.Mute.class).getValue().getMute(), Boolean.FALSE);
267                     assertEquals(lastChange.getEventedValue(0, RenderingControlVariable.Loudness.class).getValue().getChannel(), Channel.Master);
268                     assertEquals(lastChange.getEventedValue(0, RenderingControlVariable.Loudness.class).getValue().getLoudness(), Boolean.FALSE);
269                     assertEquals(lastChange.getEventedValue(0, RenderingControlVariable.Volume.class).getValue().getChannel(), Channel.Master);
270                     assertEquals(lastChange.getEventedValue(0, RenderingControlVariable.Volume.class).getValue().getVolume(), new Integer(50));
271                     assertEquals(lastChange.getEventedValue(0, RenderingControlVariable.VolumeDB.class).getValue().getChannel(), Channel.Master);
272                     assertEquals(lastChange.getEventedValue(0, RenderingControlVariable.VolumeDB.class).getValue().getVolumeDB(), new Integer(0));
273 
274                     testAssertions.add(true);
275 
276                 } catch (Exception ex) {
277                     throw new RuntimeException(ex);
278                 }
279             }
280 
281             public void eventsMissed(GENASubscription sub, int numberOfMissedEvents) {
282             }
283 
284         };
285 
286         upnpService.getControlPoint().execute(callback);
287 
288         assertEquals(testAssertions.size(), 1);
289         for (Boolean testAssertion : testAssertions) {
290             assert testAssertion;
291         }
292     }
293 }