|
|
|
@ -41,6 +41,7 @@ import org.slf4j.LoggerFactory; |
|
|
|
|
import java.net.URL; |
|
|
|
|
import java.util.ArrayList; |
|
|
|
|
import java.util.List; |
|
|
|
|
import java.util.concurrent.atomic.AtomicReference; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* @author Sindre Mehus |
|
|
|
@ -53,14 +54,54 @@ public class UPnPService { |
|
|
|
|
private SettingsService settingsService; |
|
|
|
|
private UpnpService upnpService; |
|
|
|
|
private FolderBasedContentDirectory folderBasedContentDirectory; |
|
|
|
|
private AtomicReference<Boolean> running = new AtomicReference<>(false); |
|
|
|
|
|
|
|
|
|
public void init() { |
|
|
|
|
if(settingsService.isDlnaEnabled() || settingsService.isSonosEnabled()) { |
|
|
|
|
ensureServiceStarted(); |
|
|
|
|
if(settingsService.isDlnaEnabled()) { |
|
|
|
|
// Start DLNA media server?
|
|
|
|
|
setMediaServerEnabled(true); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
Runtime.getRuntime().addShutdownHook(new Thread() { |
|
|
|
|
@Override |
|
|
|
|
public void run() { |
|
|
|
|
ensureServiceStopped(); |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public void ensureServiceStarted() { |
|
|
|
|
running.getAndUpdate(bo -> { |
|
|
|
|
if(!bo) { |
|
|
|
|
startService(); |
|
|
|
|
return true; |
|
|
|
|
} else { |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public void startService() { |
|
|
|
|
Runnable runnable = new Runnable() { |
|
|
|
|
public void run() { |
|
|
|
|
public void ensureServiceStopped() { |
|
|
|
|
running.getAndUpdate(bo -> { |
|
|
|
|
if (bo) { |
|
|
|
|
if (upnpService != null) { |
|
|
|
|
LOG.info("Disabling UPnP/DLNA media server"); |
|
|
|
|
upnpService.getRegistry().removeAllLocalDevices(); |
|
|
|
|
System.err.println("Shutting down UPnP service..."); |
|
|
|
|
upnpService.shutdown(); |
|
|
|
|
System.err.println("Shutting down UPnP service - Done!"); |
|
|
|
|
} |
|
|
|
|
return false; |
|
|
|
|
} else { |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private void startService() { |
|
|
|
|
try { |
|
|
|
|
LOG.info("Starting UPnP service..."); |
|
|
|
|
createService(); |
|
|
|
@ -69,9 +110,6 @@ public class UPnPService { |
|
|
|
|
LOG.error("Failed to start UPnP service: " + x, x); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
new Thread(runnable).start(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private synchronized void createService() throws Exception { |
|
|
|
|
upnpService = new UpnpServiceImpl(new ApacheUpnpServiceConfiguration()); |
|
|
|
@ -79,21 +117,11 @@ public class UPnPService { |
|
|
|
|
// Asynch search for other devices (most importantly UPnP-enabled routers for port-mapping)
|
|
|
|
|
upnpService.getControlPoint().search(); |
|
|
|
|
|
|
|
|
|
// Start DLNA media server?
|
|
|
|
|
setMediaServerEnabled(settingsService.isDlnaEnabled()); |
|
|
|
|
|
|
|
|
|
Runtime.getRuntime().addShutdownHook(new Thread() { |
|
|
|
|
@Override |
|
|
|
|
public void run() { |
|
|
|
|
System.err.println("Shutting down UPnP service..."); |
|
|
|
|
upnpService.shutdown(); |
|
|
|
|
System.err.println("Shutting down UPnP service - Done!"); |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public void setMediaServerEnabled(boolean enabled) { |
|
|
|
|
if (enabled) { |
|
|
|
|
ensureServiceStarted(); |
|
|
|
|
try { |
|
|
|
|
upnpService.getRegistry().addDevice(createMediaServerDevice()); |
|
|
|
|
LOG.info("Enabling UPnP/DLNA media server"); |
|
|
|
@ -101,8 +129,7 @@ public class UPnPService { |
|
|
|
|
LOG.error("Failed to start UPnP/DLNA media server: " + x, x); |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
upnpService.getRegistry().removeAllLocalDevices(); |
|
|
|
|
LOG.info("Disabling UPnP/DLNA media server"); |
|
|
|
|
ensureServiceStopped(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -157,6 +184,7 @@ public class UPnPService { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public List<String> getSonosControllerHosts() { |
|
|
|
|
ensureServiceStarted(); |
|
|
|
|
List<String> result = new ArrayList<String>(); |
|
|
|
|
for (Device device : upnpService.getRegistry().getDevices(new DeviceType("schemas-upnp-org", "ZonePlayer"))) { |
|
|
|
|
if (device instanceof RemoteDevice) { |
|
|
|
|