Commit a9dfb509 authored by Larry Sachs's avatar Larry Sachs

UpnpAvClientDemo uses new data models if available

Change-Id: I3caea37b34db0bbd4d459ce7b5607b9ca5b3562a
Signed-off-by: Larry Sachs's avatarLarry Sachs <larry.j.sachs@intel.com>
parent 745f6a73
......@@ -22,6 +22,9 @@
package org.iotivity.base.examples;
import android.os.Parcel;
import android.os.Parcelable;
import org.iotivity.base.OcException;
import org.iotivity.base.OcRepresentation;
......@@ -31,11 +34,12 @@ import org.iotivity.base.OcRepresentation;
* This class is used by UpnpAvClientActivity to create an object representation of a remote audio resource
* and update the values depending on the server response
*/
public class Audio extends Service {
public class Audio extends Service implements Parcelable {
public static final String OIC_TYPE_AUDIO = "oic.r.audio";
public static final String OCF_OIC_URI_PREFIX_AUDIO = "/ocf/audio/";
public static final String UPNP_OIC_URI_PREFIX_AUDIO = "/upnp/audio/";
public static final String UPNP_OIC_URI_PREFIX_AUDIO_NM_HREF = "/upnp/audio/RenderingControl/";
public static final String MUTE_KEY = "mute";
public static final boolean DEFAULT_MUTE = false;
......@@ -84,7 +88,7 @@ public class Audio extends Service {
return rep;
}
public boolean getMute() {
public boolean isMute() {
return mMute;
}
......@@ -111,4 +115,39 @@ public class Audio extends Service {
", " + MUTE_KEY + ": " + mMute +
", " + VOLUME_KEY + ": " + mVolume + "]";
}
// Parcelable implementation
public Audio(Parcel in) {
readFromParcel(in);
}
public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
public Audio createFromParcel(Parcel in) {
return new Audio(in);
}
public Audio[] newArray(int size) {
return new Audio[size];
}
};
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(getName());
dest.writeString(getUri());
dest.writeInt(getVolume());
dest.writeByte((byte) (isMute() ? 1 : 0));
dest.writeByte((byte) (isInitialized() ? 1 : 0));
}
private void readFromParcel(Parcel in) {
setName(in.readString());
setUri(in.readString());
setVolume(in.readInt());
setMute(in.readByte() != 0);
mIsInitialized = in.readByte() != 0;
}
public int describeContents() {
return 0;
}
}
......@@ -22,6 +22,9 @@
package org.iotivity.base.examples;
import android.os.Parcel;
import android.os.Parcelable;
import org.iotivity.base.OcException;
import org.iotivity.base.OcRepresentation;
......@@ -31,11 +34,12 @@ import org.iotivity.base.OcRepresentation;
* This class is used by UpnpAvClientActivity to create an object representation of a remote media control resource
* and update the values depending on the server response
*/
public class MediaControl extends Service {
public class MediaControl extends Service implements Parcelable {
public static final String OIC_TYPE_MEDIA_CONTROL = "oic.r.media.control";
public static final String OCF_OIC_URI_PREFIX_MEDIA_CONTROL = "/ocf/mediaControl/";
public static final String UPNP_OIC_URI_PREFIX_MEDIA_CONTROL = "/upnp/mediaControl/";
public static final String UPNP_OIC_URI_PREFIX_MEDIA_CONTROL_NM_HREF = "/upnp/mediaControl/AVTransport/";
public static final String STATE_KEY = "playState";
public static final boolean DEFAULT_STATE = false;
......@@ -44,7 +48,7 @@ public class MediaControl extends Service {
public static final double DEFAULT_SPEED = 1.0;
public static final String LOCATION_KEY = "mediaLocation";
public static final String DEFAULT_LOCATION = "0";
public static final String DEFAULT_LOCATION = "00:00:00";
public static final String LAST_ACTION_KEY = "lastAction";
public static final String DEFAULT_LAST_ACTION = "stop";
......@@ -124,9 +128,11 @@ public class MediaControl extends Service {
rep.setValue(LOCATION_KEY, mMediaLocation);
rep.setValue(LAST_ACTION_KEY, mLastAction);
OcRepresentation[] actions = mActions.getOcRepresentation();
if ((actions != null) && (actions.length > 0)) {
rep.setValue(ACTIONS_KEY, actions);
if (mActions != null) {
OcRepresentation[] actions = mActions.getOcRepresentation();
if ((actions != null) && (actions.length > 0)) {
rep.setValue(ACTIONS_KEY, actions);
}
}
return rep;
......@@ -186,4 +192,43 @@ public class MediaControl extends Service {
", " + LAST_ACTION_KEY + ": " + mLastAction +
", " + ACTIONS_KEY + mActions + "]";
}
// Parcelable implementation
public MediaControl(Parcel in) {
readFromParcel(in);
}
public static final Parcelable.Creator CREATOR = new Parcelable.Creator() {
public MediaControl createFromParcel(Parcel in) {
return new MediaControl(in);
}
public MediaControl[] newArray(int size) {
return new MediaControl[size];
}
};
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(getName());
dest.writeString(getUri());
dest.writeByte((byte) (getPlayState() ? 1 : 0));
dest.writeDouble(getMediaSpeed());
dest.writeString(getMediaLocation());
dest.writeString(getLastAction());
dest.writeByte((byte) (isInitialized() ? 1 : 0));
}
private void readFromParcel(Parcel in) {
setName(in.readString());
setUri(in.readString());
setPlayState(in.readByte() != 0);
setMediaSpeed(in.readDouble());
setMediaLocation(in.readString());
setLastAction(in.readString());
mIsInitialized = in.readByte() != 0;
}
public int describeContents() {
return 0;
}
}
......@@ -40,6 +40,10 @@ public class MediaRenderer extends Device {
private ConnectionManager mConnectionManager;
private AvTransport mAvTransport;
// New data models
private MediaControl mMediaControl;
private Audio mAudio;
public MediaRenderer() {
super();
}
......@@ -77,10 +81,29 @@ public class MediaRenderer extends Device {
mAvTransport = avTransport;
}
public MediaControl getMediaControl() {
return mMediaControl;
}
public void setMediaControl(MediaControl mediaControl) {
mMediaControl = mediaControl;
}
public Audio getAudio() {
return mAudio;
}
public void setAudio(Audio audio) {
mAudio = audio;
}
public int getVolume() {
int volume = RenderingControl.DEFAULT_VOLUME;
if (mRenderingControl != null) {
if (mAudio != null) {
volume = mAudio.getVolume();
} else if (mRenderingControl != null) {
volume = mRenderingControl.getVolume();
}
......@@ -88,6 +111,10 @@ public class MediaRenderer extends Device {
}
public void setVolume(int volume) {
if (mAudio != null) {
mAudio.setVolume(volume);
}
if (mRenderingControl != null) {
mRenderingControl.setVolume(volume);
}
......@@ -96,7 +123,10 @@ public class MediaRenderer extends Device {
public boolean isMute() {
boolean isMute = RenderingControl.DEFAULT_MUTE;
if (mRenderingControl != null) {
if (mAudio != null) {
isMute = mAudio.isMute();
} else if (mRenderingControl != null) {
isMute = mRenderingControl.isMute();
}
......@@ -104,6 +134,10 @@ public class MediaRenderer extends Device {
}
public void setMute(boolean mute) {
if (mAudio != null) {
mAudio.setMute(mute);
}
if (mRenderingControl != null) {
mRenderingControl.setMute(mute);
}
......@@ -114,7 +148,11 @@ public class MediaRenderer extends Device {
String renderingControlAsString = mRenderingControl != null ? mRenderingControl.toString() : "rendering control is null";
String connectionManagerAsString = mConnectionManager != null ? mConnectionManager.toString() : "connection manager is null";
String avTransportAsString = mAvTransport != null ? mAvTransport.toString() : "av transport is null";
String mediaControlAsString = mMediaControl != null ? mMediaControl.toString() : "media control is not defined";
String audioAsString = mAudio != null ? mAudio.toString() : "audio is not defined";
return "[" + super.toString() +
", " + mediaControlAsString +
", " + audioAsString +
", " + connectionManagerAsString +
", " + avTransportAsString +
", " + renderingControlAsString + "]";
......
......@@ -53,7 +53,12 @@ public class UpnpAvClientMediaRenderControlActivity extends Activity implements
static public final String EXTRA_AV_TRANSPORT_OBJECT = "extra.av.transport.object";
static public final String EXTRA_RENDERING_CONTROL_OBJECT = "extra.rendering.control.object";
static public final String EXTRA_MEDIA_CONTROL_OBJECT = "extra.media.control.object";
static public final String EXTRA_AUDIO_OBJECT = "extra.audio.object";
static private final String TAG = UpnpAvClientMediaRenderControlActivity.class.getSimpleName();
private MediaControl mMediaControl;
private Audio mAudio;
private AvTransport mAvTransport;
private RenderingControl mRenderingControl;
private MediaItem mMediaItem;
......@@ -62,6 +67,10 @@ public class UpnpAvClientMediaRenderControlActivity extends Activity implements
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (savedInstanceState != null) {
mMediaControl = savedInstanceState.getParcelable(EXTRA_MEDIA_CONTROL_OBJECT);
Log.d(TAG, "onCreate RestoreInstanceState, mMediaControl="+mMediaControl);
mAudio = savedInstanceState.getParcelable(EXTRA_AUDIO_OBJECT);
Log.d(TAG, "onCreate RestoreInstanceState, mAudio="+mAudio);
mAvTransport = savedInstanceState.getParcelable(EXTRA_AV_TRANSPORT_OBJECT);
Log.d(TAG, "onCreate RestoreInstanceState, mAvTransport="+mAvTransport);
mRenderingControl = savedInstanceState.getParcelable(EXTRA_RENDERING_CONTROL_OBJECT);
......@@ -72,6 +81,12 @@ public class UpnpAvClientMediaRenderControlActivity extends Activity implements
setContentView(R.layout.activity_upnp_av_client_media_render_control);
Bundle extras = getIntent().getExtras();
if (mMediaControl == null) {
mMediaControl = extras.getParcelable(EXTRA_MEDIA_CONTROL_OBJECT);
}
if (mAudio == null) {
mAudio = extras.getParcelable(EXTRA_AUDIO_OBJECT);
}
if (mAvTransport == null) {
mAvTransport = extras.getParcelable(EXTRA_AV_TRANSPORT_OBJECT);
}
......@@ -82,6 +97,10 @@ public class UpnpAvClientMediaRenderControlActivity extends Activity implements
mMediaItem = extras.getParcelable(UpnpAvClientSelectRendererActivity.EXTRA_MEDIA_ITEM_OBJECT);
}
if ((mMediaControl != null) || (mAudio != null)) {
Log.i(TAG, "Using new data models");
}
((TextView) findViewById(R.id.name_text)).setText(mMediaItem.getDisplayName());
((TextView) findViewById(R.id.artist_text)).setText(mMediaItem.getArtist());
((TextView) findViewById(R.id.album_text)).setText(mMediaItem.getAlbum());
......@@ -115,7 +134,11 @@ public class UpnpAvClientMediaRenderControlActivity extends Activity implements
public void run() {
if (playPauseButton.getText().toString().equalsIgnoreCase("play")) {
Log.d(TAG, "Play media");
doActionAvTransportRepresentation("play");
if (mMediaControl != null) {
doActionMediaControlRepresentation("play");
} else {
doActionAvTransportRepresentation("play");
}
runOnUiThread(new Runnable() {
public void run() {
playPauseButton.setText(R.string.pause);
......@@ -124,7 +147,11 @@ public class UpnpAvClientMediaRenderControlActivity extends Activity implements
} else {
Log.d(TAG, "Pause media");
doActionAvTransportRepresentation("pause");
if (mMediaControl != null) {
doActionMediaControlRepresentation("pause");
} else {
doActionAvTransportRepresentation("pause");
}
runOnUiThread(new Runnable() {
public void run() {
playPauseButton.setText(R.string.play);
......@@ -143,7 +170,11 @@ public class UpnpAvClientMediaRenderControlActivity extends Activity implements
new Thread(new Runnable() {
public void run() {
Log.d(TAG, "Stop media");
doActionAvTransportRepresentation("stop");
if (mMediaControl != null) {
doActionMediaControlRepresentation("stop");
} else {
doActionAvTransportRepresentation("stop");
}
runOnUiThread(new Runnable() {
public void run() {
playPauseButton.setText(R.string.play);
......@@ -154,9 +185,11 @@ public class UpnpAvClientMediaRenderControlActivity extends Activity implements
}
});
((Switch) findViewById(R.id.sound_switch)).setChecked(!mRenderingControl.isMute());
((SeekBar) findViewById(R.id.volume_bar)).setProgress(mRenderingControl.getVolume());
((TextView) findViewById(R.id.volume_text)).setText(String.format(getString(R.string.volume_level), mRenderingControl.getVolume()));
boolean isMute = (mAudio != null) ? mAudio.isMute() : mRenderingControl.isMute();
int volume = (mAudio != null) ? mAudio.getVolume() : mRenderingControl.getVolume();
((Switch) findViewById(R.id.sound_switch)).setChecked(!isMute);
((SeekBar) findViewById(R.id.volume_bar)).setProgress(volume);
((TextView) findViewById(R.id.volume_text)).setText(String.format(getString(R.string.volume_level), volume));
((Switch) findViewById(R.id.sound_switch)).setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
......@@ -164,7 +197,11 @@ public class UpnpAvClientMediaRenderControlActivity extends Activity implements
final int volume = ((SeekBar) findViewById(R.id.volume_bar)).getProgress();
new Thread(new Runnable() {
public void run() {
postRenderingControlRepresentation(!isChecked, volume);
if (mAudio != null) {
postAudioRepresentation(!isChecked, volume);
} else {
postRenderingControlRepresentation(!isChecked, volume);
}
}
}).start();
}
......@@ -177,7 +214,11 @@ public class UpnpAvClientMediaRenderControlActivity extends Activity implements
final boolean soundOn = ((Switch) findViewById(R.id.sound_switch)).isChecked();
new Thread(new Runnable() {
public void run() {
postRenderingControlRepresentation(!soundOn, progress);
if (mAudio != null) {
postAudioRepresentation(!soundOn, progress);
} else {
postRenderingControlRepresentation(!soundOn, progress);
}
}
}).start();
}
......@@ -193,7 +234,11 @@ public class UpnpAvClientMediaRenderControlActivity extends Activity implements
new Thread(new Runnable() {
public void run() {
doActionAvTransportRepresentation("play");
if (mMediaControl != null) {
doActionMediaControlRepresentation("play");
} else {
doActionAvTransportRepresentation("play");
}
runOnUiThread(new Runnable() {
public void run() {
playPauseButton.setText(R.string.pause);
......@@ -206,6 +251,10 @@ public class UpnpAvClientMediaRenderControlActivity extends Activity implements
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putParcelable(EXTRA_MEDIA_CONTROL_OBJECT, mMediaControl);
Log.d(TAG, "onSaveInstanceState, mMediaControl="+mMediaControl);
outState.putParcelable(EXTRA_AUDIO_OBJECT, mAudio);
Log.d(TAG, "onSaveInstanceState, mAudio="+mAudio);
outState.putParcelable(EXTRA_AV_TRANSPORT_OBJECT, mAvTransport);
Log.d(TAG, "onSaveInstanceState, mAvTransport="+mAvTransport);
outState.putParcelable(EXTRA_RENDERING_CONTROL_OBJECT, mRenderingControl);
......@@ -217,6 +266,10 @@ public class UpnpAvClientMediaRenderControlActivity extends Activity implements
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
mMediaControl = savedInstanceState.getParcelable(EXTRA_MEDIA_CONTROL_OBJECT);
Log.d(TAG, "onCreate RestoreInstanceState, mMediaControl="+mMediaControl);
mAudio = savedInstanceState.getParcelable(EXTRA_AUDIO_OBJECT);
Log.d(TAG, "onCreate RestoreInstanceState, mAudio="+mAudio);
mAvTransport = savedInstanceState.getParcelable(EXTRA_AV_TRANSPORT_OBJECT);
Log.d(TAG, "onRestoreInstanceState, mAvTransport="+mAvTransport);
mRenderingControl = savedInstanceState.getParcelable(EXTRA_RENDERING_CONTROL_OBJECT);
......@@ -225,6 +278,93 @@ public class UpnpAvClientMediaRenderControlActivity extends Activity implements
Log.d(TAG, "onRestoreInstanceState, mMediaItem="+mMediaItem);
}
private void doActionMediaControlRepresentation(String action) {
Log.i(TAG, "Posting media control representation for " + action + " action...");
if (mMediaControl != null) {
mMediaControl.setLastAction(action);
OcRepresentation mediaControlRepresentation = null;
try {
mediaControlRepresentation = mMediaControl.getOcRepresentation();
} catch (OcException e) {
Log.e(TAG, "Failed to get OcRepresentation from media control -- " + e.toString(), e);
}
if (mediaControlRepresentation != null) {
Map<String, String> queryParams = new HashMap<>();
try {
OcResource mediaControlResource = UpnpAvClientSelectRendererActivity.getOcResourceFromUri(mMediaControl.getUri()); // FIXME:
if (mediaControlResource != null) {
mediaControlResource.post(mediaControlRepresentation, queryParams, this);
} else {
Log.e(TAG, "No media control for uri " + mMediaControl.getUri());
}
} catch (OcException e) {
Log.e(TAG, "Error occurred while invoking \"post\" API -- " + e.toString(), e);
}
}
} else {
runOnUiThread(new Runnable() {
public void run() {
if (mMediaControl == null) {
Toast.makeText(UpnpAvClientMediaRenderControlActivity.this, "No media control for uri " + mMediaControl.getUri(), Toast.LENGTH_LONG).show();
} else {
Toast.makeText(UpnpAvClientMediaRenderControlActivity.this, "No media control (initialized) for uri " + mMediaControl.getUri(), Toast.LENGTH_LONG).show();
}
}
});
}
}
private void postAudioRepresentation(boolean isMute, int newVolume) {
Log.i(TAG, "Posting audio representation...");
if (mAudio != null) {
mAudio.setMute(isMute);
mAudio.setVolume(newVolume);
OcRepresentation audioRepresentation = null;
try {
audioRepresentation = mAudio.getOcRepresentation();
} catch (OcException e) {
Log.e(TAG, "Failed to get OcRepresentation from audio -- " + e.toString(), e);
}
if (audioRepresentation != null) {
Map<String, String> queryParams = new HashMap<>();
try {
OcResource audioResource = UpnpAvClientSelectRendererActivity.getOcResourceFromUri(mAudio.getUri()); // FIXME:
if (audioResource != null) {
audioResource.post(audioRepresentation, queryParams, this);
} else {
Log.e(TAG, "No audio for uri " + mAudio.getUri());
}
} catch (OcException e) {
Log.e(TAG, "Error occurred while invoking \"post\" API -- " + e.toString(), e);
}
}
} else {
runOnUiThread(new Runnable() {
public void run() {
if (mAudio == null) {
Toast.makeText(UpnpAvClientMediaRenderControlActivity.this, "No audio for uri " + mAudio.getUri(), Toast.LENGTH_LONG).show();
} else {
Toast.makeText(UpnpAvClientMediaRenderControlActivity.this, "No audio (initialized) for uri " + mAudio.getUri(), Toast.LENGTH_LONG).show();
}
}
});
}
}
private void doActionAvTransportRepresentation(String action) {
Log.i(TAG, "Posting av transport representation for " + action + " action...");
......@@ -237,7 +377,7 @@ public class UpnpAvClientMediaRenderControlActivity extends Activity implements
avTransportRepresentation.setValue(action, embeddedOcRep);
} catch (OcException e) {
Log.e(TAG, "Failed to get OcRepresentation from a av transport -- " + e.toString(), e);
Log.e(TAG, "Failed to get OcRepresentation from av transport -- " + e.toString(), e);
}
if (avTransportRepresentation != null) {
......@@ -281,7 +421,7 @@ public class UpnpAvClientMediaRenderControlActivity extends Activity implements
renderingControlRepresentation = mRenderingControl.getOcRepresentation();
} catch (OcException e) {
Log.e(TAG, "Failed to get OcRepresentation from a rendering control -- " + e.toString(), e);
Log.e(TAG, "Failed to get OcRepresentation from rendering control -- " + e.toString(), e);
}
if (renderingControlRepresentation != null) {
......@@ -292,7 +432,7 @@ public class UpnpAvClientMediaRenderControlActivity extends Activity implements
renderingControlResource.post(renderingControlRepresentation, queryParams, this);
} else {
Log.e(TAG, "No rendering control for uri " + mAvTransport.getUri());
Log.e(TAG, "No rendering control for uri " + mRenderingControl.getUri());
}
} catch (OcException e) {
......@@ -318,19 +458,6 @@ public class UpnpAvClientMediaRenderControlActivity extends Activity implements
public synchronized void onPostCompleted(List<OcHeaderOption> list, OcRepresentation ocRepresentation) {
Log.i(TAG, "POST request was successful");
Log.i(TAG, "Resource URI (from getUri()): " + ocRepresentation.getUri());
try {
if (ocRepresentation.hasAttribute(Device.URI_KEY)) {
final String ocRepUri = ocRepresentation.getValue(Device.URI_KEY);
Log.i(TAG, "Resource URI: " + ocRepUri);
} else {
Log.w(TAG, "No Resource URI");
}
} catch (OcException e) {
Log.e(TAG, "Failed to create resource representation -- " + e.toString(), e);
}
}
@Override
......
......@@ -217,6 +217,30 @@ public class UpnpAvClientSelectRendererActivity extends Activity implements
tracked = true;
}
} else if (resourceUri.startsWith(MediaControl.UPNP_OIC_URI_PREFIX_MEDIA_CONTROL)) {
MediaControl mediaControl = new MediaControl();
mediaControl.setUri(resourceUri);
// Update the device
MediaRenderer mediaRenderer = (MediaRenderer) mResourceLookup.get(mParentUri);
if (mediaRenderer != null) {
mediaRenderer.setMediaControl(mediaControl);
mResourceLookup.put(resourceUri, mediaControl);
tracked = true;
}
} else if (resourceUri.startsWith(Audio.UPNP_OIC_URI_PREFIX_AUDIO)) {
Audio audio = new Audio();
audio.setUri(resourceUri);
// Update the device
MediaRenderer mediaRenderer = (MediaRenderer) mResourceLookup.get(mParentUri);
if (mediaRenderer != null) {
mediaRenderer.setAudio(audio);
mResourceLookup.put(resourceUri, audio);
tracked = true;
}
} else {
// Unexpected resource
Log.i(TAG, "URI of an unexpected resource: " + resourceUri);
......@@ -303,6 +327,20 @@ public class UpnpAvClientSelectRendererActivity extends Activity implements
Log.i(TAG, "Finding all resources of type " + rtAsString);
String requestUri = OcPlatform.WELL_KNOWN_QUERY + "?rt=" + rtAsString;
OcPlatform.findResource("", requestUri, EnumSet.of(OcConnectivityType.CT_DEFAULT), new ResourceFoundListener(ocRepUri, href));
if (rtAsString.equalsIgnoreCase(AvTransport.UPNP_OIC_TYPE_AV_TRANSPORT)) {
// also find new data model allegory