1 package org.rpi.main;
2
3 import java.awt.image.BufferedImage;
4 import java.io.BufferedReader;
5 import java.io.ByteArrayOutputStream;
6 import java.io.File;
7 import java.io.FileWriter;
8 import java.io.IOException;
9 import java.io.InputStreamReader;
10 import java.net.InetAddress;
11 import java.net.URL;
12 import java.util.List;
13 import java.util.concurrent.ConcurrentHashMap;
14 import java.util.regex.Matcher;
15 import java.util.regex.Pattern;
16
17 import javax.imageio.ImageIO;
18
19 import org.apache.log4j.Logger;
20 import org.openhome.net.core.DebugLevel;
21 import org.openhome.net.core.DeviceStack;
22 import org.openhome.net.core.IMessageListener;
23 import org.openhome.net.core.InitParams;
24 import org.openhome.net.core.Library;
25 import org.openhome.net.device.DvDevice;
26 import org.openhome.net.device.DvDeviceFactory;
27 import org.openhome.net.device.IDvDeviceListener;
28 import org.openhome.net.device.IResourceManager;
29 import org.openhome.net.device.IResourceWriter;
30 import org.rpi.config.Config;
31 import org.rpi.os.OSManager;
32 import org.rpi.player.PlayManager;
33 import org.rpi.plugingateway.PluginGateWay;
34 import org.rpi.providers.PrvAVTransport;
35 import org.rpi.providers.PrvConnectionManager;
36 import org.rpi.providers.PrvInfo;
37 import org.rpi.providers.PrvPlayList;
38 import org.rpi.providers.PrvProduct;
39 import org.rpi.providers.PrvRadio;
40 import org.rpi.providers.PrvReceiver;
41 import org.rpi.providers.PrvRenderingControl;
42 import org.rpi.providers.PrvTime;
43 import org.rpi.providers.PrvVolume;
44 import org.rpi.radio.ChannelReader;
45 import org.rpi.sources.Source;
46 import org.rpi.sources.SourceReader;
47 import org.rpi.utils.NetworkUtils;
48
49 public class SimpleDevice implements IResourceManager, IDvDeviceListener, IMessageListener {
50
51 private Logger log = Logger.getLogger(SimpleDevice.class);
52 private DvDevice iDevice = null;
53 private Library lib = null;
54
55 private PrvConnectionManager iConnectionManager = null;
56 private PrvVolume iVolume = null;
57 private PrvPlayList iPlayList = null;
58 private PrvProduct iProduct = null;
59 private PrvInfo iInfo = null;
60 private PrvTime iTime = null;
61 private PrvRadio iRadio = null;
62 private PrvReceiver iReceiver = null;
63 private PrvAVTransport iAVTransport = null;
64 private PrvRenderingControl iRenderingControl = null;
65
66 private PlayManager iPlayer = PlayManager.getInstance();
67
68
69
70
71
72
73
74 public SimpleDevice() {
75 PluginGateWay.getInstance().setSimpleDevice(this);
76 log.debug("Creating Simple Device version: " + Config.version);
77
78
79 OSManager.getInstance();
80
81 InitParams initParams = new InitParams();
82 initParams.setLogOutput(new OpenHomeLogger());
83 if (Config.port > 0) {
84 initParams.setDvServerPort(Config.port);
85 }
86
87 initParams.setFatalErrorHandler(this);
88
89 lib = Library.create(initParams);
90 lib.setDebugLevel(getDebugLevel(Config.debug));
91 StringBuffer sb = new StringBuffer();
92
93 DeviceStack ds = lib.startDv();
94 String friendly_name = Config.friendly_name.replace(":", " ");
95 String iDeviceName = "device-" + friendly_name + "-" + NetworkUtils.getHostName() + "-MediaRenderer";
96 iDevice = new DvDeviceFactory(ds).createDeviceStandard(iDeviceName, this);
97 log.debug("Created StandardDevice: " + iDevice.getUdn());
98 sb.append("<icon>");
99 sb.append("<minetype>image/png</minetype>");
100 sb.append("<width>240</width>");
101 sb.append("<height>240</height>");
102 sb.append("<depth>24</depth>");
103 sb.append("<url>/" + iDeviceName + "/Upnp/resource/org/rpi/image/mediaplayer240.png</url>");
104 sb.append("</icon>");
105 sb.append("<icon>");
106 sb.append("<minetype>image/jpeg</minetype>");
107 sb.append("<width>240</width>");
108 sb.append("<height>240</height>");
109 sb.append("<depth>24</depth>");
110 sb.append("<url>/" + iDeviceName + "/Upnp/resource/org/rpi/image/mediaplayer240.jpg</url>");
111 sb.append("</icon>");
112 sb.append("<icon>");
113 sb.append("<minetype>image/png</minetype>");
114 sb.append("<width>120</width>");
115 sb.append("<height>120</height>");
116 sb.append("<depth>24</depth>");
117 sb.append("<url>/" + iDeviceName + "/Upnp/resource/org/rpi/image/mediaplayer120.png</url>");
118 sb.append("</icon>");
119 sb.append("<icon>");
120 sb.append("<minetype>image/jpeg</minetype>");
121 sb.append("<width>120</width>");
122 sb.append("<height>120</height>");
123 sb.append("<depth>24</depth>");
124 sb.append("<url>/" + iDeviceName + "/Upnp/resource/org/rpi/image/mediaplayer120.jpg</url>");
125 sb.append("</icon>");
126 sb.append("<icon>");
127 sb.append("<minetype>image/png</minetype>");
128 sb.append("<width>50</width>");
129 sb.append("<height>50</height>");
130 sb.append("<depth>24</depth>");
131 sb.append("<url>/" + iDeviceName + "/Upnp/resource/org/rpi/image/mediaplayer50.png</url>");
132 sb.append("</icon>");
133 sb.append("<icon>");
134 sb.append("<minetype>image/jpeg</minetype>");
135 sb.append("<width>50</width>");
136 sb.append("<height>50</height>");
137 sb.append("<depth>24</depth>");
138 sb.append("<url>/" + iDeviceName + "/Upnp/resource/org/rpi/image/mediaplayer50.jpg</url>");
139 sb.append("</icon>");
140 iDevice.setAttribute("Upnp.IconList", sb.toString());
141
142
143 iDevice.setAttribute("Upnp.Domain", "schemas-upnp-org");
144 iDevice.setAttribute("Upnp.Type", "MediaRenderer");
145 iDevice.setAttribute("Upnp.Version", "1");
146 iDevice.setAttribute("Upnp.FriendlyName", Config.friendly_name);
147 iDevice.setAttribute("Upnp.Manufacturer", "Made in Manchester");
148 iDevice.setAttribute("Upnp.ModelName", "Open Home Java Renderer: v" + Config.version);
149 iDevice.setAttribute("Upnp.ModelDescription", "'We Made History Not Money' - Tony Wilson..");
150
151
152
153
154 iConnectionManager = new PrvConnectionManager(iDevice);
155 iProduct = new PrvProduct(iDevice);
156 iVolume = new PrvVolume(iDevice);
157 iPlayList = new PrvPlayList(iDevice);
158 iInfo = new PrvInfo(iDevice);
159 iTime = new PrvTime(iDevice);
160 iRadio = new PrvRadio(iDevice);
161
162 if (Config.enableReceiver) {
163 iReceiver = new PrvReceiver(iDevice);
164 }
165 if (Config.enableAVTransport) {
166 iAVTransport = new PrvAVTransport(iDevice);
167 iRenderingControl = new PrvRenderingControl(iDevice);
168 }
169
170 try {
171 ChannelReader cr = new ChannelReader();
172 iRadio.addChannels(cr.getChannels());
173 } catch (Exception e) {
174 log.error("Error Reading Radio Channels");
175 }
176
177 try{
178 SourceReader sr = new SourceReader();
179 ConcurrentHashMap<String, Source> sources = sr.getSources();
180 if(sources.size()==0)
181 {
182 Source playlist = new Source("PlayList","Playlist","-99");
183 sources.put(playlist.getName(),playlist);
184 Source radio = new Source("Radio","Radio","-99");
185 sources.put(radio.getName(),radio);
186 if(Config.enableReceiver)
187 {
188 Source reciever = new Source("Receiver", "Receiver", "-99");
189 sources.put(reciever.getName(), reciever);
190 }
191 }
192 PluginGateWay.getInstance().setSources(sources);
193 PluginGateWay.getInstance().setDefaultSourcePin(sr.getDefaultPin());
194 for(String key : sources.keySet())
195 {
196 Source s = sources.get(key);
197 log.debug("Adding Source: " +s.toString());
198 iProduct.addSource(Config.friendly_name, s.getName(), s.getType(), true);
199 }
200 iProduct.updateCurrentSource();
201
202 }
203 catch(Exception e)
204 {
205 log.error("Error Reading Input Sources");
206 }
207
208 iDevice.setEnabled();
209 log.debug("Device Enabled UDN: " + iDevice.getUdn());
210 iProduct.setSourceByname("PlayList");
211 OSManager.getInstance().loadPlugins();
212 }
213
214
215
216
217
218 private int getDebugLevel(String sLevel) {
219 if (sLevel.equalsIgnoreCase("NONE")) {
220 return DebugLevel.None.intValue();
221 } else if (sLevel.equalsIgnoreCase("TRACE")) {
222 return DebugLevel.Trace.intValue();
223 } else if (sLevel.equalsIgnoreCase("NETWORK")) {
224 return DebugLevel.Network.intValue();
225 } else if (sLevel.equalsIgnoreCase("TIMER")) {
226 return DebugLevel.Timer.intValue();
227 } else if (sLevel.equalsIgnoreCase("SsdpMulticast")) {
228 return DebugLevel.SsdpMulticast.intValue();
229 } else if (sLevel.equalsIgnoreCase("SsdpUnicast")) {
230 return DebugLevel.SsdpUnicast.intValue();
231 } else if (sLevel.equalsIgnoreCase("Http")) {
232 return DebugLevel.Http.intValue();
233 } else if (sLevel.equalsIgnoreCase("Device")) {
234 return DebugLevel.Device.intValue();
235 } else if (sLevel.equalsIgnoreCase("XmlFetch")) {
236 return DebugLevel.XmlFetch.intValue();
237 } else if (sLevel.equalsIgnoreCase("Service")) {
238 return DebugLevel.Service.intValue();
239 } else if (sLevel.equalsIgnoreCase("Event")) {
240 return DebugLevel.Event.intValue();
241 } else if (sLevel.equalsIgnoreCase("Topology")) {
242 return DebugLevel.Topology.intValue();
243 } else if (sLevel.equalsIgnoreCase("DvInvocation")) {
244 return DebugLevel.DvInvocation.intValue();
245 } else if (sLevel.equalsIgnoreCase("DvInvocation")) {
246 return DebugLevel.DvInvocation.intValue();
247 } else if (sLevel.equalsIgnoreCase("DvEvent")) {
248 return DebugLevel.DvEvent.intValue();
249 } else if (sLevel.equalsIgnoreCase("DvWebSocket")) {
250 return DebugLevel.DvWebSocket.intValue();
251 } else if (sLevel.equalsIgnoreCase("Bonjour")) {
252 return DebugLevel.Bonjour.intValue();
253 } else if (sLevel.equalsIgnoreCase("DvDevice")) {
254 return DebugLevel.DvDevice.intValue();
255 } else if (sLevel.equalsIgnoreCase("Error")) {
256 return DebugLevel.Error.intValue();
257 } else if (sLevel.equalsIgnoreCase("All")) {
258 return DebugLevel.All.intValue();
259 } else if (sLevel.equalsIgnoreCase("Verbose")) {
260 return DebugLevel.Verbose.intValue();
261 }
262 return DebugLevel.None.intValue();
263 }
264
265 public void attachShutDownHook() {
266 Runtime.getRuntime().addShutdownHook(new Thread() {
267 @Override
268 public void run() {
269 log.debug("Shutdown Hook, Start of Shutdown");
270 dispose();
271 }
272 });
273 log.debug("Shut Down Hook Attached.");
274 }
275
276 public void dispose() {
277
278 try {
279 OSManager.getInstance().dispose();
280 } catch (Exception e) {
281
282 }
283
284 if (iPlayer != null) {
285 log.info("Destroying IPlayer");
286 try {
287 iPlayer.destroy();
288 log.info("Destroyed IPlayer");
289 } catch (Exception e) {
290 log.error("Error Destroying IPlayer", e);
291 }
292 }
293
294 if (iDevice != null) {
295 log.info("Destroying device");
296
297 try {
298 iDevice.destroy();
299 log.info("Destroyed device");
300 } catch (Exception e) {
301 log.error("Error Destroying Device", e);
302 }
303 }
304
305 if (iConnectionManager != null) {
306 log.info("Destroying ConnectionManager");
307 try {
308 iConnectionManager.dispose();
309 log.info("Destroyed ConnectionManager");
310 } catch (Exception e) {
311 log.error("Error Destroying ConnectionManager", e);
312 }
313 }
314
315 if (iPlayList != null) {
316 log.info("Destroying PlayList");
317 try {
318 iPlayList.dispose();
319 log.info("Destroyed PlayList");
320 } catch (Exception e) {
321 log.error("Error Destroying PlayList", e);
322 }
323 }
324
325 if (iVolume != null) {
326 log.info("Destroying Volume");
327 try {
328 iVolume.dispose();
329 log.info("Destroyed Volume");
330 } catch (Exception e) {
331 log.error("Error Destroying Volume", e);
332 }
333 }
334
335 if (iProduct != null) {
336 log.info("Destroying Product");
337 try {
338 iProduct.dispose();
339 log.info("Destroyed Product");
340 } catch (Exception e) {
341 log.error("Error Destroying Product", e);
342 }
343 }
344
345 if (iInfo != null) {
346 log.info("Destroying Info");
347 try {
348 iInfo.dispose();
349 log.info("Destroyed Info");
350 } catch (Exception e) {
351 log.error("Error Destroying Info", e);
352 }
353 }
354
355 if (iTime != null) {
356 log.info("Destroying Time");
357 try {
358 iTime.dispose();
359 log.info("Destroyed Time");
360 } catch (Exception e) {
361 log.error("Error Destroying Time", e);
362 }
363
364 }
365
366 if (iRadio != null) {
367 log.info("Destroying Radio");
368 try {
369 iRadio.dispose();
370 log.info("Destroyed Radio");
371 } catch (Exception e) {
372 log.error("Error Destroying Radio", e);
373 }
374
375 }
376
377 if (iReceiver != null) {
378 log.info("Destroying Receiver");
379 try {
380 iReceiver.dispose();
381 log.info("Destroyed Receiver");
382 } catch (Exception e) {
383 log.error("Error Destroying Receiver", e);
384 }
385
386 }
387
388 if (iAVTransport != null) {
389 log.info("Destroying AVTransport");
390 try {
391 iAVTransport.dispose();
392 log.info("Destroyed AVTransport");
393 } catch (Exception e) {
394 log.error("Error Destroying AVTransport", e);
395 }
396
397 }
398
399 if (iRenderingControl != null) {
400 log.info("Destroying RenderingControl");
401 try {
402 iRenderingControl.dispose();
403 log.info("Destroyed RenderingControl");
404 } catch (Exception e) {
405 log.error("Error Destroying RenderingControl", e);
406 }
407
408 }
409
410 if (lib != null) {
411 try {
412 log.info("Attempting to Close DeviceStack");
413 lib.close();
414 log.info("Closed DeviceStack");
415 } catch (Exception e) {
416 log.error("Error Closing DeviceStack", e);
417 }
418 }
419
420 }
421
422 @Override
423 public void writeResource(String resource_name, int arg1, List<String> arg2, IResourceWriter writer) {
424 log.info("writeResource Called: " + resource_name);
425 try {
426 resource_name = "/" + resource_name;
427 URL url = this.getClass().getResource(resource_name);
428 BufferedImage image = ImageIO.read(url);
429 ByteArrayOutputStream baos = new ByteArrayOutputStream();
430 String fileType = "image/png";
431 String format = "png";
432 if (resource_name.toUpperCase().endsWith("JPG")) {
433 format = "jpg";
434 fileType = "image/jpeg";
435 }
436 ImageIO.write(image, format, baos);
437 int length = baos.toByteArray().length;
438 writer.writeResourceBegin(length, fileType);
439 writer.writeResource(baos.toByteArray(), length);
440 writer.writeResourceEnd();
441 } catch (IOException e) {
442 log.error("Error Writing Resource: " + resource_name, e);
443 }
444
445 }
446
447 private void writeFile(String s) {
448 try {
449 File newTextFile = new File("C:/temp/thetextfile.txt");
450
451 FileWriter fw = new FileWriter(newTextFile);
452 fw.write(s);
453 fw.close();
454
455 } catch (IOException iox) {
456
457 iox.printStackTrace();
458 }
459 }
460
461 public PrvVolume getCustomVolume() {
462 return iVolume;
463 }
464
465 @Override
466 public void deviceDisabled() {
467 log.info("Device has been Disabled");
468 dispose();
469 }
470
471 @Override
472 public void message(String paramString) {
473 log.fatal("Fatal Error: " + paramString);
474 }
475
476
477
478
479
480 public PrvProduct getProduct()
481 {
482 return iProduct;
483 }
484 }