Added seekbar, send metadata.
This commit is contained in:
parent
e8ce9eb70a
commit
3ec4032105
2 changed files with 117 additions and 10 deletions
|
@ -11,12 +11,31 @@
|
||||||
android:layout_weight="1" >
|
android:layout_weight="1" >
|
||||||
</ListView>
|
</ListView>
|
||||||
|
|
||||||
<Button
|
<LinearLayout
|
||||||
android:id="@+id/playpause"
|
android:layout_width="match_parent"
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_weight="0"
|
android:layout_weight="0"
|
||||||
android:onClick="playPauseClicked"
|
android:orientation="vertical"
|
||||||
android:visibility="gone" />
|
android:id="@+id/controls"
|
||||||
|
android:visibility="gone" >
|
||||||
|
|
||||||
|
<SeekBar
|
||||||
|
android:id="@+id/progressBar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content" >
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/playpause"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:onClick="playPauseClicked" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
|
@ -17,12 +17,18 @@ import org.teleal.cling.model.state.StateVariableValue;
|
||||||
import org.teleal.cling.model.types.ServiceType;
|
import org.teleal.cling.model.types.ServiceType;
|
||||||
import org.teleal.cling.registry.Registry;
|
import org.teleal.cling.registry.Registry;
|
||||||
import org.teleal.cling.registry.RegistryListener;
|
import org.teleal.cling.registry.RegistryListener;
|
||||||
|
import org.teleal.cling.support.avtransport.callback.GetPositionInfo;
|
||||||
import org.teleal.cling.support.avtransport.callback.Play;
|
import org.teleal.cling.support.avtransport.callback.Play;
|
||||||
|
import org.teleal.cling.support.avtransport.callback.Seek;
|
||||||
import org.teleal.cling.support.avtransport.callback.SetAVTransportURI;
|
import org.teleal.cling.support.avtransport.callback.SetAVTransportURI;
|
||||||
import org.teleal.cling.support.avtransport.callback.Stop;
|
import org.teleal.cling.support.avtransport.callback.Stop;
|
||||||
import org.teleal.cling.support.avtransport.lastchange.AVTransportLastChangeParser;
|
import org.teleal.cling.support.avtransport.lastchange.AVTransportLastChangeParser;
|
||||||
import org.teleal.cling.support.avtransport.lastchange.AVTransportVariable;
|
import org.teleal.cling.support.avtransport.lastchange.AVTransportVariable;
|
||||||
|
import org.teleal.cling.support.contentdirectory.DIDLParser;
|
||||||
import org.teleal.cling.support.lastchange.LastChange;
|
import org.teleal.cling.support.lastchange.LastChange;
|
||||||
|
import org.teleal.cling.support.model.DIDLContent;
|
||||||
|
import org.teleal.cling.support.model.PositionInfo;
|
||||||
|
import org.teleal.cling.support.model.SeekMode;
|
||||||
import org.teleal.cling.support.model.item.Item;
|
import org.teleal.cling.support.model.item.Item;
|
||||||
|
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
|
@ -32,6 +38,7 @@ import android.content.DialogInterface;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.ServiceConnection;
|
import android.content.ServiceConnection;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.os.Handler;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.support.v4.app.Fragment;
|
import android.support.v4.app.Fragment;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
@ -43,6 +50,8 @@ import android.widget.AdapterView;
|
||||||
import android.widget.AdapterView.OnItemClickListener;
|
import android.widget.AdapterView.OnItemClickListener;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
import android.widget.ListView;
|
import android.widget.ListView;
|
||||||
|
import android.widget.SeekBar;
|
||||||
|
import android.widget.SeekBar.OnSeekBarChangeListener;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import com.github.nutomic.controldlna.MainActivity.OnBackPressedListener;
|
import com.github.nutomic.controldlna.MainActivity.OnBackPressedListener;
|
||||||
|
@ -54,12 +63,15 @@ import com.github.nutomic.controldlna.MainActivity.OnBackPressedListener;
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class RendererFragment extends Fragment implements
|
public class RendererFragment extends Fragment implements
|
||||||
OnBackPressedListener, OnItemClickListener, OnClickListener {
|
OnBackPressedListener, OnItemClickListener, OnClickListener,
|
||||||
|
OnSeekBarChangeListener {
|
||||||
|
|
||||||
private final String TAG = "RendererFragment";
|
private final String TAG = "RendererFragment";
|
||||||
|
|
||||||
private ListView mListView;
|
private ListView mListView;
|
||||||
|
|
||||||
|
private View mControls;
|
||||||
|
private SeekBar mProgressBar;
|
||||||
private Button mPlayPause;
|
private Button mPlayPause;
|
||||||
|
|
||||||
private boolean mPlaying = false;
|
private boolean mPlaying = false;
|
||||||
|
@ -199,6 +211,9 @@ public class RendererFragment extends Fragment implements
|
||||||
mListView = (ListView) getView().findViewById(R.id.listview);
|
mListView = (ListView) getView().findViewById(R.id.listview);
|
||||||
mListView.setAdapter(mRendererAdapter);
|
mListView.setAdapter(mRendererAdapter);
|
||||||
mListView.setOnItemClickListener(this);
|
mListView.setOnItemClickListener(this);
|
||||||
|
mControls = getView().findViewById(R.id.controls);
|
||||||
|
mProgressBar = (SeekBar) getView().findViewById(R.id.progressBar);
|
||||||
|
mProgressBar.setOnSeekBarChangeListener(this);
|
||||||
mPlayPause = (Button) getView().findViewById(R.id.playpause);
|
mPlayPause = (Button) getView().findViewById(R.id.playpause);
|
||||||
mPlayPause.setOnClickListener(this);
|
mPlayPause.setOnClickListener(this);
|
||||||
mPlayPause.setText(R.string.play);
|
mPlayPause.setText(R.string.play);
|
||||||
|
@ -210,6 +225,37 @@ public class RendererFragment extends Fragment implements
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void pollTimePosition() {
|
||||||
|
final Service<?, ?> service = mCurrentRenderer.findService(
|
||||||
|
new ServiceType("schemas-upnp-org", "AVTransport"));
|
||||||
|
mUpnpService.getControlPoint().execute(new GetPositionInfo(service) {
|
||||||
|
|
||||||
|
@SuppressWarnings("rawtypes")
|
||||||
|
@Override
|
||||||
|
public void failure(ActionInvocation invocation,
|
||||||
|
UpnpResponse operation, String defaultMessage) {
|
||||||
|
Log.w(TAG, "Get position failed: " + defaultMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("rawtypes")
|
||||||
|
@Override
|
||||||
|
public void received(ActionInvocation invocation, PositionInfo positionInfo) {
|
||||||
|
mProgressBar.setMax((int) positionInfo.getTrackDurationSeconds());
|
||||||
|
mProgressBar.setProgress((int) positionInfo.getTrackElapsedSeconds());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (mPlaying) {
|
||||||
|
new Handler().postDelayed(new Runnable() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
pollTimePosition();
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clears cached playback URI.
|
* Clears cached playback URI.
|
||||||
*/
|
*/
|
||||||
|
@ -247,8 +293,19 @@ public class RendererFragment extends Fragment implements
|
||||||
mListView.setAdapter(mPlaylistAdapter);
|
mListView.setAdapter(mPlaylistAdapter);
|
||||||
final Service<?, ?> service = mCurrentRenderer.findService(
|
final Service<?, ?> service = mCurrentRenderer.findService(
|
||||||
new ServiceType("schemas-upnp-org", "AVTransport"));
|
new ServiceType("schemas-upnp-org", "AVTransport"));
|
||||||
|
DIDLParser parser = new DIDLParser();
|
||||||
|
DIDLContent didl = new DIDLContent();
|
||||||
|
didl.addItem(mPlaylist[track]);
|
||||||
|
String metadata;
|
||||||
|
try {
|
||||||
|
metadata = parser.generate(didl, true);
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
Log.w(TAG, "Metadata serialization failed", e);
|
||||||
|
metadata = "NO METADATA";
|
||||||
|
}
|
||||||
mUpnpService.getControlPoint().execute(new SetAVTransportURI(service,
|
mUpnpService.getControlPoint().execute(new SetAVTransportURI(service,
|
||||||
mPlaylist[track].getFirstResource().getValue(), "NO METADATA") {
|
mPlaylist[track].getFirstResource().getValue(), metadata) {
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
@Override
|
@Override
|
||||||
public void failure(ActionInvocation invocation,
|
public void failure(ActionInvocation invocation,
|
||||||
|
@ -311,6 +368,7 @@ public class RendererFragment extends Fragment implements
|
||||||
public void run() {
|
public void run() {
|
||||||
mPlayPause.setText(R.string.pause);
|
mPlayPause.setText(R.string.pause);
|
||||||
mPlaying = true;
|
mPlaying = true;
|
||||||
|
pollTimePosition();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
|
@ -353,7 +411,7 @@ public class RendererFragment extends Fragment implements
|
||||||
}
|
}
|
||||||
|
|
||||||
mListView.setAdapter(mPlaylistAdapter);
|
mListView.setAdapter(mPlaylistAdapter);
|
||||||
mPlayPause.setVisibility(View.VISIBLE);
|
mControls.setVisibility(View.VISIBLE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -391,7 +449,7 @@ public class RendererFragment extends Fragment implements
|
||||||
mSubscriptionCallback.end();
|
mSubscriptionCallback.end();
|
||||||
|
|
||||||
mListView.setAdapter(mRendererAdapter);
|
mListView.setAdapter(mRendererAdapter);
|
||||||
mPlayPause.setVisibility(View.GONE);
|
mControls.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -451,4 +509,34 @@ public class RendererFragment extends Fragment implements
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends manual seek on progress bar to renderer.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void onProgressChanged(SeekBar seekBar, int progress,
|
||||||
|
boolean fromUser) {
|
||||||
|
if (fromUser) {
|
||||||
|
final Service<?, ?> service = mCurrentRenderer.findService(
|
||||||
|
new ServiceType("schemas-upnp-org", "AVTransport"));
|
||||||
|
mUpnpService.getControlPoint().execute(new Seek(service,
|
||||||
|
SeekMode.REL_TIME, Integer.toString(progress)) {
|
||||||
|
|
||||||
|
@SuppressWarnings("rawtypes")
|
||||||
|
@Override
|
||||||
|
public void failure(ActionInvocation invocation,
|
||||||
|
UpnpResponse operation, String defaultMessage) {
|
||||||
|
Log.w(TAG, "Seek failed: " + defaultMessage);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStartTrackingTouch(SeekBar seekBar) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onStopTrackingTouch(SeekBar seekBar) {
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Reference in a new issue