Merged UpnpController into RemotePlayService.
This commit is contained in:
parent
8ec6b90e92
commit
20e0517594
4 changed files with 118 additions and 281 deletions
|
@ -31,7 +31,6 @@ import android.os.Messenger;
|
||||||
|
|
||||||
interface IRemotePlayService {
|
interface IRemotePlayService {
|
||||||
void startSearch(in Messenger listener);
|
void startSearch(in Messenger listener);
|
||||||
void stopSearch();
|
|
||||||
void selectRenderer(String id);
|
void selectRenderer(String id);
|
||||||
void unselectRenderer(String id);
|
void unselectRenderer(String id);
|
||||||
void setVolume(int volume);
|
void setVolume(int volume);
|
||||||
|
|
|
@ -205,8 +205,6 @@ final class Provider extends MediaRouteProvider {
|
||||||
try {
|
try {
|
||||||
if (request != null && request.isActiveScan())
|
if (request != null && request.isActiveScan())
|
||||||
mIRemotePlayService.startSearch(mListener);
|
mIRemotePlayService.startSearch(mListener);
|
||||||
else
|
|
||||||
mIRemotePlayService.stopSearch();
|
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,15 +30,21 @@ package com.github.nutomic.controldlna.upnp;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.teleal.cling.android.AndroidUpnpService;
|
||||||
|
import org.teleal.cling.android.AndroidUpnpServiceImpl;
|
||||||
import org.teleal.cling.controlpoint.SubscriptionCallback;
|
import org.teleal.cling.controlpoint.SubscriptionCallback;
|
||||||
import org.teleal.cling.model.action.ActionInvocation;
|
import org.teleal.cling.model.action.ActionInvocation;
|
||||||
import org.teleal.cling.model.gena.CancelReason;
|
import org.teleal.cling.model.gena.CancelReason;
|
||||||
import org.teleal.cling.model.gena.GENASubscription;
|
import org.teleal.cling.model.gena.GENASubscription;
|
||||||
import org.teleal.cling.model.message.UpnpResponse;
|
import org.teleal.cling.model.message.UpnpResponse;
|
||||||
import org.teleal.cling.model.meta.Device;
|
import org.teleal.cling.model.meta.Device;
|
||||||
|
import org.teleal.cling.model.meta.LocalDevice;
|
||||||
import org.teleal.cling.model.meta.RemoteDevice;
|
import org.teleal.cling.model.meta.RemoteDevice;
|
||||||
import org.teleal.cling.model.meta.StateVariableAllowedValueRange;
|
import org.teleal.cling.model.meta.StateVariableAllowedValueRange;
|
||||||
import org.teleal.cling.model.state.StateVariableValue;
|
import org.teleal.cling.model.state.StateVariableValue;
|
||||||
|
import org.teleal.cling.model.types.ServiceType;
|
||||||
|
import org.teleal.cling.registry.Registry;
|
||||||
|
import org.teleal.cling.registry.RegistryListener;
|
||||||
import org.teleal.cling.support.avtransport.callback.GetPositionInfo;
|
import org.teleal.cling.support.avtransport.callback.GetPositionInfo;
|
||||||
import org.teleal.cling.support.avtransport.callback.Pause;
|
import org.teleal.cling.support.avtransport.callback.Pause;
|
||||||
import org.teleal.cling.support.avtransport.callback.Play;
|
import org.teleal.cling.support.avtransport.callback.Play;
|
||||||
|
@ -54,7 +60,10 @@ import org.teleal.cling.support.renderingcontrol.callback.GetVolume;
|
||||||
import org.teleal.cling.support.renderingcontrol.callback.SetVolume;
|
import org.teleal.cling.support.renderingcontrol.callback.SetVolume;
|
||||||
|
|
||||||
import android.app.Service;
|
import android.app.Service;
|
||||||
|
import android.content.ComponentName;
|
||||||
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
import android.content.ServiceConnection;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
import android.os.Messenger;
|
import android.os.Messenger;
|
||||||
|
@ -63,8 +72,6 @@ import android.support.v7.media.MediaItemStatus;
|
||||||
import android.support.v7.media.MediaItemStatus.Builder;
|
import android.support.v7.media.MediaItemStatus.Builder;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.github.nutomic.controldlna.upnp.UpnpController.DeviceListenerCallback;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allows UPNP playback from within different apps by providing a proxy interface.
|
* Allows UPNP playback from within different apps by providing a proxy interface.
|
||||||
|
@ -72,7 +79,7 @@ import com.github.nutomic.controldlna.upnp.UpnpController.DeviceListenerCallback
|
||||||
* @author Felix Ableitner
|
* @author Felix Ableitner
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class RemotePlayService extends Service implements DeviceListenerCallback {
|
public class RemotePlayService extends Service implements RegistryListener {
|
||||||
|
|
||||||
private static final String TAG = "RemotePlayService";
|
private static final String TAG = "RemotePlayService";
|
||||||
|
|
||||||
|
@ -86,7 +93,30 @@ public class RemotePlayService extends Service implements DeviceListenerCallback
|
||||||
|
|
||||||
private boolean mManuallyStopped;
|
private boolean mManuallyStopped;
|
||||||
|
|
||||||
private UpnpController mUpnpController = new UpnpController();
|
protected AndroidUpnpService mUpnpService;
|
||||||
|
|
||||||
|
private ServiceConnection mUpnpServiceConnection = new ServiceConnection() {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers DeviceListener, adds known devices and starts search if requested.
|
||||||
|
*/
|
||||||
|
public void onServiceConnected(ComponentName className, IBinder service) {
|
||||||
|
mUpnpService = (AndroidUpnpService) service;
|
||||||
|
mUpnpService.getRegistry().addListener(RemotePlayService.this);
|
||||||
|
for (Device<?, ?, ?> d : mUpnpService.getControlPoint().getRegistry().getDevices()) {
|
||||||
|
if (d instanceof LocalDevice)
|
||||||
|
localDeviceAdded(mUpnpService.getRegistry(), (LocalDevice) d);
|
||||||
|
else
|
||||||
|
remoteDeviceAdded(mUpnpService.getRegistry(), (RemoteDevice) d);
|
||||||
|
}
|
||||||
|
Log.i(TAG, "Starting device search");
|
||||||
|
mUpnpService.getControlPoint().search();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onServiceDisconnected(ComponentName className) {
|
||||||
|
mUpnpService = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Receives events from current renderer.
|
* Receives events from current renderer.
|
||||||
|
@ -98,20 +128,15 @@ public class RemotePlayService extends Service implements DeviceListenerCallback
|
||||||
@Override
|
@Override
|
||||||
public void startSearch(Messenger listener)
|
public void startSearch(Messenger listener)
|
||||||
throws RemoteException {
|
throws RemoteException {
|
||||||
mUpnpController.startSearch();
|
|
||||||
mListener = listener;
|
mListener = listener;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void stopSearch() throws RemoteException {
|
|
||||||
mUpnpController.stopSearch();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void selectRenderer(String id) throws RemoteException {
|
public void selectRenderer(String id) throws RemoteException {
|
||||||
mCurrentRenderer = mDevices.get(id);
|
mCurrentRenderer = mDevices.get(id);
|
||||||
mSubscriptionCallback = new SubscriptionCallback(
|
mSubscriptionCallback = new SubscriptionCallback(
|
||||||
UpnpController.getService(mCurrentRenderer, "AVTransport"), 600) {
|
mCurrentRenderer.findService(
|
||||||
|
new ServiceType("schemas-upnp-org", "AVTransport")), 600) {
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
@Override
|
@Override
|
||||||
|
@ -176,7 +201,7 @@ public class RemotePlayService extends Service implements DeviceListenerCallback
|
||||||
Exception exception, String defaultMsg) {
|
Exception exception, String defaultMsg) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
mUpnpController.execute(mSubscriptionCallback);
|
mUpnpService.getControlPoint().execute(mSubscriptionCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -192,8 +217,8 @@ public class RemotePlayService extends Service implements DeviceListenerCallback
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void setVolume(int volume) throws RemoteException {
|
public void setVolume(int volume) throws RemoteException {
|
||||||
mUpnpController.execute(
|
mUpnpService.getControlPoint().execute(
|
||||||
new SetVolume(UpnpController.getService(mCurrentRenderer,
|
new SetVolume(getService(mCurrentRenderer,
|
||||||
"RenderingControl"), volume) {
|
"RenderingControl"), volume) {
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
|
@ -211,8 +236,8 @@ public class RemotePlayService extends Service implements DeviceListenerCallback
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void play(String uri, String metadata) throws RemoteException {
|
public void play(String uri, String metadata) throws RemoteException {
|
||||||
mUpnpController.execute(new SetAVTransportURI(
|
mUpnpService.getControlPoint().execute(new SetAVTransportURI(
|
||||||
UpnpController.getService(mCurrentRenderer, "AVTransport"),
|
getService(mCurrentRenderer, "AVTransport"),
|
||||||
uri, metadata) {
|
uri, metadata) {
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
@Override
|
@Override
|
||||||
|
@ -224,8 +249,8 @@ public class RemotePlayService extends Service implements DeviceListenerCallback
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
@Override
|
@Override
|
||||||
public void success(ActionInvocation invocation) {
|
public void success(ActionInvocation invocation) {
|
||||||
mUpnpController.execute(
|
mUpnpService.getControlPoint().execute(
|
||||||
new Play(UpnpController.getService(mCurrentRenderer,
|
new Play(getService(mCurrentRenderer,
|
||||||
"AVTransport")) {
|
"AVTransport")) {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -243,9 +268,8 @@ public class RemotePlayService extends Service implements DeviceListenerCallback
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void pause(final String sessionId) throws RemoteException {
|
public void pause(final String sessionId) throws RemoteException {
|
||||||
mUpnpController.execute(
|
mUpnpService.getControlPoint().execute(
|
||||||
new Pause(UpnpController.getService(mDevices.get(sessionId),
|
new Pause(getService(mDevices.get(sessionId), "AVTransport")) {
|
||||||
"AVTransport")) {
|
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
@Override
|
@Override
|
||||||
|
@ -264,8 +288,8 @@ public class RemotePlayService extends Service implements DeviceListenerCallback
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void resume(String sessionId) throws RemoteException {
|
public void resume(String sessionId) throws RemoteException {
|
||||||
mUpnpController.execute(
|
mUpnpService.getControlPoint().execute(
|
||||||
new Play(UpnpController.getService(mDevices.get(sessionId),
|
new Play(getService(mDevices.get(sessionId),
|
||||||
"AVTransport")) {
|
"AVTransport")) {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -283,9 +307,8 @@ public class RemotePlayService extends Service implements DeviceListenerCallback
|
||||||
@Override
|
@Override
|
||||||
public void stop(String sessionId) throws RemoteException {
|
public void stop(String sessionId) throws RemoteException {
|
||||||
mManuallyStopped = true;
|
mManuallyStopped = true;
|
||||||
mUpnpController.execute(
|
mUpnpService.getControlPoint().execute(
|
||||||
new Stop(UpnpController.getService(mDevices.get(sessionId),
|
new Stop(getService(mDevices.get(sessionId), "AVTransport")) {
|
||||||
"AVTransport")) {
|
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
@Override
|
@Override
|
||||||
|
@ -303,8 +326,8 @@ public class RemotePlayService extends Service implements DeviceListenerCallback
|
||||||
@Override
|
@Override
|
||||||
public void seek(String sessionId, String itemId, long milliseconds)
|
public void seek(String sessionId, String itemId, long milliseconds)
|
||||||
throws RemoteException {
|
throws RemoteException {
|
||||||
mUpnpController.execute(new Seek(
|
mUpnpService.getControlPoint().execute(new Seek(
|
||||||
UpnpController.getService(mDevices.get(sessionId), "AVTransport"),
|
getService(mDevices.get(sessionId), "AVTransport"),
|
||||||
SeekMode.REL_TIME,
|
SeekMode.REL_TIME,
|
||||||
Integer.toString((int) milliseconds / 1000)) {
|
Integer.toString((int) milliseconds / 1000)) {
|
||||||
|
|
||||||
|
@ -330,8 +353,8 @@ public class RemotePlayService extends Service implements DeviceListenerCallback
|
||||||
@Override
|
@Override
|
||||||
public void getItemStatus(String sessionId, final String itemId, final int requestHash)
|
public void getItemStatus(String sessionId, final String itemId, final int requestHash)
|
||||||
throws RemoteException {
|
throws RemoteException {
|
||||||
mUpnpController.execute(new GetPositionInfo(
|
mUpnpService.getControlPoint().execute(new GetPositionInfo(
|
||||||
UpnpController.getService(mDevices.get(sessionId), "AVTransport")) {
|
getService(mDevices.get(sessionId), "AVTransport")) {
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
@Override
|
@Override
|
||||||
|
@ -378,22 +401,34 @@ public class RemotePlayService extends Service implements DeviceListenerCallback
|
||||||
@Override
|
@Override
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
super.onCreate();
|
super.onCreate();
|
||||||
mUpnpController.open(this);
|
bindService(
|
||||||
mUpnpController.addCallback(this);
|
new Intent(this, AndroidUpnpServiceImpl.class),
|
||||||
|
mUpnpServiceConnection,
|
||||||
|
Context.BIND_AUTO_CREATE
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDestroy() {
|
public void onDestroy() {
|
||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
mUpnpController.close(this);
|
unbindService(mUpnpServiceConnection);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a device service by name for direct queries.
|
||||||
|
*/
|
||||||
|
private org.teleal.cling.model.meta.Service<?, ?> getService(
|
||||||
|
Device<?, ?, ?> device, String name) {
|
||||||
|
return device.findService(
|
||||||
|
new ServiceType("schemas-upnp-org", name));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gather device data and send it to Provider.
|
* Gather device data and send it to Provider.
|
||||||
*/
|
*/
|
||||||
@Override
|
private void deviceAdded(final Device<?, ?, ?> device) {
|
||||||
public void deviceAdded(final Device<?, ?, ?> device) {
|
final org.teleal.cling.model.meta.Service<?, ?> rc =
|
||||||
final org.teleal.cling.model.meta.Service<?, ?> rc = UpnpController.getService(device, "RenderingControl");
|
getService(device, "RenderingControl");
|
||||||
if (rc == null || mListener == null)
|
if (rc == null || mListener == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -401,7 +436,7 @@ public class RemotePlayService extends Service implements DeviceListenerCallback
|
||||||
device instanceof RemoteDevice) {
|
device instanceof RemoteDevice) {
|
||||||
mDevices.put(device.getIdentity().getUdn().toString(), device);
|
mDevices.put(device.getIdentity().getUdn().toString(), device);
|
||||||
|
|
||||||
mUpnpController.execute(
|
mUpnpService.getControlPoint().execute(
|
||||||
new GetVolume(rc) {
|
new GetVolume(rc) {
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
|
@ -441,8 +476,7 @@ public class RemotePlayService extends Service implements DeviceListenerCallback
|
||||||
/**
|
/**
|
||||||
* Remove the device from Provider.
|
* Remove the device from Provider.
|
||||||
*/
|
*/
|
||||||
@Override
|
private void deviceRemoved(Device<?, ?, ?> device) {
|
||||||
public void deviceRemoved(Device<?, ?, ?> device) {
|
|
||||||
if (device.getType().getType().equals("MediaRenderer") &&
|
if (device.getType().getType().equals("MediaRenderer") &&
|
||||||
device instanceof RemoteDevice) {
|
device instanceof RemoteDevice) {
|
||||||
Message msg = Message.obtain(null, Provider.MSG_RENDERER_REMOVED, 0, 0);
|
Message msg = Message.obtain(null, Provider.MSG_RENDERER_REMOVED, 0, 0);
|
||||||
|
@ -462,8 +496,50 @@ public class RemotePlayService extends Service implements DeviceListenerCallback
|
||||||
* If a device was updated, we just add it again (devices are stored in
|
* If a device was updated, we just add it again (devices are stored in
|
||||||
* maps, so adding the same one again just overwrites the old one).
|
* maps, so adding the same one again just overwrites the old one).
|
||||||
*/
|
*/
|
||||||
@Override
|
private void deviceUpdated(Device<?, ?, ?> device) {
|
||||||
public void deviceUpdated(Device<?, ?, ?> device) {
|
|
||||||
deviceAdded(device);
|
deviceAdded(device);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterShutdown() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void beforeShutdown(Registry registry) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void localDeviceAdded(Registry registry, LocalDevice device) {
|
||||||
|
deviceAdded(device);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void localDeviceRemoved(Registry registry, LocalDevice device) {
|
||||||
|
deviceRemoved(device);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remoteDeviceAdded(Registry registry, RemoteDevice device) {
|
||||||
|
deviceAdded(device);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remoteDeviceDiscoveryFailed(Registry registry, RemoteDevice device,
|
||||||
|
Exception exception) {
|
||||||
|
Log.w(TAG, "Remote device discovery failed", exception);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remoteDeviceDiscoveryStarted(Registry registry, RemoteDevice device) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remoteDeviceRemoved(Registry registry, RemoteDevice device) {
|
||||||
|
deviceRemoved(device);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remoteDeviceUpdated(Registry registry, RemoteDevice device) {
|
||||||
|
deviceUpdated(device);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,236 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright (c) 2013, Felix Ableitner
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are met:
|
|
||||||
* Redistributions of source code must retain the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer.
|
|
||||||
* Redistributions in binary form must reproduce the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer in the
|
|
||||||
documentation and/or other materials provided with the distribution.
|
|
||||||
* Neither the name of the <organization> nor the
|
|
||||||
names of its contributors may be used to endorse or promote products
|
|
||||||
derived from this software without specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
|
||||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.github.nutomic.controldlna.upnp;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
import org.teleal.cling.android.AndroidUpnpService;
|
|
||||||
import org.teleal.cling.android.AndroidUpnpServiceImpl;
|
|
||||||
import org.teleal.cling.controlpoint.ActionCallback;
|
|
||||||
import org.teleal.cling.controlpoint.SubscriptionCallback;
|
|
||||||
import org.teleal.cling.model.meta.Device;
|
|
||||||
import org.teleal.cling.model.meta.LocalDevice;
|
|
||||||
import org.teleal.cling.model.meta.RemoteDevice;
|
|
||||||
import org.teleal.cling.model.meta.Service;
|
|
||||||
import org.teleal.cling.model.types.ServiceType;
|
|
||||||
import org.teleal.cling.registry.Registry;
|
|
||||||
import org.teleal.cling.registry.RegistryListener;
|
|
||||||
|
|
||||||
import android.content.ComponentName;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.ServiceConnection;
|
|
||||||
import android.os.IBinder;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles UPNP connection, including device discovery and general queries.
|
|
||||||
*
|
|
||||||
* @author Felix Ableitner
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class UpnpController implements RegistryListener {
|
|
||||||
|
|
||||||
private static final String TAG = "UpnpController";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Callbacks may be called from a background thread.
|
|
||||||
*
|
|
||||||
* @author Felix Ableitner
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public interface DeviceListenerCallback {
|
|
||||||
public void deviceAdded(Device<?, ?, ?> device);
|
|
||||||
public void deviceRemoved(Device<?, ?, ?> device);
|
|
||||||
public void deviceUpdated(Device<?, ?, ?> device);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Used if the UPNP service is not yet ready. If true, a device search
|
|
||||||
* will be started as soon as the service becomes available.
|
|
||||||
*/
|
|
||||||
private boolean mStartSearchImmediately;
|
|
||||||
|
|
||||||
private ArrayList<Device<?, ?, ?>> mDevices = new ArrayList<Device<?, ?, ?>>();
|
|
||||||
|
|
||||||
private ArrayList<DeviceListenerCallback> mListeners =
|
|
||||||
new ArrayList<DeviceListenerCallback>();
|
|
||||||
|
|
||||||
protected AndroidUpnpService mUpnpService;
|
|
||||||
|
|
||||||
private ServiceConnection mUpnpServiceConnection = new ServiceConnection() {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Registers DeviceListener, adds known devices and starts search if requested.
|
|
||||||
*/
|
|
||||||
public void onServiceConnected(ComponentName className, IBinder service) {
|
|
||||||
mUpnpService = (AndroidUpnpService) service;
|
|
||||||
mUpnpService.getRegistry().addListener(UpnpController.this);
|
|
||||||
for (Device<?, ?, ?> d : mUpnpService.getControlPoint().getRegistry().getDevices()) {
|
|
||||||
if (d instanceof LocalDevice)
|
|
||||||
localDeviceAdded(mUpnpService.getRegistry(), (LocalDevice) d);
|
|
||||||
else
|
|
||||||
remoteDeviceAdded(mUpnpService.getRegistry(), (RemoteDevice) d);
|
|
||||||
}
|
|
||||||
if (mStartSearchImmediately)
|
|
||||||
startSearch();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onServiceDisconnected(ComponentName className) {
|
|
||||||
mUpnpService = null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Opens connection to the Cling UPNP service.
|
|
||||||
*
|
|
||||||
* @param context Application context.
|
|
||||||
*/
|
|
||||||
public void open(Context context) {
|
|
||||||
context.bindService(
|
|
||||||
new Intent(context, AndroidUpnpServiceImpl.class),
|
|
||||||
mUpnpServiceConnection,
|
|
||||||
Context.BIND_AUTO_CREATE
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Closes the connection to the Cling UPNP service.
|
|
||||||
*
|
|
||||||
* @param context Application context.
|
|
||||||
*/
|
|
||||||
public void close(Context context) {
|
|
||||||
mUpnpService.getRegistry().removeListener(this);
|
|
||||||
context.unbindService(mUpnpServiceConnection);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Starts active search for UPNP devices.
|
|
||||||
*/
|
|
||||||
public void startSearch() {
|
|
||||||
if (mUpnpService != null) {
|
|
||||||
Log.i(TAG, "Starting device search");
|
|
||||||
mUpnpService.getControlPoint().search();
|
|
||||||
mStartSearchImmediately = false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
mStartSearchImmediately = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Stops active search for UPNP devices.
|
|
||||||
*
|
|
||||||
* Not yet implemented.
|
|
||||||
*/
|
|
||||||
public void stopSearch() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a device service by name for direct queries.
|
|
||||||
*/
|
|
||||||
public static Service<?, ?> getService(Device<?, ?, ?> device, String name) {
|
|
||||||
return device.findService(
|
|
||||||
new ServiceType("schemas-upnp-org", name));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addCallback(DeviceListenerCallback callback) {
|
|
||||||
mListeners.add(callback);
|
|
||||||
for (Device<?, ?, ?> d : mDevices) {
|
|
||||||
callback.deviceAdded(d);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void removeCallback(DeviceListenerCallback callback) {
|
|
||||||
mListeners.remove(callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void deviceAdded(Device<?, ?, ?> device) {
|
|
||||||
mDevices.add(device);
|
|
||||||
for (DeviceListenerCallback l : mListeners)
|
|
||||||
l.deviceAdded(device);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void deviceRemoved(Device<?, ?, ?> device) {
|
|
||||||
mDevices.remove(device);
|
|
||||||
for (DeviceListenerCallback l : mListeners)
|
|
||||||
l.deviceRemoved(device);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void execute(ActionCallback callback) {
|
|
||||||
mUpnpService.getControlPoint().execute(callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void execute(SubscriptionCallback callback) {
|
|
||||||
mUpnpService.getControlPoint().execute(callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void afterShutdown() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void beforeShutdown(Registry registry) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void localDeviceAdded(Registry registry, LocalDevice device) {
|
|
||||||
deviceAdded(device);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void localDeviceRemoved(Registry registry, LocalDevice device) {
|
|
||||||
deviceRemoved(device);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void remoteDeviceAdded(Registry registry, RemoteDevice device) {
|
|
||||||
deviceAdded(device);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void remoteDeviceDiscoveryFailed(Registry registry, RemoteDevice device,
|
|
||||||
Exception exception) {
|
|
||||||
Log.w(TAG, "Remote device discovery failed", exception);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void remoteDeviceDiscoveryStarted(Registry registry, RemoteDevice device) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void remoteDeviceRemoved(Registry registry, RemoteDevice device) {
|
|
||||||
deviceRemoved(device);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void remoteDeviceUpdated(Registry registry, RemoteDevice device) {
|
|
||||||
for (DeviceListenerCallback l : mListeners)
|
|
||||||
l.deviceUpdated(device);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
Reference in a new issue