Formatting fixes.
- add braces to if/for - indent with tabs instead of spaces - remove trailing whitespaces
This commit is contained in:
parent
59df28b2bd
commit
105bb9de94
30 changed files with 980 additions and 913 deletions
|
@ -27,17 +27,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
package com.github.nutomic.controldlna.gui;
|
package com.github.nutomic.controldlna.gui;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.teleal.cling.support.model.item.Item;
|
|
||||||
|
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.net.ConnectivityManager;
|
|
||||||
import android.net.NetworkInfo;
|
|
||||||
import android.net.wifi.WifiManager;
|
import android.net.wifi.WifiManager;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
|
@ -50,17 +43,16 @@ import android.support.v7.app.ActionBar;
|
||||||
import android.support.v7.app.ActionBar.Tab;
|
import android.support.v7.app.ActionBar.Tab;
|
||||||
import android.support.v7.app.ActionBar.TabListener;
|
import android.support.v7.app.ActionBar.TabListener;
|
||||||
import android.support.v7.app.ActionBarActivity;
|
import android.support.v7.app.ActionBarActivity;
|
||||||
import android.util.Log;
|
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
|
||||||
import android.widget.CheckBox;
|
|
||||||
import android.widget.CompoundButton;
|
|
||||||
import android.widget.CompoundButton.OnCheckedChangeListener;
|
|
||||||
|
|
||||||
import com.github.nutomic.controldlna.R;
|
import com.github.nutomic.controldlna.R;
|
||||||
|
|
||||||
|
import org.teleal.cling.support.model.item.Item;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main activity, with tabs for media servers and media routes.
|
* Main activity, with tabs for media servers and media routes.
|
||||||
*
|
*
|
||||||
|
@ -114,8 +106,7 @@ public class MainActivity extends ActionBarActivity {
|
||||||
|
|
||||||
mViewPager = (ViewPager) findViewById(R.id.pager);
|
mViewPager = (ViewPager) findViewById(R.id.pager);
|
||||||
mViewPager.setAdapter(mSectionsPagerAdapter);
|
mViewPager.setAdapter(mSectionsPagerAdapter);
|
||||||
mViewPager.setOnPageChangeListener(
|
mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
|
||||||
new ViewPager.SimpleOnPageChangeListener() {
|
|
||||||
@Override
|
@Override
|
||||||
public void onPageSelected(int position) {
|
public void onPageSelected(int position) {
|
||||||
actionBar.setSelectedNavigationItem(position);
|
actionBar.setSelectedNavigationItem(position);
|
||||||
|
@ -204,7 +195,7 @@ public class MainActivity extends ActionBarActivity {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected void onNewIntent(Intent intent) {
|
protected void onNewIntent(Intent intent) {
|
||||||
if (intent.getAction().equals("showRouteFragment")) {
|
if (intent.getAction() != null && intent.getAction().equals("showRouteFragment")) {
|
||||||
mViewPager.setCurrentItem(1);
|
mViewPager.setCurrentItem(1);
|
||||||
mRouteFragment.scrollToCurrent();
|
mRouteFragment.scrollToCurrent();
|
||||||
}
|
}
|
||||||
|
@ -233,9 +224,10 @@ public class MainActivity extends ActionBarActivity {
|
||||||
public void onBackPressed() {
|
public void onBackPressed() {
|
||||||
OnBackPressedListener currentFragment = (OnBackPressedListener)
|
OnBackPressedListener currentFragment = (OnBackPressedListener)
|
||||||
mSectionsPagerAdapter.getItem(mViewPager.getCurrentItem());
|
mSectionsPagerAdapter.getItem(mViewPager.getCurrentItem());
|
||||||
if (!currentFragment.onBackPressed())
|
if (!currentFragment.onBackPressed()) {
|
||||||
super.onBackPressed();
|
super.onBackPressed();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Changes volume on key press (via RouteFragment).
|
* Changes volume on key press (via RouteFragment).
|
||||||
|
@ -244,12 +236,14 @@ public class MainActivity extends ActionBarActivity {
|
||||||
public boolean dispatchKeyEvent(KeyEvent event) {
|
public boolean dispatchKeyEvent(KeyEvent event) {
|
||||||
switch (event.getKeyCode()) {
|
switch (event.getKeyCode()) {
|
||||||
case KeyEvent.KEYCODE_VOLUME_UP:
|
case KeyEvent.KEYCODE_VOLUME_UP:
|
||||||
if (event.getAction() == KeyEvent.ACTION_DOWN)
|
if (event.getAction() == KeyEvent.ACTION_DOWN) {
|
||||||
mRouteFragment.increaseVolume();
|
mRouteFragment.increaseVolume();
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
case KeyEvent.KEYCODE_VOLUME_DOWN:
|
case KeyEvent.KEYCODE_VOLUME_DOWN:
|
||||||
if (event.getAction() == KeyEvent.ACTION_DOWN)
|
if (event.getAction() == KeyEvent.ACTION_DOWN) {
|
||||||
mRouteFragment.decreaseVolume();
|
mRouteFragment.decreaseVolume();
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return super.dispatchKeyEvent(event);
|
return super.dispatchKeyEvent(event);
|
||||||
|
|
|
@ -95,9 +95,8 @@ public class PreferencesActivity extends PreferenceActivity
|
||||||
public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen,
|
public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen,
|
||||||
Preference preference) {
|
Preference preference) {
|
||||||
if (preference == mContactDev) {
|
if (preference == mContactDev) {
|
||||||
Intent i = new Intent(Intent.ACTION_SENDTO, Uri.fromParts(
|
startActivity(new Intent(Intent.ACTION_SENDTO, Uri.fromParts(
|
||||||
"mailto", getString(R.string.contact_mail, "@", "."), null));
|
"mailto", getString(R.string.contact_mail, "@", "."), null)));
|
||||||
startActivity(i);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return super.onPreferenceTreeClick(preferenceScreen, preference);
|
return super.onPreferenceTreeClick(preferenceScreen, preference);
|
||||||
|
|
|
@ -27,10 +27,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
package com.github.nutomic.controldlna.gui;
|
package com.github.nutomic.controldlna.gui;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.teleal.cling.support.model.item.Item;
|
|
||||||
|
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
@ -49,7 +45,6 @@ import android.support.v7.media.MediaRouter;
|
||||||
import android.support.v7.media.MediaRouter.Callback;
|
import android.support.v7.media.MediaRouter.Callback;
|
||||||
import android.support.v7.media.MediaRouter.ProviderInfo;
|
import android.support.v7.media.MediaRouter.ProviderInfo;
|
||||||
import android.support.v7.media.MediaRouter.RouteInfo;
|
import android.support.v7.media.MediaRouter.RouteInfo;
|
||||||
import android.util.Log;
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.View.OnClickListener;
|
import android.view.View.OnClickListener;
|
||||||
|
@ -73,6 +68,10 @@ import com.github.nutomic.controldlna.mediarouter.MediaRouterPlayServiceBinder;
|
||||||
import com.github.nutomic.controldlna.utility.FileArrayAdapter;
|
import com.github.nutomic.controldlna.utility.FileArrayAdapter;
|
||||||
import com.github.nutomic.controldlna.utility.RouteAdapter;
|
import com.github.nutomic.controldlna.utility.RouteAdapter;
|
||||||
|
|
||||||
|
import org.teleal.cling.support.model.item.Item;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Controls media playback by showing a list of routes, and after selecting one,
|
* Controls media playback by showing a list of routes, and after selecting one,
|
||||||
* the current playlist and playback controls.
|
* the current playlist and playback controls.
|
||||||
|
@ -93,6 +92,7 @@ OnSeekBarChangeListener, OnScrollListener {
|
||||||
private ImageButton mRepeat;
|
private ImageButton mRepeat;
|
||||||
private TextView mCurrentTimeView;
|
private TextView mCurrentTimeView;
|
||||||
private TextView mTotalTimeView;
|
private TextView mTotalTimeView;
|
||||||
|
private TextView mEmptyView;
|
||||||
|
|
||||||
private View mCurrentTrackView;
|
private View mCurrentTrackView;
|
||||||
|
|
||||||
|
@ -126,9 +126,10 @@ OnSeekBarChangeListener, OnScrollListener {
|
||||||
mPlaylistAdapter.add(mMediaRouterPlayService.getPlaylist());
|
mPlaylistAdapter.add(mMediaRouterPlayService.getPlaylist());
|
||||||
applyColors();
|
applyColors();
|
||||||
RouteInfo currentRoute = mMediaRouterPlayService.getCurrentRoute();
|
RouteInfo currentRoute = mMediaRouterPlayService.getCurrentRoute();
|
||||||
if (currentRoute != null)
|
if (currentRoute != null) {
|
||||||
playlistMode(currentRoute);
|
playlistMode(currentRoute);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void onServiceDisconnected(ComponentName className) {
|
public void onServiceDisconnected(ComponentName className) {
|
||||||
mMediaRouterPlayService = null;
|
mMediaRouterPlayService = null;
|
||||||
|
@ -168,7 +169,9 @@ OnSeekBarChangeListener, OnScrollListener {
|
||||||
mListView.setAdapter(mRouteAdapter);
|
mListView.setAdapter(mRouteAdapter);
|
||||||
mListView.setOnItemClickListener(this);
|
mListView.setOnItemClickListener(this);
|
||||||
mListView.setOnScrollListener(this);
|
mListView.setOnScrollListener(this);
|
||||||
mListView.setEmptyView(getView().findViewById(android.R.id.empty));
|
|
||||||
|
mEmptyView = (TextView) getView().findViewById(android.R.id.empty);
|
||||||
|
mListView.setEmptyView(mEmptyView);
|
||||||
|
|
||||||
mControls = getView().findViewById(R.id.controls);
|
mControls = getView().findViewById(R.id.controls);
|
||||||
mProgressBar = (SeekBar) getView().findViewById(R.id.progressBar);
|
mProgressBar = (SeekBar) getView().findViewById(R.id.progressBar);
|
||||||
|
@ -201,19 +204,17 @@ OnSeekBarChangeListener, OnScrollListener {
|
||||||
new Intent(getActivity(), MediaRouterPlayService.class));
|
new Intent(getActivity(), MediaRouterPlayService.class));
|
||||||
getActivity().getApplicationContext().bindService(
|
getActivity().getApplicationContext().bindService(
|
||||||
new Intent(getActivity(), MediaRouterPlayService.class),
|
new Intent(getActivity(), MediaRouterPlayService.class),
|
||||||
mPlayServiceConnection,
|
mPlayServiceConnection, Context.BIND_AUTO_CREATE);
|
||||||
Context.BIND_AUTO_CREATE
|
|
||||||
);
|
|
||||||
|
|
||||||
if (savedInstanceState != null)
|
if (savedInstanceState != null) {
|
||||||
mListView.onRestoreInstanceState(savedInstanceState.getParcelable("list_state"));
|
mListView.onRestoreInstanceState(savedInstanceState.getParcelable("list_state"));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSaveInstanceState(Bundle outState) {
|
public void onSaveInstanceState(Bundle outState) {
|
||||||
super.onSaveInstanceState(outState);
|
super.onSaveInstanceState(outState);
|
||||||
|
|
||||||
//outState.putBoolean("route_selected", mSelectedRoute != null);
|
|
||||||
outState.putParcelable("list_state", mListView.onSaveInstanceState());
|
outState.putParcelable("list_state", mListView.onSaveInstanceState());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -229,8 +230,8 @@ OnSeekBarChangeListener, OnScrollListener {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int onPrepareCallbackFlags() {
|
public int onPrepareCallbackFlags() {
|
||||||
return MediaRouter.CALLBACK_FLAG_REQUEST_DISCOVERY
|
return MediaRouter.CALLBACK_FLAG_REQUEST_DISCOVERY |
|
||||||
| MediaRouter.CALLBACK_FLAG_PERFORM_ACTIVE_SCAN;
|
MediaRouter.CALLBACK_FLAG_PERFORM_ACTIVE_SCAN;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -238,17 +239,19 @@ OnSeekBarChangeListener, OnScrollListener {
|
||||||
return new MediaRouter.Callback() {
|
return new MediaRouter.Callback() {
|
||||||
@Override
|
@Override
|
||||||
public void onRouteAdded(MediaRouter router, RouteInfo route) {
|
public void onRouteAdded(MediaRouter router, RouteInfo route) {
|
||||||
for (int i = 0; i < mRouteAdapter.getCount(); i++)
|
for (int i = 0; i < mRouteAdapter.getCount(); i++) {
|
||||||
if (mRouteAdapter.getItem(i).getId().equals(route.getId())) {
|
if (mRouteAdapter.getItem(i).getId().equals(route.getId())) {
|
||||||
mRouteAdapter.remove(mRouteAdapter.getItem(i));
|
mRouteAdapter.remove(mRouteAdapter.getItem(i));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
mRouteAdapter.add(route);
|
mRouteAdapter.add(route);
|
||||||
|
|
||||||
RouteInfo current = mMediaRouterPlayService.getCurrentRoute();
|
RouteInfo current = mMediaRouterPlayService.getCurrentRoute();
|
||||||
if (current != null && route.getId().equals(current.getId()))
|
if (current != null && route.getId().equals(current.getId())) {
|
||||||
playlistMode(current);
|
playlistMode(current);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onRouteChanged(MediaRouter router, RouteInfo route) {
|
public void onRouteChanged(MediaRouter router, RouteInfo route) {
|
||||||
|
@ -301,8 +304,9 @@ OnSeekBarChangeListener, OnScrollListener {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void onItemClick(AdapterView<?> a, View v, final int position, long id) {
|
public void onItemClick(AdapterView<?> a, View v, final int position, long id) {
|
||||||
if (mListView.getAdapter() == mRouteAdapter)
|
if (mListView.getAdapter() == mRouteAdapter) {
|
||||||
playlistMode(mRouteAdapter.getItem(position));
|
playlistMode(mRouteAdapter.getItem(position));
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
mMediaRouterPlayService.play(position);
|
mMediaRouterPlayService.play(position);
|
||||||
changePlayPauseState(true);
|
changePlayPauseState(true);
|
||||||
|
@ -317,8 +321,7 @@ OnSeekBarChangeListener, OnScrollListener {
|
||||||
mListView.setAdapter(mRouteAdapter);
|
mListView.setAdapter(mRouteAdapter);
|
||||||
disableTrackHighlight();
|
disableTrackHighlight();
|
||||||
mSelectedRoute = null;
|
mSelectedRoute = null;
|
||||||
TextView emptyView = (TextView) mListView.getEmptyView();
|
mEmptyView.setText(R.string.route_list_empty);
|
||||||
emptyView.setText(R.string.route_list_empty);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -334,8 +337,7 @@ OnSeekBarChangeListener, OnScrollListener {
|
||||||
changePlayPauseState(true);
|
changePlayPauseState(true);
|
||||||
mStartPlayingOnSelect = -1;
|
mStartPlayingOnSelect = -1;
|
||||||
}
|
}
|
||||||
TextView emptyView = (TextView) mListView.getEmptyView();
|
mEmptyView.setText(R.string.playlist_empty);
|
||||||
emptyView.setText(R.string.playlist_empty);
|
|
||||||
mListView.post(new Runnable() {
|
mListView.post(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
|
@ -348,24 +350,27 @@ OnSeekBarChangeListener, OnScrollListener {
|
||||||
* Sets colored background on the item that is currently playing.
|
* Sets colored background on the item that is currently playing.
|
||||||
*/
|
*/
|
||||||
private void enableTrackHighlight() {
|
private void enableTrackHighlight() {
|
||||||
if (mListView.getAdapter() == mRouteAdapter || mMediaRouterPlayService == null || !isVisible())
|
if (mListView.getAdapter() == mRouteAdapter ||
|
||||||
|
mMediaRouterPlayService == null || !isVisible())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
disableTrackHighlight();
|
disableTrackHighlight();
|
||||||
mCurrentTrackView = mListView.getChildAt(mMediaRouterPlayService.getCurrentTrack()
|
mCurrentTrackView = mListView.getChildAt(mMediaRouterPlayService.getCurrentTrack()
|
||||||
- mListView.getFirstVisiblePosition() + mListView.getHeaderViewsCount());
|
- mListView.getFirstVisiblePosition() + mListView.getHeaderViewsCount());
|
||||||
if (mCurrentTrackView != null)
|
if (mCurrentTrackView != null) {
|
||||||
mCurrentTrackView.setBackgroundColor(
|
mCurrentTrackView.setBackgroundColor(
|
||||||
getResources().getColor(R.color.currently_playing_background));
|
getResources().getColor(R.color.currently_playing_background));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes highlight from the item that was last highlighted.
|
* Removes highlight from the item that was last highlighted.
|
||||||
*/
|
*/
|
||||||
private void disableTrackHighlight() {
|
private void disableTrackHighlight() {
|
||||||
if (mCurrentTrackView != null)
|
if (mCurrentTrackView != null) {
|
||||||
mCurrentTrackView.setBackgroundColor(Color.TRANSPARENT);
|
mCurrentTrackView.setBackgroundColor(Color.TRANSPARENT);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unselects current media renderer if one is selected (with dialog).
|
* Unselects current media renderer if one is selected (with dialog).
|
||||||
|
@ -373,12 +378,11 @@ OnSeekBarChangeListener, OnScrollListener {
|
||||||
@Override
|
@Override
|
||||||
public boolean onBackPressed() {
|
public boolean onBackPressed() {
|
||||||
if (mListView.getAdapter() == mPlaylistAdapter) {
|
if (mListView.getAdapter() == mPlaylistAdapter) {
|
||||||
if (mPlaying)
|
if (mPlaying) {
|
||||||
new AlertDialog.Builder(getActivity())
|
new AlertDialog.Builder(getActivity())
|
||||||
.setMessage(R.string.exit_renderer)
|
.setMessage(R.string.exit_renderer)
|
||||||
.setPositiveButton(android.R.string.yes,
|
.setPositiveButton(android.R.string.yes,
|
||||||
new DialogInterface.OnClickListener() {
|
new DialogInterface.OnClickListener() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onClick(DialogInterface dialog,
|
public void onClick(DialogInterface dialog,
|
||||||
int which) {
|
int which) {
|
||||||
|
@ -389,8 +393,10 @@ OnSeekBarChangeListener, OnScrollListener {
|
||||||
})
|
})
|
||||||
.setNegativeButton(android.R.string.no, null)
|
.setNegativeButton(android.R.string.no, null)
|
||||||
.show();
|
.show();
|
||||||
else
|
}
|
||||||
|
else {
|
||||||
deviceListMode();
|
deviceListMode();
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -470,9 +476,10 @@ OnSeekBarChangeListener, OnScrollListener {
|
||||||
@Override
|
@Override
|
||||||
public void onProgressChanged(SeekBar seekBar, int progress,
|
public void onProgressChanged(SeekBar seekBar, int progress,
|
||||||
boolean fromUser) {
|
boolean fromUser) {
|
||||||
if (fromUser)
|
if (fromUser) {
|
||||||
mMediaRouterPlayService.seek(progress);
|
mMediaRouterPlayService.seek(progress);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onStartTrackingTouch(SeekBar seekBar) {
|
public void onStartTrackingTouch(SeekBar seekBar) {
|
||||||
|
@ -514,7 +521,8 @@ OnSeekBarChangeListener, OnScrollListener {
|
||||||
if (mSelectedRoute != null) {
|
if (mSelectedRoute != null) {
|
||||||
mMediaRouterPlayService.play(start);
|
mMediaRouterPlayService.play(start);
|
||||||
changePlayPauseState(true);
|
changePlayPauseState(true);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
Toast.makeText(getActivity(), R.string.select_route, Toast.LENGTH_SHORT)
|
Toast.makeText(getActivity(), R.string.select_route, Toast.LENGTH_SHORT)
|
||||||
.show();
|
.show();
|
||||||
mStartPlayingOnSelect = start;
|
mStartPlayingOnSelect = start;
|
||||||
|
@ -528,17 +536,18 @@ OnSeekBarChangeListener, OnScrollListener {
|
||||||
* @return Formatted time string.
|
* @return Formatted time string.
|
||||||
*/
|
*/
|
||||||
private String generateTimeString(int time) {
|
private String generateTimeString(int time) {
|
||||||
assert(time >= 0);
|
|
||||||
int seconds = time % 60;
|
int seconds = time % 60;
|
||||||
int minutes = time / 60;
|
int minutes = time / 60;
|
||||||
if (minutes > 99)
|
if (minutes > 99) {
|
||||||
return "99:99";
|
return "99:99";
|
||||||
else
|
}
|
||||||
|
else {
|
||||||
return Integer.toString(minutes) + ":" +
|
return Integer.toString(minutes) + ":" +
|
||||||
((seconds > 9)
|
((seconds > 9)
|
||||||
? seconds
|
? seconds
|
||||||
: "0" + Integer.toString(seconds));
|
: "0" + Integer.toString(seconds));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Receives information from MediaRouterPlayService about playback status.
|
* Receives information from MediaRouterPlayService about playback status.
|
||||||
|
@ -559,14 +568,17 @@ OnSeekBarChangeListener, OnScrollListener {
|
||||||
|
|
||||||
if (status.getPlaybackState() == MediaItemStatus.PLAYBACK_STATE_PLAYING ||
|
if (status.getPlaybackState() == MediaItemStatus.PLAYBACK_STATE_PLAYING ||
|
||||||
status.getPlaybackState() == MediaItemStatus.PLAYBACK_STATE_BUFFERING ||
|
status.getPlaybackState() == MediaItemStatus.PLAYBACK_STATE_BUFFERING ||
|
||||||
status.getPlaybackState() == MediaItemStatus.PLAYBACK_STATE_PENDING)
|
status.getPlaybackState() == MediaItemStatus.PLAYBACK_STATE_PENDING) {
|
||||||
changePlayPauseState(true);
|
changePlayPauseState(true);
|
||||||
else
|
}
|
||||||
|
else {
|
||||||
changePlayPauseState(false);
|
changePlayPauseState(false);
|
||||||
|
}
|
||||||
|
|
||||||
if (mListView.getAdapter() == mPlaylistAdapter)
|
if (mListView.getAdapter() == mPlaylistAdapter) {
|
||||||
enableTrackHighlight();
|
enableTrackHighlight();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Changes the state of mPlayPause button to pause/resume according to
|
* Changes the state of mPlayPause button to pause/resume according to
|
||||||
|
|
|
@ -27,24 +27,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
package com.github.nutomic.controldlna.gui;
|
package com.github.nutomic.controldlna.gui;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Stack;
|
|
||||||
|
|
||||||
import org.teleal.cling.android.AndroidUpnpService;
|
|
||||||
import org.teleal.cling.android.AndroidUpnpServiceImpl;
|
|
||||||
import org.teleal.cling.model.action.ActionInvocation;
|
|
||||||
import org.teleal.cling.model.message.UpnpResponse;
|
|
||||||
import org.teleal.cling.model.meta.Device;
|
|
||||||
import org.teleal.cling.model.meta.Service;
|
|
||||||
import org.teleal.cling.model.types.ServiceType;
|
|
||||||
import org.teleal.cling.model.types.UDN;
|
|
||||||
import org.teleal.cling.support.contentdirectory.callback.Browse;
|
|
||||||
import org.teleal.cling.support.model.BrowseFlag;
|
|
||||||
import org.teleal.cling.support.model.DIDLContent;
|
|
||||||
import org.teleal.cling.support.model.container.Container;
|
|
||||||
import org.teleal.cling.support.model.item.Item;
|
|
||||||
|
|
||||||
import android.content.BroadcastReceiver;
|
import android.content.BroadcastReceiver;
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
@ -70,6 +52,24 @@ import com.github.nutomic.controldlna.gui.MainActivity.OnBackPressedListener;
|
||||||
import com.github.nutomic.controldlna.utility.DeviceArrayAdapter;
|
import com.github.nutomic.controldlna.utility.DeviceArrayAdapter;
|
||||||
import com.github.nutomic.controldlna.utility.FileArrayAdapter;
|
import com.github.nutomic.controldlna.utility.FileArrayAdapter;
|
||||||
|
|
||||||
|
import org.teleal.cling.android.AndroidUpnpService;
|
||||||
|
import org.teleal.cling.android.AndroidUpnpServiceImpl;
|
||||||
|
import org.teleal.cling.model.action.ActionInvocation;
|
||||||
|
import org.teleal.cling.model.message.UpnpResponse;
|
||||||
|
import org.teleal.cling.model.meta.Device;
|
||||||
|
import org.teleal.cling.model.meta.Service;
|
||||||
|
import org.teleal.cling.model.types.ServiceType;
|
||||||
|
import org.teleal.cling.model.types.UDN;
|
||||||
|
import org.teleal.cling.support.contentdirectory.callback.Browse;
|
||||||
|
import org.teleal.cling.support.model.BrowseFlag;
|
||||||
|
import org.teleal.cling.support.model.DIDLContent;
|
||||||
|
import org.teleal.cling.support.model.container.Container;
|
||||||
|
import org.teleal.cling.support.model.item.Item;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Stack;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shows a list of media servers, upon selecting one, allows browsing their
|
* Shows a list of media servers, upon selecting one, allows browsing their
|
||||||
* directories.
|
* directories.
|
||||||
|
@ -107,6 +107,8 @@ public class ServerFragment extends ListFragment implements OnBackPressedListene
|
||||||
*/
|
*/
|
||||||
private Stack<String> mCurrentPath = new Stack<String>();
|
private Stack<String> mCurrentPath = new Stack<String>();
|
||||||
|
|
||||||
|
private TextView mEmptyView;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds the scroll position in the list view at each directory level.
|
* Holds the scroll position in the list view at each directory level.
|
||||||
*/
|
*/
|
||||||
|
@ -148,7 +150,6 @@ public class ServerFragment extends ListFragment implements OnBackPressedListene
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||||
Bundle savedInstanceState) {
|
Bundle savedInstanceState) {
|
||||||
|
|
||||||
return inflater.inflate(R.layout.server_fragment, null);
|
return inflater.inflate(R.layout.server_fragment, null);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -166,22 +167,24 @@ public class ServerFragment extends ListFragment implements OnBackPressedListene
|
||||||
setListAdapter(mServerAdapter);
|
setListAdapter(mServerAdapter);
|
||||||
getActivity().getApplicationContext().bindService(
|
getActivity().getApplicationContext().bindService(
|
||||||
new Intent(getActivity(), AndroidUpnpServiceImpl.class),
|
new Intent(getActivity(), AndroidUpnpServiceImpl.class),
|
||||||
mUpnpServiceConnection,
|
mUpnpServiceConnection, Context.BIND_AUTO_CREATE);
|
||||||
Context.BIND_AUTO_CREATE
|
|
||||||
);
|
|
||||||
|
|
||||||
IntentFilter filter = new IntentFilter();
|
IntentFilter filter = new IntentFilter();
|
||||||
filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
|
filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
|
||||||
filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
|
filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
|
||||||
getActivity().registerReceiver(mWifiReceiver, filter);
|
getActivity().registerReceiver(mWifiReceiver, filter);
|
||||||
|
|
||||||
|
mEmptyView = (TextView) getListView().getEmptyView();
|
||||||
|
|
||||||
if (savedInstanceState != null) {
|
if (savedInstanceState != null) {
|
||||||
mRestoreServer = savedInstanceState.getString("current_server");
|
mRestoreServer = savedInstanceState.getString("current_server");
|
||||||
mCurrentPath.addAll(savedInstanceState.getStringArrayList("path"));
|
mCurrentPath.addAll(savedInstanceState.getStringArrayList("path"));
|
||||||
mListState.addAll(savedInstanceState.getParcelableArrayList("list_state"));
|
mListState.addAll(savedInstanceState.getParcelableArrayList("list_state"));
|
||||||
} else
|
}
|
||||||
|
else {
|
||||||
mListState.push(getListView().onSaveInstanceState());
|
mListState.push(getListView().onSaveInstanceState());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores current server and path/list state stacks.
|
* Stores current server and path/list state stacks.
|
||||||
|
@ -210,20 +213,24 @@ public class ServerFragment extends ListFragment implements OnBackPressedListene
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void onListItemClick(ListView l, View v, int position, long id) {
|
public void onListItemClick(ListView l, View v, int position, long id) {
|
||||||
if (getListAdapter() == mServerAdapter)
|
if (getListAdapter() == mServerAdapter) {
|
||||||
browsingMode(mServerAdapter.getItem(position));
|
browsingMode(mServerAdapter.getItem(position));
|
||||||
else if (getListAdapter() == mFileAdapter)
|
}
|
||||||
|
else if (getListAdapter() == mFileAdapter) {
|
||||||
if (mFileAdapter.getItem(position) instanceof Container)
|
if (mFileAdapter.getItem(position) instanceof Container)
|
||||||
getFiles(((Container) mFileAdapter.getItem(position)).getId());
|
getFiles(((Container) mFileAdapter.getItem(position)).getId());
|
||||||
else {
|
else {
|
||||||
List<Item> playlist = new ArrayList<Item>();
|
List<Item> playlist = new ArrayList<Item>();
|
||||||
for (int i = 0; i < mFileAdapter.getCount(); i++)
|
for (int i = 0; i < mFileAdapter.getCount(); i++) {
|
||||||
if (mFileAdapter.getItem(i) instanceof Item)
|
if (mFileAdapter.getItem(i) instanceof Item) {
|
||||||
playlist.add((Item) mFileAdapter.getItem(i));
|
playlist.add((Item) mFileAdapter.getItem(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
MainActivity activity = (MainActivity) getActivity();
|
MainActivity activity = (MainActivity) getActivity();
|
||||||
activity.play(playlist, position);
|
activity.play(playlist, position);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Displays available servers in the ListView.
|
* Displays available servers in the ListView.
|
||||||
|
@ -231,8 +238,7 @@ public class ServerFragment extends ListFragment implements OnBackPressedListene
|
||||||
private void serverMode() {
|
private void serverMode() {
|
||||||
setListAdapter(mServerAdapter);
|
setListAdapter(mServerAdapter);
|
||||||
mCurrentServer = null;
|
mCurrentServer = null;
|
||||||
TextView emptyView = (TextView) getListView().getEmptyView();
|
mEmptyView.setText(R.string.device_list_empty);
|
||||||
emptyView.setText(R.string.device_list_empty);
|
|
||||||
getListView().onRestoreInstanceState(mListState.pop());
|
getListView().onRestoreInstanceState(mListState.pop());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -243,8 +249,7 @@ public class ServerFragment extends ListFragment implements OnBackPressedListene
|
||||||
setListAdapter(mFileAdapter);
|
setListAdapter(mFileAdapter);
|
||||||
mCurrentServer = server;
|
mCurrentServer = server;
|
||||||
getFiles(ROOT_DIRECTORY);
|
getFiles(ROOT_DIRECTORY);
|
||||||
TextView emptyView = (TextView) getListView().getEmptyView();
|
mEmptyView.setText(R.string.folder_list_empty);
|
||||||
emptyView.setText(R.string.folder_list_empty);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -281,15 +286,19 @@ public class ServerFragment extends ListFragment implements OnBackPressedListene
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
mFileAdapter.clear();
|
mFileAdapter.clear();
|
||||||
for (Container c : didl.getContainers())
|
for (Container c : didl.getContainers()) {
|
||||||
mFileAdapter.add(c);
|
mFileAdapter.add(c);
|
||||||
for (Item i : didl.getItems())
|
}
|
||||||
|
for (Item i : didl.getItems()) {
|
||||||
mFileAdapter.add(i);
|
mFileAdapter.add(i);
|
||||||
if (restoreListState)
|
}
|
||||||
|
if (restoreListState) {
|
||||||
getListView().onRestoreInstanceState(mListState.pop());
|
getListView().onRestoreInstanceState(mListState.pop());
|
||||||
else
|
}
|
||||||
|
else {
|
||||||
getListView().setSelectionFromTop(0, 0);
|
getListView().setSelectionFromTop(0, 0);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -317,10 +326,12 @@ public class ServerFragment extends ListFragment implements OnBackPressedListene
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
mCurrentPath.pop();
|
mCurrentPath.pop();
|
||||||
if (mCurrentPath.empty())
|
if (mCurrentPath.empty()) {
|
||||||
serverMode();
|
serverMode();
|
||||||
else
|
}
|
||||||
|
else {
|
||||||
getFiles(true);
|
getFiles(true);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -340,11 +351,13 @@ public class ServerFragment extends ListFragment implements OnBackPressedListene
|
||||||
if (wifi.isConnected()) {
|
if (wifi.isConnected()) {
|
||||||
if (mUpnpService != null) {
|
if (mUpnpService != null) {
|
||||||
for (Device<?, ?, ?> d : mUpnpService.getControlPoint()
|
for (Device<?, ?, ?> d : mUpnpService.getControlPoint()
|
||||||
.getRegistry().getDevices())
|
.getRegistry().getDevices()) {
|
||||||
mServerAdapter.deviceAdded(d);
|
mServerAdapter.deviceAdded(d);
|
||||||
|
}
|
||||||
mUpnpService.getControlPoint().search();
|
mUpnpService.getControlPoint().search();
|
||||||
}
|
}
|
||||||
} else
|
}
|
||||||
|
else {
|
||||||
for (int i = 0; i < mServerAdapter.getCount(); i++) {
|
for (int i = 0; i < mServerAdapter.getCount(); i++) {
|
||||||
Device<?, ?, ?> d = mServerAdapter.getItem(i);
|
Device<?, ?, ?> d = mServerAdapter.getItem(i);
|
||||||
UDN udn = new UDN(d.getIdentity().getUdn().toString());
|
UDN udn = new UDN(d.getIdentity().getUdn().toString());
|
||||||
|
@ -359,6 +372,7 @@ public class ServerFragment extends ListFragment implements OnBackPressedListene
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,8 +27,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
package com.github.nutomic.controldlna.localroute;
|
package com.github.nutomic.controldlna.localroute;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.media.AudioManager;
|
import android.media.AudioManager;
|
||||||
|
@ -41,6 +39,8 @@ import android.support.v7.media.MediaRouteProvider;
|
||||||
import android.support.v7.media.MediaRouter.ControlRequestCallback;
|
import android.support.v7.media.MediaRouter.ControlRequestCallback;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Receives control intents through media route and executes them on a MediaPlayer.
|
* Receives control intents through media route and executes them on a MediaPlayer.
|
||||||
*
|
*
|
||||||
|
@ -114,10 +114,12 @@ public class Controller extends MediaRouteProvider.RouteController implements
|
||||||
mState = MediaItemStatus.PLAYBACK_STATE_BUFFERING;
|
mState = MediaItemStatus.PLAYBACK_STATE_BUFFERING;
|
||||||
getStatus(mItemId, mRouteId, callback);
|
getStatus(mItemId, mRouteId, callback);
|
||||||
return true;
|
return true;
|
||||||
} catch (IllegalArgumentException e) {
|
}
|
||||||
|
catch (IllegalArgumentException e) {
|
||||||
mState = MediaItemStatus.PLAYBACK_STATE_ERROR;
|
mState = MediaItemStatus.PLAYBACK_STATE_ERROR;
|
||||||
Log.d(TAG, "Failed to start playback", e);
|
Log.d(TAG, "Failed to start playback", e);
|
||||||
} catch (IOException e) {
|
}
|
||||||
|
catch (IOException e) {
|
||||||
mState = MediaItemStatus.PLAYBACK_STATE_ERROR;
|
mState = MediaItemStatus.PLAYBACK_STATE_ERROR;
|
||||||
Log.d(TAG, "Failed to start playback", e);
|
Log.d(TAG, "Failed to start playback", e);
|
||||||
}
|
}
|
||||||
|
@ -161,14 +163,16 @@ public class Controller extends MediaRouteProvider.RouteController implements
|
||||||
.setContentPosition(mPlayer.getCurrentPosition())
|
.setContentPosition(mPlayer.getCurrentPosition())
|
||||||
.setContentDuration(mPlayer.getDuration())
|
.setContentDuration(mPlayer.getDuration())
|
||||||
.setTimestamp(SystemClock.elapsedRealtime())
|
.setTimestamp(SystemClock.elapsedRealtime())
|
||||||
.build().asBundle();
|
.build()
|
||||||
|
.asBundle();
|
||||||
|
|
||||||
status.putString(MediaControlIntent.EXTRA_SESSION_ID, mRouteId);
|
status.putString(MediaControlIntent.EXTRA_SESSION_ID, mRouteId);
|
||||||
status.putString(MediaControlIntent.EXTRA_ITEM_ID, mItemId);
|
status.putString(MediaControlIntent.EXTRA_ITEM_ID, mItemId);
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
status = new MediaItemStatus.Builder(MediaItemStatus.PLAYBACK_STATE_INVALIDATED)
|
status = new MediaItemStatus.Builder(MediaItemStatus.PLAYBACK_STATE_INVALIDATED)
|
||||||
.build().asBundle();
|
.build().asBundle();
|
||||||
|
}
|
||||||
|
|
||||||
callback.onResult(status);
|
callback.onResult(status);
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,7 +74,8 @@ final class Provider extends MediaRouteProvider {
|
||||||
private static void addDataTypeUnchecked(IntentFilter filter, String type) {
|
private static void addDataTypeUnchecked(IntentFilter filter, String type) {
|
||||||
try {
|
try {
|
||||||
filter.addDataType(type);
|
filter.addDataType(type);
|
||||||
} catch (MalformedMimeTypeException ex) {
|
}
|
||||||
|
catch (MalformedMimeTypeException ex) {
|
||||||
throw new RuntimeException(ex);
|
throw new RuntimeException(ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,8 +36,9 @@ public class ProviderService extends MediaRouteProviderService {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MediaRouteProvider onCreateMediaRouteProvider() {
|
public MediaRouteProvider onCreateMediaRouteProvider() {
|
||||||
if (mProvider == null)
|
if (mProvider == null) {
|
||||||
mProvider = new Provider(this);
|
mProvider = new Provider(this);
|
||||||
|
}
|
||||||
return mProvider;
|
return mProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,17 +27,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
package com.github.nutomic.controldlna.mediarouter;
|
package com.github.nutomic.controldlna.mediarouter;
|
||||||
|
|
||||||
import java.lang.ref.WeakReference;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Random;
|
|
||||||
|
|
||||||
import org.teleal.cling.support.contentdirectory.DIDLParser;
|
|
||||||
import org.teleal.cling.support.model.DIDLContent;
|
|
||||||
import org.teleal.cling.support.model.DIDLObject;
|
|
||||||
import org.teleal.cling.support.model.item.Item;
|
|
||||||
import org.teleal.cling.support.model.item.MusicTrack;
|
|
||||||
|
|
||||||
import android.app.Notification;
|
import android.app.Notification;
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
import android.app.Service;
|
import android.app.Service;
|
||||||
|
@ -66,6 +55,17 @@ import com.github.nutomic.controldlna.gui.PreferencesActivity;
|
||||||
import com.github.nutomic.controldlna.gui.RouteFragment;
|
import com.github.nutomic.controldlna.gui.RouteFragment;
|
||||||
import com.github.nutomic.controldlna.utility.LoadImageTask;
|
import com.github.nutomic.controldlna.utility.LoadImageTask;
|
||||||
|
|
||||||
|
import org.teleal.cling.support.contentdirectory.DIDLParser;
|
||||||
|
import org.teleal.cling.support.model.DIDLContent;
|
||||||
|
import org.teleal.cling.support.model.DIDLObject;
|
||||||
|
import org.teleal.cling.support.model.item.Item;
|
||||||
|
import org.teleal.cling.support.model.item.MusicTrack;
|
||||||
|
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Background service that handles media playback to a single UPNP media renderer.
|
* Background service that handles media playback to a single UPNP media renderer.
|
||||||
*
|
*
|
||||||
|
@ -120,12 +120,14 @@ public class MediaRouterPlayService extends Service {
|
||||||
new MediaRouter.Callback() {
|
new MediaRouter.Callback() {
|
||||||
@Override
|
@Override
|
||||||
public void onRouteRemoved(MediaRouter router, RouteInfo route) {
|
public void onRouteRemoved(MediaRouter router, RouteInfo route) {
|
||||||
if (route.equals(mCurrentRoute))
|
if (route.equals(mCurrentRoute)) {
|
||||||
stopForeground(true);
|
stopForeground(true);
|
||||||
|
}
|
||||||
|
|
||||||
if (!mBound && !mPollingStatus)
|
if (!mBound && !mPollingStatus) {
|
||||||
stopSelf();
|
stopSelf();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onRouteAdded(MediaRouter router, RouteInfo route) {
|
public void onRouteAdded(MediaRouter router, RouteInfo route) {
|
||||||
|
@ -150,10 +152,11 @@ public class MediaRouterPlayService extends Service {
|
||||||
title = mPlaylist.get(mCurrentTrack).getTitle();
|
title = mPlaylist.get(mCurrentTrack).getTitle();
|
||||||
if (mPlaylist.get(mCurrentTrack) instanceof MusicTrack) {
|
if (mPlaylist.get(mCurrentTrack) instanceof MusicTrack) {
|
||||||
MusicTrack track = (MusicTrack) mPlaylist.get(mCurrentTrack);
|
MusicTrack track = (MusicTrack) mPlaylist.get(mCurrentTrack);
|
||||||
if (track.getArtists().length > 0)
|
if (track.getArtists().length > 0) {
|
||||||
artist = track.getArtists()[0].getName();
|
artist = track.getArtists()[0].getName();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
Intent intent = new Intent(MediaRouterPlayService.this, MainActivity.class);
|
Intent intent = new Intent(MediaRouterPlayService.this, MainActivity.class);
|
||||||
intent.setAction("showRouteFragment");
|
intent.setAction("showRouteFragment");
|
||||||
Notification notification = new NotificationCompat.Builder(MediaRouterPlayService.this)
|
Notification notification = new NotificationCompat.Builder(MediaRouterPlayService.this)
|
||||||
|
@ -207,10 +210,9 @@ public class MediaRouterPlayService extends Service {
|
||||||
pollStatus();
|
pollStatus();
|
||||||
|
|
||||||
PhoneCallListener phoneListener = new PhoneCallListener();
|
PhoneCallListener phoneListener = new PhoneCallListener();
|
||||||
TelephonyManager telephonyManager = (TelephonyManager) this
|
TelephonyManager telephonyManager =
|
||||||
.getSystemService(Context.TELEPHONY_SERVICE);
|
(TelephonyManager) this.getSystemService(Context.TELEPHONY_SERVICE);
|
||||||
telephonyManager.listen(phoneListener,
|
telephonyManager.listen(phoneListener, PhoneStateListener.LISTEN_CALL_STATE);
|
||||||
PhoneStateListener.LISTEN_CALL_STATE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -225,8 +227,9 @@ public class MediaRouterPlayService extends Service {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean onUnbind(Intent intent) {
|
public boolean onUnbind(Intent intent) {
|
||||||
if (!mPollingStatus)
|
if (!mPollingStatus) {
|
||||||
stopSelf();
|
stopSelf();
|
||||||
|
}
|
||||||
mBound = false;
|
mBound = false;
|
||||||
return super.onUnbind(intent);
|
return super.onUnbind(intent);
|
||||||
}
|
}
|
||||||
|
@ -287,9 +290,10 @@ public class MediaRouterPlayService extends Service {
|
||||||
new CreateNotificationTask().execute(mPlaylist.get(mCurrentTrack)
|
new CreateNotificationTask().execute(mPlaylist.get(mCurrentTrack)
|
||||||
.getFirstPropertyValue(DIDLObject.Property.UPNP.ALBUM_ART_URI.class));
|
.getFirstPropertyValue(DIDLObject.Property.UPNP.ALBUM_ART_URI.class));
|
||||||
|
|
||||||
if (mRouterFragment.get() != null)
|
if (mRouterFragment.get() != null) {
|
||||||
mRouterFragment.get().scrollToCurrent();
|
mRouterFragment.get().scrollToCurrent();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -347,8 +351,7 @@ public class MediaRouterPlayService extends Service {
|
||||||
intent.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK);
|
intent.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK);
|
||||||
intent.putExtra(MediaControlIntent.EXTRA_SESSION_ID, mSessionId);
|
intent.putExtra(MediaControlIntent.EXTRA_SESSION_ID, mSessionId);
|
||||||
intent.putExtra(MediaControlIntent.EXTRA_ITEM_ID, mItemId);
|
intent.putExtra(MediaControlIntent.EXTRA_ITEM_ID, mItemId);
|
||||||
intent.putExtra(MediaControlIntent.EXTRA_ITEM_CONTENT_POSITION,
|
intent.putExtra(MediaControlIntent.EXTRA_ITEM_CONTENT_POSITION, (long) seconds * 1000);
|
||||||
(long) seconds * 1000);
|
|
||||||
mMediaRouter.getSelectedRoute().sendControlRequest(intent, null);
|
mMediaRouter.getSelectedRoute().sendControlRequest(intent, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -358,6 +361,9 @@ public class MediaRouterPlayService extends Service {
|
||||||
* @param playlist The media files in the playlist.
|
* @param playlist The media files in the playlist.
|
||||||
*/
|
*/
|
||||||
public void setPlaylist(List<Item> playlist) {
|
public void setPlaylist(List<Item> playlist) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
mPlaylist = playlist;
|
mPlaylist = playlist;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -389,8 +395,9 @@ public class MediaRouterPlayService extends Service {
|
||||||
else {
|
else {
|
||||||
// Playlist over, stop playback.
|
// Playlist over, stop playback.
|
||||||
stop();
|
stop();
|
||||||
if (!mBound)
|
if (!mBound) {
|
||||||
stopSelf();
|
stopSelf();
|
||||||
|
}
|
||||||
mPollingStatus = false;
|
mPollingStatus = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -404,12 +411,14 @@ public class MediaRouterPlayService extends Service {
|
||||||
if (mCurrentTrack == -1)
|
if (mCurrentTrack == -1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (mShuffle)
|
if (mShuffle) {
|
||||||
// Play random item.
|
// Play random item.
|
||||||
play(new Random().nextInt(mPlaylist.size()));
|
play(new Random().nextInt(mPlaylist.size()));
|
||||||
else
|
}
|
||||||
|
else {
|
||||||
play(mCurrentTrack - 1);
|
play(mCurrentTrack - 1);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns index of the track that is currently played (zero-based).
|
* Returns index of the track that is currently played (zero-based).
|
||||||
|
@ -437,17 +446,20 @@ public class MediaRouterPlayService extends Service {
|
||||||
if (status == null)
|
if (status == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (mRouterFragment.get() != null)
|
if (mRouterFragment.get() != null) {
|
||||||
mRouterFragment.get().receivePlaybackStatus(status);
|
mRouterFragment.get().receivePlaybackStatus(status);
|
||||||
|
}
|
||||||
if (status.getPlaybackState() != MediaItemStatus.PLAYBACK_STATE_PENDING &&
|
if (status.getPlaybackState() != MediaItemStatus.PLAYBACK_STATE_PENDING &&
|
||||||
status.getPlaybackState() != MediaItemStatus.PLAYBACK_STATE_BUFFERING &&
|
status.getPlaybackState() != MediaItemStatus.PLAYBACK_STATE_BUFFERING &&
|
||||||
status.getPlaybackState() != MediaItemStatus.PLAYBACK_STATE_PLAYING)
|
status.getPlaybackState() != MediaItemStatus.PLAYBACK_STATE_PLAYING) {
|
||||||
stopForeground(true);
|
stopForeground(true);
|
||||||
|
}
|
||||||
|
|
||||||
if (status.getPlaybackState() == MediaItemStatus.PLAYBACK_STATE_FINISHED ||
|
if (status.getPlaybackState() == MediaItemStatus.PLAYBACK_STATE_FINISHED ||
|
||||||
status.getPlaybackState() == MediaItemStatus.PLAYBACK_STATE_CANCELED)
|
status.getPlaybackState() == MediaItemStatus.PLAYBACK_STATE_CANCELED) {
|
||||||
playNext();
|
playNext();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,12 +27,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
package com.github.nutomic.controldlna.upnp;
|
package com.github.nutomic.controldlna.upnp;
|
||||||
|
|
||||||
import java.lang.ref.WeakReference;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map.Entry;
|
|
||||||
import java.util.Random;
|
|
||||||
|
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
|
@ -54,10 +48,17 @@ import android.support.v7.media.MediaRouteProvider;
|
||||||
import android.support.v7.media.MediaRouteProviderDescriptor.Builder;
|
import android.support.v7.media.MediaRouteProviderDescriptor.Builder;
|
||||||
import android.support.v7.media.MediaRouter;
|
import android.support.v7.media.MediaRouter;
|
||||||
import android.support.v7.media.MediaRouter.ControlRequestCallback;
|
import android.support.v7.media.MediaRouter.ControlRequestCallback;
|
||||||
|
import android.util.Log;
|
||||||
import android.util.Pair;
|
import android.util.Pair;
|
||||||
import android.util.SparseArray;
|
import android.util.SparseArray;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allows playing to a DLNA renderer from a remote app.
|
* Allows playing to a DLNA renderer from a remote app.
|
||||||
*
|
*
|
||||||
|
@ -65,6 +66,8 @@ import android.widget.Toast;
|
||||||
*/
|
*/
|
||||||
final class Provider extends MediaRouteProvider {
|
final class Provider extends MediaRouteProvider {
|
||||||
|
|
||||||
|
private static final String TAG = "Provider";
|
||||||
|
|
||||||
// Device has been added.
|
// Device has been added.
|
||||||
// param: Device device
|
// param: Device device
|
||||||
public static final int MSG_RENDERER_ADDED = 1;
|
public static final int MSG_RENDERER_ADDED = 1;
|
||||||
|
@ -93,8 +96,8 @@ final class Provider extends MediaRouteProvider {
|
||||||
public int volume;
|
public int volume;
|
||||||
public int volumeMax;
|
public int volumeMax;
|
||||||
|
|
||||||
public static final Parcelable.Creator<Device> CREATOR
|
public static final Parcelable.Creator<Device> CREATOR =
|
||||||
= new Parcelable.Creator<Device>() {
|
new Parcelable.Creator<Device>() {
|
||||||
public Device createFromParcel(Parcel in) {
|
public Device createFromParcel(Parcel in) {
|
||||||
return new Device(in);
|
return new Device(in);
|
||||||
}
|
}
|
||||||
|
@ -187,20 +190,18 @@ final class Provider extends MediaRouteProvider {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleMessage(Message msg) {
|
public void handleMessage(Message msg) {
|
||||||
if (mService.get() != null)
|
if (mService.get() != null) {
|
||||||
mService.get().handleMessage(msg);
|
mService.get().handleMessage(msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
final Messenger mListener = new Messenger(new DeviceListener(this));
|
final Messenger mListener = new Messenger(new DeviceListener(this));
|
||||||
|
|
||||||
public Provider(Context context) {
|
public Provider(Context context) {
|
||||||
super(context);
|
super(context);
|
||||||
context.bindService(
|
context.bindService(new Intent(context, RemotePlayService.class),
|
||||||
new Intent(context, RemotePlayService.class),
|
mConnection, Context.BIND_AUTO_CREATE);
|
||||||
mConnection,
|
|
||||||
Context.BIND_AUTO_CREATE
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void close() {
|
public void close() {
|
||||||
|
@ -210,9 +211,11 @@ final class Provider extends MediaRouteProvider {
|
||||||
@Override
|
@Override
|
||||||
public void onDiscoveryRequestChanged(MediaRouteDiscoveryRequest request) {
|
public void onDiscoveryRequestChanged(MediaRouteDiscoveryRequest request) {
|
||||||
try {
|
try {
|
||||||
if (request != null && request.isActiveScan() && mIRemotePlayService != null)
|
if (request != null && request.isActiveScan() && mIRemotePlayService != null) {
|
||||||
mIRemotePlayService.startSearch(mListener);
|
mIRemotePlayService.startSearch(mListener);
|
||||||
} catch (RemoteException e) {
|
}
|
||||||
|
}
|
||||||
|
catch (RemoteException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -259,7 +262,8 @@ final class Provider extends MediaRouteProvider {
|
||||||
public void onSelect() {
|
public void onSelect() {
|
||||||
try {
|
try {
|
||||||
mIRemotePlayService.selectRenderer(mRouteId);
|
mIRemotePlayService.selectRenderer(mRouteId);
|
||||||
} catch (RemoteException e) {
|
}
|
||||||
|
catch (RemoteException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -268,7 +272,8 @@ final class Provider extends MediaRouteProvider {
|
||||||
public void onUnselect() {
|
public void onUnselect() {
|
||||||
try {
|
try {
|
||||||
mIRemotePlayService.unselectRenderer(mRouteId);
|
mIRemotePlayService.unselectRenderer(mRouteId);
|
||||||
} catch (RemoteException e) {
|
}
|
||||||
|
catch (RemoteException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -280,7 +285,8 @@ final class Provider extends MediaRouteProvider {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
mIRemotePlayService.setVolume(volume);
|
mIRemotePlayService.setVolume(volume);
|
||||||
} catch (RemoteException e) {
|
}
|
||||||
|
catch (RemoteException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
mDevices.get(mRouteId).volume = volume;
|
mDevices.get(mRouteId).volume = volume;
|
||||||
|
@ -323,10 +329,8 @@ final class Provider extends MediaRouteProvider {
|
||||||
}
|
}
|
||||||
else if (intent.getAction().equals(MediaControlIntent.ACTION_SEEK)) {
|
else if (intent.getAction().equals(MediaControlIntent.ACTION_SEEK)) {
|
||||||
mIRemotePlayService.seek(mRouteId,
|
mIRemotePlayService.seek(mRouteId,
|
||||||
intent.getStringExtra(
|
intent.getStringExtra(MediaControlIntent.EXTRA_ITEM_ID),
|
||||||
MediaControlIntent.EXTRA_ITEM_ID),
|
intent.getLongExtra(MediaControlIntent.EXTRA_ITEM_CONTENT_POSITION, 0));
|
||||||
intent.getLongExtra(
|
|
||||||
MediaControlIntent.EXTRA_ITEM_CONTENT_POSITION, 0));
|
|
||||||
getItemStatus(intent, callback);
|
getItemStatus(intent, callback);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -334,8 +338,9 @@ final class Provider extends MediaRouteProvider {
|
||||||
getItemStatus(intent, callback);
|
getItemStatus(intent, callback);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} catch (RemoteException e) {
|
}
|
||||||
e.printStackTrace();
|
catch (RemoteException e) {
|
||||||
|
Log.w(TAG, "Failed to execute control request", e);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -357,8 +362,7 @@ final class Provider extends MediaRouteProvider {
|
||||||
mRequests.put(r, pair);
|
mRequests.put(r, pair);
|
||||||
mIRemotePlayService.getItemStatus(
|
mIRemotePlayService.getItemStatus(
|
||||||
intent.getStringExtra(MediaControlIntent.EXTRA_SESSION_ID),
|
intent.getStringExtra(MediaControlIntent.EXTRA_SESSION_ID),
|
||||||
intent.getStringExtra(MediaControlIntent.EXTRA_ITEM_ID),
|
intent.getStringExtra(MediaControlIntent.EXTRA_ITEM_ID), r);
|
||||||
r);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -382,12 +386,14 @@ final class Provider extends MediaRouteProvider {
|
||||||
mRequests.get(data.getInt("hash"));
|
mRequests.get(data.getInt("hash"));
|
||||||
Bundle status = data.getBundle("media_item_status");
|
Bundle status = data.getBundle("media_item_status");
|
||||||
|
|
||||||
if (pair.first.hasExtra(MediaControlIntent.EXTRA_SESSION_ID))
|
if (pair.first.hasExtra(MediaControlIntent.EXTRA_SESSION_ID)) {
|
||||||
status.putString(MediaControlIntent.EXTRA_SESSION_ID,
|
status.putString(MediaControlIntent.EXTRA_SESSION_ID,
|
||||||
pair.first.getStringExtra(MediaControlIntent.EXTRA_SESSION_ID));
|
pair.first.getStringExtra(MediaControlIntent.EXTRA_SESSION_ID));
|
||||||
if (pair.first.hasExtra(MediaControlIntent.EXTRA_ITEM_ID))
|
}
|
||||||
|
if (pair.first.hasExtra(MediaControlIntent.EXTRA_ITEM_ID)) {
|
||||||
status.putString(MediaControlIntent.EXTRA_ITEM_ID,
|
status.putString(MediaControlIntent.EXTRA_ITEM_ID,
|
||||||
pair.first.getStringExtra(MediaControlIntent.EXTRA_ITEM_ID));
|
pair.first.getStringExtra(MediaControlIntent.EXTRA_ITEM_ID));
|
||||||
|
}
|
||||||
pair.second.onResult(status);
|
pair.second.onResult(status);
|
||||||
break;
|
break;
|
||||||
case MSG_ERROR:
|
case MSG_ERROR:
|
||||||
|
|
|
@ -36,8 +36,9 @@ public class ProviderService extends MediaRouteProviderService {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MediaRouteProvider onCreateMediaRouteProvider() {
|
public MediaRouteProvider onCreateMediaRouteProvider() {
|
||||||
if (mProvider == null)
|
if (mProvider == null) {
|
||||||
mProvider = new Provider(this);
|
mProvider = new Provider(this);
|
||||||
|
}
|
||||||
return mProvider;
|
return mProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -87,11 +87,14 @@ public class RemotePlayService extends Service implements RegistryListener {
|
||||||
public void onServiceConnected(ComponentName className, IBinder service) {
|
public void onServiceConnected(ComponentName className, IBinder service) {
|
||||||
mUpnpService = (AndroidUpnpService) service;
|
mUpnpService = (AndroidUpnpService) service;
|
||||||
mUpnpService.getRegistry().addListener(RemotePlayService.this);
|
mUpnpService.getRegistry().addListener(RemotePlayService.this);
|
||||||
for (Device<?, ?, ?> d : mUpnpService.getControlPoint().getRegistry().getDevices())
|
for (Device<?, ?, ?> d : mUpnpService.getControlPoint().getRegistry().getDevices()) {
|
||||||
if (d instanceof LocalDevice)
|
if (d instanceof LocalDevice) {
|
||||||
localDeviceAdded(mUpnpService.getRegistry(), (LocalDevice) d);
|
localDeviceAdded(mUpnpService.getRegistry(), (LocalDevice) d);
|
||||||
else
|
}
|
||||||
|
else {
|
||||||
remoteDeviceAdded(mUpnpService.getRegistry(), (RemoteDevice) d);
|
remoteDeviceAdded(mUpnpService.getRegistry(), (RemoteDevice) d);
|
||||||
|
}
|
||||||
|
}
|
||||||
mUpnpService.getControlPoint().search();
|
mUpnpService.getControlPoint().search();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,11 +122,8 @@ public class RemotePlayService extends Service implements RegistryListener {
|
||||||
@Override
|
@Override
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
super.onCreate();
|
super.onCreate();
|
||||||
bindService(
|
bindService(new Intent(this, AndroidUpnpServiceImpl.class),
|
||||||
new Intent(this, AndroidUpnpServiceImpl.class),
|
mUpnpServiceConnection, Context.BIND_AUTO_CREATE);
|
||||||
mUpnpServiceConnection,
|
|
||||||
Context.BIND_AUTO_CREATE
|
|
||||||
);
|
|
||||||
|
|
||||||
IntentFilter filter = new IntentFilter();
|
IntentFilter filter = new IntentFilter();
|
||||||
filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
|
filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
|
||||||
|
@ -144,7 +144,8 @@ public class RemotePlayService extends Service implements RegistryListener {
|
||||||
void sendMessage(Message msg) {
|
void sendMessage(Message msg) {
|
||||||
try {
|
try {
|
||||||
mListener.send(msg);
|
mListener.send(msg);
|
||||||
} catch (RemoteException e) {
|
}
|
||||||
|
catch (RemoteException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -173,22 +174,29 @@ public class RemotePlayService extends Service implements RegistryListener {
|
||||||
|
|
||||||
if (wifi.isConnected()) {
|
if (wifi.isConnected()) {
|
||||||
if (mUpnpService != null) {
|
if (mUpnpService != null) {
|
||||||
for (Device<?, ?, ?> d : mUpnpService.getControlPoint().getRegistry().getDevices())
|
for (Device<?, ?, ?> d :
|
||||||
|
mUpnpService.getControlPoint().getRegistry().getDevices()) {
|
||||||
deviceAdded(d);
|
deviceAdded(d);
|
||||||
|
}
|
||||||
mUpnpService.getControlPoint().search();
|
mUpnpService.getControlPoint().search();
|
||||||
}
|
}
|
||||||
} else
|
}
|
||||||
for (Entry<String, Device<?, ?, ?>> d : mDevices.entrySet())
|
else {
|
||||||
|
for (Entry<String, Device<?, ?, ?>> d : mDevices.entrySet()) {
|
||||||
if (mUpnpService.getControlPoint().getRegistry()
|
if (mUpnpService.getControlPoint().getRegistry()
|
||||||
.getDevice(new UDN(d.getKey()), false) == null) {
|
.getDevice(new UDN(d.getKey()), false) == null) {
|
||||||
deviceRemoved(d.getValue());
|
deviceRemoved(d.getValue());
|
||||||
for (RemotePlayServiceBinder b : mBinders.keySet())
|
for (RemotePlayServiceBinder b : mBinders.keySet()) {
|
||||||
if (b.mCurrentRenderer != null && b.mCurrentRenderer.equals(d.getValue())) {
|
if (b.mCurrentRenderer != null &&
|
||||||
|
b.mCurrentRenderer.equals(d.getValue())) {
|
||||||
b.mSubscriptionCallback.end();
|
b.mSubscriptionCallback.end();
|
||||||
b.mCurrentRenderer = null;
|
b.mCurrentRenderer = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -196,8 +204,7 @@ public class RemotePlayService extends Service implements RegistryListener {
|
||||||
*/
|
*/
|
||||||
org.teleal.cling.model.meta.Service<?, ?> getService(
|
org.teleal.cling.model.meta.Service<?, ?> getService(
|
||||||
Device<?, ?, ?> device, String name) {
|
Device<?, ?, ?> device, String name) {
|
||||||
return device.findService(
|
return device.findService(new ServiceType("schemas-upnp-org", name));
|
||||||
new ServiceType("schemas-upnp-org", name));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -207,8 +214,7 @@ public class RemotePlayService extends Service implements RegistryListener {
|
||||||
if (mDevices.containsValue(device))
|
if (mDevices.containsValue(device))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
final org.teleal.cling.model.meta.Service<?, ?> rc =
|
final org.teleal.cling.model.meta.Service<?, ?> rc = getService(device, "RenderingControl");
|
||||||
getService(device, "RenderingControl");
|
|
||||||
if (rc == null || mListener == null)
|
if (rc == null || mListener == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -233,7 +239,8 @@ public class RemotePlayService extends Service implements RegistryListener {
|
||||||
int maxVolume = 100;
|
int maxVolume = 100;
|
||||||
if (rc.getStateVariable("Volume") != null) {
|
if (rc.getStateVariable("Volume") != null) {
|
||||||
StateVariableAllowedValueRange volumeRange =
|
StateVariableAllowedValueRange volumeRange =
|
||||||
rc.getStateVariable("Volume").getTypeDetails().getAllowedValueRange();
|
rc.getStateVariable("Volume")
|
||||||
|
.getTypeDetails().getAllowedValueRange();
|
||||||
maxVolume = (int) volumeRange.getMaximum();
|
maxVolume = (int) volumeRange.getMaximum();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -83,25 +83,26 @@ public class RemotePlayServiceBinder extends IRemotePlayService.Stub {
|
||||||
private RemotePlayService mRps;
|
private RemotePlayService mRps;
|
||||||
|
|
||||||
private boolean mStartingPlayback = false;
|
private boolean mStartingPlayback = false;
|
||||||
|
|
||||||
public RemotePlayServiceBinder(RemotePlayService rps) {
|
public RemotePlayServiceBinder(RemotePlayService rps) {
|
||||||
mRps = rps;
|
mRps = rps;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void startSearch(Messenger listener)
|
public void startSearch(Messenger listener) throws RemoteException {
|
||||||
throws RemoteException {
|
|
||||||
mRps.mListener = listener;
|
mRps.mListener = listener;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void selectRenderer(String id) throws RemoteException {
|
public void selectRenderer(String id) throws RemoteException {
|
||||||
mCurrentRenderer = mRps.mDevices.get(id);
|
mCurrentRenderer = mRps.mDevices.get(id);
|
||||||
for (RemotePlayServiceBinder b : mRps.mBinders.keySet())
|
for (RemotePlayServiceBinder b : mRps.mBinders.keySet()) {
|
||||||
if (b != this && mCurrentRenderer.equals(b.mCurrentRenderer))
|
if (b != this && mCurrentRenderer.equals(b.mCurrentRenderer)) {
|
||||||
b.unselectRenderer("");
|
b.unselectRenderer("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mSubscriptionCallback = new SubscriptionCallback(
|
mSubscriptionCallback = new SubscriptionCallback(mCurrentRenderer.findService(
|
||||||
mCurrentRenderer.findService(
|
|
||||||
new ServiceType("schemas-upnp-org", "AVTransport")), 600) {
|
new ServiceType("schemas-upnp-org", "AVTransport")), 600) {
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
|
@ -111,8 +112,7 @@ public class RemotePlayServiceBinder extends IRemotePlayService.Stub {
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
@Override
|
@Override
|
||||||
protected void ended(GENASubscription sub, CancelReason reason,
|
protected void ended(GENASubscription sub, CancelReason reason, UpnpResponse response) {
|
||||||
UpnpResponse response) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
|
@ -121,16 +121,14 @@ public class RemotePlayServiceBinder extends IRemotePlayService.Stub {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
Map<String, StateVariableValue> m = sub.getCurrentValues();
|
Map<String, StateVariableValue> m = sub.getCurrentValues();
|
||||||
try {
|
try {
|
||||||
LastChange lastChange = new LastChange(
|
LastChange lastChange = new LastChange(new AVTransportLastChangeParser(),
|
||||||
new AVTransportLastChangeParser(),
|
|
||||||
m.get("LastChange").toString());
|
m.get("LastChange").toString());
|
||||||
if (mStartingPlayback || lastChange.getEventedValue(0,
|
if (mStartingPlayback || lastChange.getEventedValue(0,
|
||||||
AVTransportVariable.TransportState.class) == null)
|
AVTransportVariable.TransportState.class) == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
switch (lastChange.getEventedValue(0,
|
switch (lastChange.getEventedValue(0,
|
||||||
AVTransportVariable.TransportState.class)
|
AVTransportVariable.TransportState.class).getValue()) {
|
||||||
.getValue()) {
|
|
||||||
case PLAYING:
|
case PLAYING:
|
||||||
mPlaybackState = MediaItemStatus.PLAYBACK_STATE_PLAYING;
|
mPlaybackState = MediaItemStatus.PLAYBACK_STATE_PLAYING;
|
||||||
break;
|
break;
|
||||||
|
@ -149,7 +147,8 @@ public class RemotePlayServiceBinder extends IRemotePlayService.Stub {
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (Exception e) {
|
}
|
||||||
|
catch (Exception e) {
|
||||||
Log.w(TAG, "Failed to parse UPNP event", e);
|
Log.w(TAG, "Failed to parse UPNP event", e);
|
||||||
mRps.sendError("Failed to parse UPNP event");
|
mRps.sendError("Failed to parse UPNP event");
|
||||||
}
|
}
|
||||||
|
@ -157,8 +156,7 @@ public class RemotePlayServiceBinder extends IRemotePlayService.Stub {
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
@Override
|
@Override
|
||||||
protected void eventsMissed(GENASubscription sub,
|
protected void eventsMissed(GENASubscription sub, int numberOfMissedEvents) {
|
||||||
int numberOfMissedEvents) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
|
@ -177,10 +175,12 @@ public class RemotePlayServiceBinder extends IRemotePlayService.Stub {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void unselectRenderer(String sessionId) throws RemoteException {
|
public void unselectRenderer(String sessionId) throws RemoteException {
|
||||||
if (mRps.mDevices.get(sessionId) != null)
|
if (mRps.mDevices.get(sessionId) != null) {
|
||||||
stop(sessionId);
|
stop(sessionId);
|
||||||
if (mSubscriptionCallback != null)
|
}
|
||||||
|
if (mSubscriptionCallback != null) {
|
||||||
mSubscriptionCallback.end();
|
mSubscriptionCallback.end();
|
||||||
|
}
|
||||||
mCurrentRenderer = null;
|
mCurrentRenderer = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -284,8 +284,10 @@ public class RemotePlayServiceBinder extends IRemotePlayService.Stub {
|
||||||
// Sometimes stop works even though pause does not.
|
// Sometimes stop works even though pause does not.
|
||||||
try {
|
try {
|
||||||
stop(sessionId);
|
stop(sessionId);
|
||||||
} catch (RemoteException e) {
|
}
|
||||||
e.printStackTrace();
|
catch (RemoteException e) {
|
||||||
|
Log.w(TAG, "Calling stop failed", e);
|
||||||
|
mRps.sendError("Calling stop failed: " + e.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -372,6 +374,7 @@ public class RemotePlayServiceBinder extends IRemotePlayService.Stub {
|
||||||
public void failure(ActionInvocation invocation,
|
public void failure(ActionInvocation invocation,
|
||||||
UpnpResponse operation, String defaultMessage) {
|
UpnpResponse operation, String defaultMessage) {
|
||||||
Log.w(TAG, "Get position failed: " + defaultMessage);
|
Log.w(TAG, "Get position failed: " + defaultMessage);
|
||||||
|
mRps.sendError("Get position failed: " + defaultMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
|
@ -382,7 +385,8 @@ public class RemotePlayServiceBinder extends IRemotePlayService.Stub {
|
||||||
Builder status = null;
|
Builder status = null;
|
||||||
|
|
||||||
status = new MediaItemStatus.Builder(mPlaybackState);
|
status = new MediaItemStatus.Builder(mPlaybackState);
|
||||||
if (positionInfo.getTrackURI() != null && positionInfo.getTrackURI().equals(itemId)) {
|
if (positionInfo.getTrackURI() != null &&
|
||||||
|
positionInfo.getTrackURI().equals(itemId)) {
|
||||||
try {
|
try {
|
||||||
status.setContentPosition(positionInfo.getTrackElapsedSeconds() * 1000)
|
status.setContentPosition(positionInfo.getTrackElapsedSeconds() * 1000)
|
||||||
.setContentDuration(positionInfo.getTrackDurationSeconds() * 1000)
|
.setContentDuration(positionInfo.getTrackDurationSeconds() * 1000)
|
||||||
|
@ -390,6 +394,8 @@ public class RemotePlayServiceBinder extends IRemotePlayService.Stub {
|
||||||
}
|
}
|
||||||
catch (NumberFormatException e) {
|
catch (NumberFormatException e) {
|
||||||
Log.d(TAG, "Failed to read track position or duration", e);
|
Log.d(TAG, "Failed to read track position or duration", e);
|
||||||
|
mRps.sendError("Failed to read track position or duration: " +
|
||||||
|
e.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,16 +27,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
package com.github.nutomic.controldlna.utility;
|
package com.github.nutomic.controldlna.utility;
|
||||||
|
|
||||||
import java.net.URI;
|
|
||||||
import java.net.URISyntaxException;
|
|
||||||
import java.util.Comparator;
|
|
||||||
|
|
||||||
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.registry.Registry;
|
|
||||||
import org.teleal.cling.registry.RegistryListener;
|
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
@ -48,6 +38,16 @@ import android.widget.TextView;
|
||||||
|
|
||||||
import com.github.nutomic.controldlna.R;
|
import com.github.nutomic.controldlna.R;
|
||||||
|
|
||||||
|
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.registry.Registry;
|
||||||
|
import org.teleal.cling.registry.RegistryListener;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
import java.util.Comparator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Displays the devices that are inserted through the RegistryListener (either
|
* Displays the devices that are inserted through the RegistryListener (either
|
||||||
* of type RENDERER or SERVER).
|
* of type RENDERER or SERVER).
|
||||||
|
@ -60,8 +60,6 @@ public class DeviceArrayAdapter extends ArrayAdapter<Device<?, ?, ?>>
|
||||||
|
|
||||||
private static final String TAG = "DeviceArrayAdapter";
|
private static final String TAG = "DeviceArrayAdapter";
|
||||||
|
|
||||||
public static final String RENDERER = "MediaRenderer";
|
|
||||||
|
|
||||||
public static final String SERVER = "MediaServer";
|
public static final String SERVER = "MediaServer";
|
||||||
|
|
||||||
private Activity mActivity;
|
private Activity mActivity;
|
||||||
|
@ -91,15 +89,16 @@ public class DeviceArrayAdapter extends ArrayAdapter<Device<?, ?, ?>>
|
||||||
|
|
||||||
if (getItem(position).hasIcons()) {
|
if (getItem(position).hasIcons()) {
|
||||||
URI uri = getItem(position).getIcons()[0].getUri();
|
URI uri = getItem(position).getIcons()[0].getUri();
|
||||||
if (getItem(position) instanceof RemoteDevice)
|
if (getItem(position) instanceof RemoteDevice) {
|
||||||
try {
|
try {
|
||||||
RemoteDevice device = (RemoteDevice) getItem(position);
|
RemoteDevice device = (RemoteDevice) getItem(position);
|
||||||
uri = device.normalizeURI(uri).toURI();
|
uri = device.normalizeURI(uri).toURI();
|
||||||
} catch (URISyntaxException e) {
|
}
|
||||||
|
catch (URISyntaxException e) {
|
||||||
Log.w(TAG, "Failed to get device icon URI", e);
|
Log.w(TAG, "Failed to get device icon URI", e);
|
||||||
}
|
}
|
||||||
RemoteImageView icon =
|
}
|
||||||
(RemoteImageView) convertView.findViewById(R.id.image);
|
RemoteImageView icon = (RemoteImageView) convertView.findViewById(R.id.image);
|
||||||
icon.setImageUri(uri);
|
icon.setImageUri(uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,9 +109,11 @@ public class DeviceArrayAdapter extends ArrayAdapter<Device<?, ?, ?>>
|
||||||
* Adds a new device to the list if its type equals mDeviceType.
|
* Adds a new device to the list if its type equals mDeviceType.
|
||||||
*/
|
*/
|
||||||
public void deviceAdded(final Device<?, ?, ?> device) {
|
public void deviceAdded(final Device<?, ?, ?> device) {
|
||||||
for (int i = 0; i < getCount(); i++)
|
for (int i = 0; i < getCount(); i++) {
|
||||||
if (getItem(i).equals(device))
|
if (getItem(i).equals(device)) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mActivity.runOnUiThread(new Runnable() {
|
mActivity.runOnUiThread(new Runnable() {
|
||||||
|
|
||||||
|
@ -141,9 +142,10 @@ public class DeviceArrayAdapter extends ArrayAdapter<Device<?, ?, ?>>
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if (getPosition(device) != -1)
|
if (getPosition(device) != -1) {
|
||||||
remove(device);
|
remove(device);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -80,30 +80,36 @@ public class FileArrayAdapter extends ArrayAdapter<DIDLObject> {
|
||||||
? Integer.toString(track.getOriginalTrackNumber()) + ". "
|
? Integer.toString(track.getOriginalTrackNumber()) + ". "
|
||||||
: "";
|
: "";
|
||||||
title.setText(trackNumber + item.getTitle());
|
title.setText(trackNumber + item.getTitle());
|
||||||
if (track.getArtists().length > 0)
|
if (track.getArtists().length > 0) {
|
||||||
artist.setText(track.getArtists()[0].getName());
|
artist.setText(track.getArtists()[0].getName());
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
|
else {
|
||||||
title.setText(item.getTitle());
|
title.setText(item.getTitle());
|
||||||
|
}
|
||||||
|
|
||||||
RemoteImageView image = (RemoteImageView) convertView.findViewById(R.id.image);
|
RemoteImageView image = (RemoteImageView) convertView.findViewById(R.id.image);
|
||||||
URI icon = item.getFirstPropertyValue(
|
URI icon = item.getFirstPropertyValue(DIDLObject.Property.UPNP.ALBUM_ART_URI.class);
|
||||||
DIDLObject.Property.UPNP.ALBUM_ART_URI.class);
|
|
||||||
if (icon != null) {
|
if (icon != null) {
|
||||||
image.setImageUri(icon);
|
image.setImageUri(icon);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
int resId;
|
int resId;
|
||||||
if (item instanceof AudioItem)
|
if (item instanceof AudioItem) {
|
||||||
resId = R.drawable.ic_doc_audio_am;
|
resId = R.drawable.ic_doc_audio_am;
|
||||||
else if (item instanceof VideoItem)
|
}
|
||||||
|
else if (item instanceof VideoItem) {
|
||||||
resId = R.drawable.ic_doc_video_am;
|
resId = R.drawable.ic_doc_video_am;
|
||||||
else if (item instanceof ImageItem)
|
}
|
||||||
|
else if (item instanceof ImageItem) {
|
||||||
resId = R.drawable.ic_doc_image;
|
resId = R.drawable.ic_doc_image;
|
||||||
else if (item instanceof PlaylistItem)
|
}
|
||||||
|
else if (item instanceof PlaylistItem) {
|
||||||
resId = R.drawable.ic_doc_album;
|
resId = R.drawable.ic_doc_album;
|
||||||
else
|
}
|
||||||
|
else {
|
||||||
resId = R.drawable.ic_root_folder_am;
|
resId = R.drawable.ic_root_folder_am;
|
||||||
|
}
|
||||||
image.setImageResource(resId);
|
image.setImageResource(resId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,8 +120,9 @@ public class FileArrayAdapter extends ArrayAdapter<DIDLObject> {
|
||||||
* Replacement for addAll, which is not implemented on lower API levels.
|
* Replacement for addAll, which is not implemented on lower API levels.
|
||||||
*/
|
*/
|
||||||
public void add(List<Item> playlist) {
|
public void add(List<Item> playlist) {
|
||||||
for (DIDLObject d : playlist)
|
for (DIDLObject d : playlist) {
|
||||||
add(d);
|
add(d);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,7 @@ import android.os.AsyncTask;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles background task of loading a bitmap by URI.
|
* Loads an image by URI in the background and returns it.
|
||||||
*
|
*
|
||||||
* @author Felix Ableitner
|
* @author Felix Ableitner
|
||||||
*
|
*
|
||||||
|
@ -56,15 +56,15 @@ public class LoadImageTask extends AsyncTask<URI, Void, Bitmap> {
|
||||||
|
|
||||||
Bitmap bm = null;
|
Bitmap bm = null;
|
||||||
try {
|
try {
|
||||||
URLConnection conn = new URL(uri[0].toString())
|
URLConnection conn = new URL(uri[0].toString()).openConnection();
|
||||||
.openConnection();
|
|
||||||
conn.connect();
|
conn.connect();
|
||||||
InputStream is = conn.getInputStream();
|
InputStream is = conn.getInputStream();
|
||||||
BufferedInputStream bis = new BufferedInputStream(is);
|
BufferedInputStream bis = new BufferedInputStream(is);
|
||||||
bm = BitmapFactory.decodeStream(bis);
|
bm = BitmapFactory.decodeStream(bis);
|
||||||
bis.close();
|
bis.close();
|
||||||
is.close();
|
is.close();
|
||||||
} catch (IOException e) {
|
}
|
||||||
|
catch (IOException e) {
|
||||||
Log.w(TAG, "Failed to load artwork image", e);
|
Log.w(TAG, "Failed to load artwork image", e);
|
||||||
}
|
}
|
||||||
return bm;
|
return bm;
|
||||||
|
|
|
@ -52,9 +52,10 @@ public class RemoteImageView extends ImageView {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onPostExecute(Bitmap bm) {
|
protected void onPostExecute(Bitmap bm) {
|
||||||
if (bm != null)
|
if (bm != null) {
|
||||||
setImageBitmap(bm);
|
setImageBitmap(bm);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Reference in a new issue