From 105bb9de9473a69e28c5dcb4827ee4c289ac9b3f Mon Sep 17 00:00:00 2001 From: Felix Ableitner Date: Mon, 5 May 2014 16:19:06 +0200 Subject: [PATCH] Formatting fixes. - add braces to if/for - indent with tabs instead of spaces - remove trailing whitespaces --- res/layout/activity_main.xml | 8 +- res/layout/list_item.xml | 54 ++--- res/layout/route_fragment.xml | 184 +++++++-------- res/layout/server_fragment.xml | 34 +-- res/menu/menu.xml | 6 +- res/values/arrays.xml | 10 +- res/values/colors.xml | 4 +- res/values/dimens.xml | 6 +- res/values/strings.xml | 90 ++++---- res/values/styles.xml | 30 +-- res/xml/preferences.xml | 28 +-- .../nutomic/controldlna/gui/MainActivity.java | 130 +++++------ .../controldlna/gui/PreferencesActivity.java | 131 ++++++----- .../controldlna/gui/RouteFragment.java | 144 ++++++------ .../controldlna/gui/ServerFragment.java | 110 +++++---- .../controldlna/localroute/Controller.java | 212 +++++++++--------- .../controldlna/localroute/Provider.java | 111 ++++----- .../localroute/ProviderService.java | 19 +- .../mediarouter/MediaRouterPlayService.java | 160 +++++++------ .../MediaRouterPlayServiceBinder.java | 12 +- .../controldlna/upnp/IRemotePlayService.aidl | 20 +- .../nutomic/controldlna/upnp/Provider.java | 88 ++++---- .../controldlna/upnp/ProviderService.java | 13 +- .../controldlna/upnp/RemotePlayService.java | 57 ++--- .../upnp/RemotePlayServiceBinder.java | 102 +++++---- .../utility/DeviceArrayAdapter.java | 50 +++-- .../controldlna/utility/FileArrayAdapter.java | 41 ++-- .../controldlna/utility/LoadImageTask.java | 20 +- .../controldlna/utility/RemoteImageView.java | 17 +- .../controldlna/utility/RouteAdapter.java | 2 +- 30 files changed, 980 insertions(+), 913 deletions(-) diff --git a/res/layout/activity_main.xml b/res/layout/activity_main.xml index 18ffdf3..3676c09 100644 --- a/res/layout/activity_main.xml +++ b/res/layout/activity_main.xml @@ -1,6 +1,6 @@ + xmlns:android="http://schemas.android.com/apk/res/android" + android:id="@+id/pager" + android:layout_width="match_parent" + android:layout_height="match_parent" /> diff --git a/res/layout/list_item.xml b/res/layout/list_item.xml index 31b64d5..30bac95 100644 --- a/res/layout/list_item.xml +++ b/res/layout/list_item.xml @@ -1,38 +1,38 @@ + android:layout_width="fill_parent" + android:layout_height="?android:attr/listPreferredItemHeight" + android:orientation="horizontal" > + + + - - - + android:layout_width="fill_parent" + android:layout_height="fill_parent" + android:orientation="vertical" + android:layout_marginTop="4dip" > + android:id="@+id/title" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:textAppearance="?android:attr/textAppearanceMedium" + android:lines="1" + android:ellipsize="end" /> + android:id="@+id/subtitle" + android:layout_width="fill_parent" + android:layout_height="wrap_content" + android:textAppearance="?android:attr/textAppearanceSmall" + android:lines="1" + android:ellipsize="end" /> diff --git a/res/layout/route_fragment.xml b/res/layout/route_fragment.xml index 025820e..961d8a4 100644 --- a/res/layout/route_fragment.xml +++ b/res/layout/route_fragment.xml @@ -1,102 +1,102 @@ + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical" > - - - - - + - + + + + + - - - - - - - - - - - - + - - - - - + + + + + + + + + + + + + + + diff --git a/res/layout/server_fragment.xml b/res/layout/server_fragment.xml index e2f0622..4a5529e 100644 --- a/res/layout/server_fragment.xml +++ b/res/layout/server_fragment.xml @@ -1,21 +1,21 @@ - - - - + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="vertical" > + + + + diff --git a/res/menu/menu.xml b/res/menu/menu.xml index 70f3d03..ffd380d 100644 --- a/res/menu/menu.xml +++ b/res/menu/menu.xml @@ -2,8 +2,8 @@ - + \ No newline at end of file diff --git a/res/values/arrays.xml b/res/values/arrays.xml index 47bfef4..f718358 100644 --- a/res/values/arrays.xml +++ b/res/values/arrays.xml @@ -1,8 +1,8 @@ - - yes - no - ask - + + yes + no + ask + \ No newline at end of file diff --git a/res/values/colors.xml b/res/values/colors.xml index 2a7b872..df2d913 100644 --- a/res/values/colors.xml +++ b/res/values/colors.xml @@ -1,5 +1,5 @@ - #BB99CC00 - #ff33b5e5 + #BB99CC00 + #ff33b5e5 diff --git a/res/values/dimens.xml b/res/values/dimens.xml index 55c1e59..3c6cff8 100644 --- a/res/values/dimens.xml +++ b/res/values/dimens.xml @@ -1,7 +1,7 @@ - - 16dp - 16dp + + 16dp + 16dp diff --git a/res/values/strings.xml b/res/values/strings.xml index d52c120..2ffd8c7 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -1,42 +1,42 @@ - ControlDLNA - - - Server - Folder is empty - No UPNP devices found. - \nNew devices will be added automatically when they are available. - - - Route - Playlist is empty - No routes found. - \nNew routes will be added automatically when they are available. - - - Play - Pause - Previous - Next - Shuffle - Repeat - - - Do you really want to exit the renderer? - Playback will be stopped. - Please select a route - Wifi needs to be connected for playback. - Do you want to enable it now? + ControlDLNA - - Local Device - - - Album Art - - + + Server + Folder is empty + No UPNP devices found. + \nNew devices will be added automatically when they are available. + + + Route + Playlist is empty + No routes found. + \nNew routes will be added automatically when they are available. + + + Play + Pause + Previous + Next + Shuffle + Repeat + + + Do you really want to exit the renderer? + Playback will be stopped. + Please select a route + Wifi needs to be connected for playback. + Do you want to enable it now? + + + Local Device + + + Album Art + + UPNP Route Provider Service @@ -45,18 +45,18 @@ Preferences - - Automatically enable Wifi on start + + Automatically enable Wifi on start - - - yes - no - ask - + + + yes + no + ask + - - Pause playback on incoming phone call + + Pause playback on incoming phone call Contact Developer diff --git a/res/values/styles.xml b/res/values/styles.xml index 6ce89c7..d10f846 100644 --- a/res/values/styles.xml +++ b/res/values/styles.xml @@ -1,20 +1,20 @@ - - + + - - + + diff --git a/res/xml/preferences.xml b/res/xml/preferences.xml index 9cf4091..8ea9a8c 100644 --- a/res/xml/preferences.xml +++ b/res/xml/preferences.xml @@ -1,20 +1,20 @@ - + - + + + - - \ No newline at end of file diff --git a/src/com/github/nutomic/controldlna/gui/MainActivity.java b/src/com/github/nutomic/controldlna/gui/MainActivity.java index ade41b9..5894523 100644 --- a/src/com/github/nutomic/controldlna/gui/MainActivity.java +++ b/src/com/github/nutomic/controldlna/gui/MainActivity.java @@ -5,13 +5,13 @@ All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. + notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. * Neither the name of the nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED @@ -27,17 +27,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.github.nutomic.controldlna.gui; -import java.util.List; - -import org.teleal.cling.support.model.item.Item; - import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; -import android.content.SharedPreferences; -import android.net.ConnectivityManager; -import android.net.NetworkInfo; import android.net.wifi.WifiManager; import android.os.Bundle; 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.TabListener; import android.support.v7.app.ActionBarActivity; -import android.util.Log; import android.view.KeyEvent; import android.view.Menu; 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 org.teleal.cling.support.model.item.Item; + +import java.util.List; + /** * 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.setAdapter(mSectionsPagerAdapter); - mViewPager.setOnPageChangeListener( - new ViewPager.SimpleOnPageChangeListener() { + mViewPager.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() { @Override public void onPageSelected(int position) { actionBar.setSelectedNavigationItem(position); @@ -143,27 +134,27 @@ public class MainActivity extends ActionBarActivity { .setText(R.string.title_route) .setTabListener(tabListener)); - final WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE); - if (!wifi.isWifiEnabled()){ - String value = PreferenceManager.getDefaultSharedPreferences(this) - .getString(PreferencesActivity.KEY_ENABLE_WIFI_ON_START, "ask"); - if (value.equals("yes")) { - wifi.setWifiEnabled(true); - } - else if (value.equals("ask")) { - new AlertDialog.Builder(this) - .setMessage(R.string.enable_wifi_dialog) - .setPositiveButton(android.R.string.yes, - new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialogInterface, int i) { - wifi.setWifiEnabled(true); - } - }) - .setNegativeButton(android.R.string.no, null) - .show(); - } - } + final WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE); + if (!wifi.isWifiEnabled()) { + String value = PreferenceManager.getDefaultSharedPreferences(this) + .getString(PreferencesActivity.KEY_ENABLE_WIFI_ON_START, "ask"); + if (value.equals("yes")) { + wifi.setWifiEnabled(true); + } + else if (value.equals("ask")) { + new AlertDialog.Builder(this) + .setMessage(R.string.enable_wifi_dialog) + .setPositiveButton(android.R.string.yes, + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialogInterface, int i) { + wifi.setWifiEnabled(true); + } + }) + .setNegativeButton(android.R.string.no, null) + .show(); + } + } if (savedInstanceState != null) { @@ -181,30 +172,30 @@ public class MainActivity extends ActionBarActivity { onNewIntent(getIntent()); } - @Override - public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.menu, menu); - return true; - } + @Override + public boolean onCreateOptionsMenu(Menu menu) { + getMenuInflater().inflate(R.menu.menu, menu); + return true; + } - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case R.id.preferences: - Intent i = new Intent(this, PreferencesActivity.class); - startActivity(i); - return true; - default: - return super.onOptionsItemSelected(item); - } - } + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case R.id.preferences: + Intent i = new Intent(this, PreferencesActivity.class); + startActivity(i); + return true; + default: + return super.onOptionsItemSelected(item); + } + } - /** + /** * Displays the RouteFragment immediately (instead of ServerFragment). */ @Override protected void onNewIntent(Intent intent) { - if (intent.getAction().equals("showRouteFragment")) { + if (intent.getAction() != null && intent.getAction().equals("showRouteFragment")) { mViewPager.setCurrentItem(1); mRouteFragment.scrollToCurrent(); } @@ -216,13 +207,13 @@ public class MainActivity extends ActionBarActivity { @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); - // Avoid crash if called during startup. - if (mServerFragment != null && mRouteFragment != null) { - FragmentManager fm = getSupportFragmentManager(); - fm.putFragment(outState, ServerFragment.class.getName(), mServerFragment); - fm.putFragment(outState, RouteFragment.class.getName(), mRouteFragment); - outState.putInt("currentTab", mViewPager.getCurrentItem()); - } + // Avoid crash if called during startup. + if (mServerFragment != null && mRouteFragment != null) { + FragmentManager fm = getSupportFragmentManager(); + fm.putFragment(outState, ServerFragment.class.getName(), mServerFragment); + fm.putFragment(outState, RouteFragment.class.getName(), mRouteFragment); + outState.putInt("currentTab", mViewPager.getCurrentItem()); + } } /** @@ -233,8 +224,9 @@ public class MainActivity extends ActionBarActivity { public void onBackPressed() { OnBackPressedListener currentFragment = (OnBackPressedListener) mSectionsPagerAdapter.getItem(mViewPager.getCurrentItem()); - if (!currentFragment.onBackPressed()) + if (!currentFragment.onBackPressed()) { super.onBackPressed(); + } } /** @@ -244,12 +236,14 @@ public class MainActivity extends ActionBarActivity { public boolean dispatchKeyEvent(KeyEvent event) { switch (event.getKeyCode()) { case KeyEvent.KEYCODE_VOLUME_UP: - if (event.getAction() == KeyEvent.ACTION_DOWN) + if (event.getAction() == KeyEvent.ACTION_DOWN) { mRouteFragment.increaseVolume(); + } return true; case KeyEvent.KEYCODE_VOLUME_DOWN: - if (event.getAction() == KeyEvent.ACTION_DOWN) + if (event.getAction() == KeyEvent.ACTION_DOWN) { mRouteFragment.decreaseVolume(); + } return true; default: return super.dispatchKeyEvent(event); diff --git a/src/com/github/nutomic/controldlna/gui/PreferencesActivity.java b/src/com/github/nutomic/controldlna/gui/PreferencesActivity.java index e4f48dd..2d734cd 100644 --- a/src/com/github/nutomic/controldlna/gui/PreferencesActivity.java +++ b/src/com/github/nutomic/controldlna/gui/PreferencesActivity.java @@ -5,13 +5,13 @@ All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. + notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. * Neither the name of the nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED @@ -43,73 +43,72 @@ import android.view.MenuItem; import com.github.nutomic.controldlna.R; public class PreferencesActivity extends PreferenceActivity - implements SharedPreferences.OnSharedPreferenceChangeListener { + implements SharedPreferences.OnSharedPreferenceChangeListener { - public static final String KEY_ENABLE_WIFI_ON_START = "enable_wifi_on_start"; - public static final String KEY_INCOMING_PHONE_CALL_PAUSE = "incoming_phone_call_pause"; - private static final String KEY_CONTACT_DEV = "contact_dev"; + public static final String KEY_ENABLE_WIFI_ON_START = "enable_wifi_on_start"; + public static final String KEY_INCOMING_PHONE_CALL_PAUSE = "incoming_phone_call_pause"; + private static final String KEY_CONTACT_DEV = "contact_dev"; - private ListPreference mEnableWifiOnStart; - private Preference mContactDev; + private ListPreference mEnableWifiOnStart; + private Preference mContactDev; - /** - * Initializes preferences from xml. - */ - @Override - public void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); + /** + * Initializes preferences from xml. + */ + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); - // There is currently no way to get ActionBar in PreferenceActivity on pre-honeycomb with - // compatibility library, so we'll have to do a version check. - if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { - getActionBar().setDisplayHomeAsUpEnabled(true); - } + // There is currently no way to get ActionBar in PreferenceActivity on pre-honeycomb with + // compatibility library, so we'll have to do a version check. + if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { + getActionBar().setDisplayHomeAsUpEnabled(true); + } - PreferenceManager.getDefaultSharedPreferences(this) - .registerOnSharedPreferenceChangeListener(this); - addPreferencesFromResource(R.xml.preferences); - final PreferenceScreen screen = getPreferenceScreen(); - mEnableWifiOnStart = (ListPreference) screen.findPreference(KEY_ENABLE_WIFI_ON_START); - mEnableWifiOnStart.setSummary(mEnableWifiOnStart.getEntry()); - mContactDev = screen.findPreference(KEY_CONTACT_DEV); - } + PreferenceManager.getDefaultSharedPreferences(this) + .registerOnSharedPreferenceChangeListener(this); + addPreferencesFromResource(R.xml.preferences); + final PreferenceScreen screen = getPreferenceScreen(); + mEnableWifiOnStart = (ListPreference) screen.findPreference(KEY_ENABLE_WIFI_ON_START); + mEnableWifiOnStart.setSummary(mEnableWifiOnStart.getEntry()); + mContactDev = screen.findPreference(KEY_CONTACT_DEV); + } - /** - * Navigates up from activity on ActionBar back click. - */ - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case android.R.id.home: - NavUtils.navigateUpFromSameTask(this); - return true; - default: - return super.onOptionsItemSelected(item); - } - } + /** + * Navigates up from activity on ActionBar back click. + */ + @Override + public boolean onOptionsItemSelected(MenuItem item) { + switch (item.getItemId()) { + case android.R.id.home: + NavUtils.navigateUpFromSameTask(this); + return true; + default: + return super.onOptionsItemSelected(item); + } + } - /** - * Sends mail intent on contact dev preference click. - */ - @Override - public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, - Preference preference) { - if (preference == mContactDev) { - Intent i = new Intent(Intent.ACTION_SENDTO, Uri.fromParts( - "mailto", getString(R.string.contact_mail, "@", "."), null)); - startActivity(i); - return true; - } - return super.onPreferenceTreeClick(preferenceScreen, preference); - } + /** + * Sends mail intent on contact dev preference click. + */ + @Override + public boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, + Preference preference) { + if (preference == mContactDev) { + startActivity(new Intent(Intent.ACTION_SENDTO, Uri.fromParts( + "mailto", getString(R.string.contact_mail, "@", "."), null))); + return true; + } + return super.onPreferenceTreeClick(preferenceScreen, preference); + } + + /** + * Updates summary of list preference (from current item). + */ + public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { + if (key.equals(KEY_ENABLE_WIFI_ON_START)) { + mEnableWifiOnStart.setSummary(mEnableWifiOnStart.getEntry()); + } + } - /** - * Updates summary of list preference (from current item). - */ - public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { - if (key.equals(KEY_ENABLE_WIFI_ON_START)) { - mEnableWifiOnStart.setSummary(mEnableWifiOnStart.getEntry()); - } - } - } diff --git a/src/com/github/nutomic/controldlna/gui/RouteFragment.java b/src/com/github/nutomic/controldlna/gui/RouteFragment.java index 9663922..ed325f2 100644 --- a/src/com/github/nutomic/controldlna/gui/RouteFragment.java +++ b/src/com/github/nutomic/controldlna/gui/RouteFragment.java @@ -5,13 +5,13 @@ All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. + notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. * Neither the name of the nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED @@ -27,10 +27,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.github.nutomic.controldlna.gui; -import java.util.List; - -import org.teleal.cling.support.model.item.Item; - import android.app.AlertDialog; import android.content.ComponentName; 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.ProviderInfo; import android.support.v7.media.MediaRouter.RouteInfo; -import android.util.Log; import android.view.LayoutInflater; import android.view.View; 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.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, * the current playlist and playback controls. @@ -81,8 +80,8 @@ import com.github.nutomic.controldlna.utility.RouteAdapter; * */ public class RouteFragment extends MediaRouteDiscoveryFragment implements -OnBackPressedListener, OnItemClickListener, OnClickListener, -OnSeekBarChangeListener, OnScrollListener { + OnBackPressedListener, OnItemClickListener, OnClickListener, + OnSeekBarChangeListener, OnScrollListener { private ListView mListView; @@ -93,6 +92,7 @@ OnSeekBarChangeListener, OnScrollListener { private ImageButton mRepeat; private TextView mCurrentTimeView; private TextView mTotalTimeView; + private TextView mEmptyView; private View mCurrentTrackView; @@ -126,8 +126,9 @@ OnSeekBarChangeListener, OnScrollListener { mPlaylistAdapter.add(mMediaRouterPlayService.getPlaylist()); applyColors(); RouteInfo currentRoute = mMediaRouterPlayService.getCurrentRoute(); - if (currentRoute != null) + if (currentRoute != null) { playlistMode(currentRoute); + } } public void onServiceDisconnected(ComponentName className) { @@ -168,7 +169,9 @@ OnSeekBarChangeListener, OnScrollListener { mListView.setAdapter(mRouteAdapter); mListView.setOnItemClickListener(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); mProgressBar = (SeekBar) getView().findViewById(R.id.progressBar); @@ -201,19 +204,17 @@ OnSeekBarChangeListener, OnScrollListener { new Intent(getActivity(), MediaRouterPlayService.class)); getActivity().getApplicationContext().bindService( new Intent(getActivity(), MediaRouterPlayService.class), - mPlayServiceConnection, - Context.BIND_AUTO_CREATE - ); + mPlayServiceConnection, Context.BIND_AUTO_CREATE); - if (savedInstanceState != null) + if (savedInstanceState != null) { mListView.onRestoreInstanceState(savedInstanceState.getParcelable("list_state")); + } } @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); - //outState.putBoolean("route_selected", mSelectedRoute != null); outState.putParcelable("list_state", mListView.onSaveInstanceState()); } @@ -229,8 +230,8 @@ OnSeekBarChangeListener, OnScrollListener { */ @Override public int onPrepareCallbackFlags() { - return MediaRouter.CALLBACK_FLAG_REQUEST_DISCOVERY - | MediaRouter.CALLBACK_FLAG_PERFORM_ACTIVE_SCAN; + return MediaRouter.CALLBACK_FLAG_REQUEST_DISCOVERY | + MediaRouter.CALLBACK_FLAG_PERFORM_ACTIVE_SCAN; } @Override @@ -238,16 +239,18 @@ OnSeekBarChangeListener, OnScrollListener { return new MediaRouter.Callback() { @Override 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())) { mRouteAdapter.remove(mRouteAdapter.getItem(i)); break; } + } mRouteAdapter.add(route); - RouteInfo current = mMediaRouterPlayService.getCurrentRoute(); - if (current != null && route.getId().equals(current.getId())) - playlistMode(current); + RouteInfo current = mMediaRouterPlayService.getCurrentRoute(); + if (current != null && route.getId().equals(current.getId())) { + playlistMode(current); + } } @Override @@ -301,8 +304,9 @@ OnSeekBarChangeListener, OnScrollListener { */ @Override public void onItemClick(AdapterView a, View v, final int position, long id) { - if (mListView.getAdapter() == mRouteAdapter) + if (mListView.getAdapter() == mRouteAdapter) { playlistMode(mRouteAdapter.getItem(position)); + } else { mMediaRouterPlayService.play(position); changePlayPauseState(true); @@ -317,8 +321,7 @@ OnSeekBarChangeListener, OnScrollListener { mListView.setAdapter(mRouteAdapter); disableTrackHighlight(); mSelectedRoute = null; - TextView emptyView = (TextView) mListView.getEmptyView(); - emptyView.setText(R.string.route_list_empty); + mEmptyView.setText(R.string.route_list_empty); } /** @@ -334,37 +337,39 @@ OnSeekBarChangeListener, OnScrollListener { changePlayPauseState(true); mStartPlayingOnSelect = -1; } - TextView emptyView = (TextView) mListView.getEmptyView(); - emptyView.setText(R.string.playlist_empty); - mListView.post(new Runnable() { - @Override - public void run() { - scrollToCurrent(); - } - }); + mEmptyView.setText(R.string.playlist_empty); + mListView.post(new Runnable() { + @Override + public void run() { + scrollToCurrent(); + } + }); } /** * Sets colored background on the item that is currently playing. */ private void enableTrackHighlight() { - if (mListView.getAdapter() == mRouteAdapter || mMediaRouterPlayService == null || !isVisible()) + if (mListView.getAdapter() == mRouteAdapter || + mMediaRouterPlayService == null || !isVisible()) return; disableTrackHighlight(); mCurrentTrackView = mListView.getChildAt(mMediaRouterPlayService.getCurrentTrack() - mListView.getFirstVisiblePosition() + mListView.getHeaderViewsCount()); - if (mCurrentTrackView != null) + if (mCurrentTrackView != null) { mCurrentTrackView.setBackgroundColor( getResources().getColor(R.color.currently_playing_background)); + } } /** * Removes highlight from the item that was last highlighted. */ private void disableTrackHighlight() { - if (mCurrentTrackView != null) + if (mCurrentTrackView != null) { mCurrentTrackView.setBackgroundColor(Color.TRANSPARENT); + } } /** @@ -373,24 +378,25 @@ OnSeekBarChangeListener, OnScrollListener { @Override public boolean onBackPressed() { if (mListView.getAdapter() == mPlaylistAdapter) { - if (mPlaying) + if (mPlaying) { new AlertDialog.Builder(getActivity()) - .setMessage(R.string.exit_renderer) - .setPositiveButton(android.R.string.yes, - new DialogInterface.OnClickListener() { - - @Override - public void onClick(DialogInterface dialog, - int which) { - mMediaRouterPlayService.stop(); - changePlayPauseState(false); - deviceListMode(); - } - }) - .setNegativeButton(android.R.string.no, null) - .show(); - else + .setMessage(R.string.exit_renderer) + .setPositiveButton(android.R.string.yes, + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, + int which) { + mMediaRouterPlayService.stop(); + changePlayPauseState(false); + deviceListMode(); + } + }) + .setNegativeButton(android.R.string.no, null) + .show(); + } + else { deviceListMode(); + } return true; } return false; @@ -470,8 +476,9 @@ OnSeekBarChangeListener, OnScrollListener { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { - if (fromUser) + if (fromUser) { mMediaRouterPlayService.seek(progress); + } } @Override @@ -514,9 +521,10 @@ OnSeekBarChangeListener, OnScrollListener { if (mSelectedRoute != null) { mMediaRouterPlayService.play(start); changePlayPauseState(true); - } else { + } + else { Toast.makeText(getActivity(), R.string.select_route, Toast.LENGTH_SHORT) - .show(); + .show(); mStartPlayingOnSelect = start; } } @@ -528,16 +536,17 @@ OnSeekBarChangeListener, OnScrollListener { * @return Formatted time string. */ private String generateTimeString(int time) { - assert(time >= 0); int seconds = time % 60; int minutes = time / 60; - if (minutes > 99) + if (minutes > 99) { return "99:99"; - else + } + else { return Integer.toString(minutes) + ":" + - ((seconds > 9) - ? seconds + ((seconds > 9) + ? seconds : "0" + Integer.toString(seconds)); + } } /** @@ -559,13 +568,16 @@ OnSeekBarChangeListener, OnScrollListener { if (status.getPlaybackState() == MediaItemStatus.PLAYBACK_STATE_PLAYING || status.getPlaybackState() == MediaItemStatus.PLAYBACK_STATE_BUFFERING || - status.getPlaybackState() == MediaItemStatus.PLAYBACK_STATE_PENDING) + status.getPlaybackState() == MediaItemStatus.PLAYBACK_STATE_PENDING) { changePlayPauseState(true); - else + } + else { changePlayPauseState(false); + } - if (mListView.getAdapter() == mPlaylistAdapter) + if (mListView.getAdapter() == mPlaylistAdapter) { enableTrackHighlight(); + } } /** diff --git a/src/com/github/nutomic/controldlna/gui/ServerFragment.java b/src/com/github/nutomic/controldlna/gui/ServerFragment.java index 96db53f..d29c02a 100644 --- a/src/com/github/nutomic/controldlna/gui/ServerFragment.java +++ b/src/com/github/nutomic/controldlna/gui/ServerFragment.java @@ -5,13 +5,13 @@ All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. + notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. * Neither the name of the nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED @@ -27,24 +27,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 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.ComponentName; import android.content.Context; @@ -70,12 +52,30 @@ import com.github.nutomic.controldlna.gui.MainActivity.OnBackPressedListener; import com.github.nutomic.controldlna.utility.DeviceArrayAdapter; 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 * directories. - * + * * @author Felix Ableitner - * + * */ public class ServerFragment extends ListFragment implements OnBackPressedListener { @@ -107,6 +107,8 @@ public class ServerFragment extends ListFragment implements OnBackPressedListene */ private Stack mCurrentPath = new Stack(); + private TextView mEmptyView; + /** * Holds the scroll position in the list view at each directory level. */ @@ -148,7 +150,6 @@ public class ServerFragment extends ListFragment implements OnBackPressedListene @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - return inflater.inflate(R.layout.server_fragment, null); }; @@ -166,21 +167,23 @@ public class ServerFragment extends ListFragment implements OnBackPressedListene setListAdapter(mServerAdapter); getActivity().getApplicationContext().bindService( new Intent(getActivity(), AndroidUpnpServiceImpl.class), - mUpnpServiceConnection, - Context.BIND_AUTO_CREATE - ); + mUpnpServiceConnection, Context.BIND_AUTO_CREATE); IntentFilter filter = new IntentFilter(); filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION); getActivity().registerReceiver(mWifiReceiver, filter); + mEmptyView = (TextView) getListView().getEmptyView(); + if (savedInstanceState != null) { mRestoreServer = savedInstanceState.getString("current_server"); mCurrentPath.addAll(savedInstanceState.getStringArrayList("path")); mListState.addAll(savedInstanceState.getParcelableArrayList("list_state")); - } else + } + else { mListState.push(getListView().onSaveInstanceState()); + } } /** @@ -191,7 +194,7 @@ public class ServerFragment extends ListFragment implements OnBackPressedListene super.onSaveInstanceState(outState); outState.putString("current_server", (mCurrentServer != null) ? mCurrentServer.getIdentity().getUdn().toString() - : ""); + : ""); outState.putStringArrayList("path", new ArrayList(mCurrentPath)); mListState.pop(); mListState.push(getListView().onSaveInstanceState()); @@ -210,19 +213,23 @@ public class ServerFragment extends ListFragment implements OnBackPressedListene */ @Override public void onListItemClick(ListView l, View v, int position, long id) { - if (getListAdapter() == mServerAdapter) + if (getListAdapter() == mServerAdapter) { browsingMode(mServerAdapter.getItem(position)); - else if (getListAdapter() == mFileAdapter) + } + else if (getListAdapter() == mFileAdapter) { if (mFileAdapter.getItem(position) instanceof Container) getFiles(((Container) mFileAdapter.getItem(position)).getId()); else { List playlist = new ArrayList(); - for (int i = 0; i < mFileAdapter.getCount(); i++) - if (mFileAdapter.getItem(i) instanceof Item) + for (int i = 0; i < mFileAdapter.getCount(); i++) { + if (mFileAdapter.getItem(i) instanceof Item) { playlist.add((Item) mFileAdapter.getItem(i)); + } + } MainActivity activity = (MainActivity) getActivity(); activity.play(playlist, position); } + } } /** @@ -231,8 +238,7 @@ public class ServerFragment extends ListFragment implements OnBackPressedListene private void serverMode() { setListAdapter(mServerAdapter); mCurrentServer = null; - TextView emptyView = (TextView) getListView().getEmptyView(); - emptyView.setText(R.string.device_list_empty); + mEmptyView.setText(R.string.device_list_empty); getListView().onRestoreInstanceState(mListState.pop()); } @@ -243,8 +249,7 @@ public class ServerFragment extends ListFragment implements OnBackPressedListene setListAdapter(mFileAdapter); mCurrentServer = server; getFiles(ROOT_DIRECTORY); - TextView emptyView = (TextView) getListView().getEmptyView(); - emptyView.setText(R.string.folder_list_empty); + mEmptyView.setText(R.string.folder_list_empty); } /** @@ -258,7 +263,7 @@ public class ServerFragment extends ListFragment implements OnBackPressedListene /** * Displays the current directory on the ListView. - * + * * @param restoreListState True if we are going back up the directory tree, * which means we restore scroll position etc. This pops * mListState. @@ -281,14 +286,18 @@ public class ServerFragment extends ListFragment implements OnBackPressedListene @Override public void run() { mFileAdapter.clear(); - for (Container c : didl.getContainers()) + for (Container c : didl.getContainers()) { mFileAdapter.add(c); - for (Item i : didl.getItems()) + } + for (Item i : didl.getItems()) { mFileAdapter.add(i); - if (restoreListState) + } + if (restoreListState) { getListView().onRestoreInstanceState(mListState.pop()); - else + } + else { getListView().setSelectionFromTop(0, 0); + } } }); } @@ -317,10 +326,12 @@ public class ServerFragment extends ListFragment implements OnBackPressedListene return false; mCurrentPath.pop(); - if (mCurrentPath.empty()) + if (mCurrentPath.empty()) { serverMode(); - else + } + else { getFiles(true); + } return true; } @@ -340,11 +351,13 @@ public class ServerFragment extends ListFragment implements OnBackPressedListene if (wifi.isConnected()) { if (mUpnpService != null) { for (Device d : mUpnpService.getControlPoint() - .getRegistry().getDevices()) + .getRegistry().getDevices()) { mServerAdapter.deviceAdded(d); + } mUpnpService.getControlPoint().search(); } - } else + } + else { for (int i = 0; i < mServerAdapter.getCount(); i++) { Device d = mServerAdapter.getItem(i); UDN udn = new UDN(d.getIdentity().getUdn().toString()); @@ -358,6 +371,7 @@ public class ServerFragment extends ListFragment implements OnBackPressedListene } } } + } } }; diff --git a/src/com/github/nutomic/controldlna/localroute/Controller.java b/src/com/github/nutomic/controldlna/localroute/Controller.java index efa2208..474f59a 100644 --- a/src/com/github/nutomic/controldlna/localroute/Controller.java +++ b/src/com/github/nutomic/controldlna/localroute/Controller.java @@ -4,14 +4,14 @@ All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED @@ -27,8 +27,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.github.nutomic.controldlna.localroute; -import java.io.IOException; - import android.content.Context; import android.content.Intent; import android.media.AudioManager; @@ -41,13 +39,15 @@ import android.support.v7.media.MediaRouteProvider; import android.support.v7.media.MediaRouter.ControlRequestCallback; import android.util.Log; +import java.io.IOException; + /** * Receives control intents through media route and executes them on a MediaPlayer. - * + * * @author felix * */ -public class Controller extends MediaRouteProvider.RouteController implements +public class Controller extends MediaRouteProvider.RouteController implements MediaPlayer.OnCompletionListener, MediaPlayer.OnPreparedListener { private static final String TAG = "Controller"; @@ -55,104 +55,106 @@ public class Controller extends MediaRouteProvider.RouteController implements private Context mContext; private AudioManager mAudio; - - AudioManager.OnAudioFocusChangeListener mFocusListener; + + AudioManager.OnAudioFocusChangeListener mFocusListener; - private final String mRouteId; - - private String mItemId; - - private int mState; - + private final String mRouteId; + + private String mItemId; + + private int mState; + private MediaPlayer mPlayer = new MediaPlayer(); - public Controller(String routeId, Context context) { - mContext = context; - mRouteId = routeId; - mAudio = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); - mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); - mPlayer.setOnPreparedListener(this); - } + public Controller(String routeId, Context context) { + mContext = context; + mRouteId = routeId; + mAudio = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); + mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); + mPlayer.setOnPreparedListener(this); + } - @Override - public void onRelease() { - mPlayer.release(); - } + @Override + public void onRelease() { + mPlayer.release(); + } - @Override - public void onSelect() { - mAudio.requestAudioFocus(mFocusListener, AudioManager.STREAM_MUSIC, - AudioManager.AUDIOFOCUS_GAIN); - } + @Override + public void onSelect() { + mAudio.requestAudioFocus(mFocusListener, AudioManager.STREAM_MUSIC, + AudioManager.AUDIOFOCUS_GAIN); + } - @Override - public void onUnselect() { - mAudio.abandonAudioFocus(mFocusListener); - } + @Override + public void onUnselect() { + mAudio.abandonAudioFocus(mFocusListener); + } - @Override - public void onSetVolume(int volume) { - mAudio.setStreamVolume(AudioManager.STREAM_MUSIC, volume, 0); - } + @Override + public void onSetVolume(int volume) { + mAudio.setStreamVolume(AudioManager.STREAM_MUSIC, volume, 0); + } - @Override - public void onUpdateVolume(int delta) { - int currentVolume = mAudio.getStreamVolume(AudioManager.STREAM_MUSIC); - mAudio.setStreamVolume(AudioManager.STREAM_MUSIC, currentVolume + delta, 0); - } + @Override + public void onUpdateVolume(int delta) { + int currentVolume = mAudio.getStreamVolume(AudioManager.STREAM_MUSIC); + mAudio.setStreamVolume(AudioManager.STREAM_MUSIC, currentVolume + delta, 0); + } - @Override - public boolean onControlRequest(Intent intent, ControlRequestCallback callback) { - String sessionId = intent.getStringExtra(MediaControlIntent.EXTRA_SESSION_ID); - String itemId = intent.getStringExtra(MediaControlIntent.EXTRA_ITEM_ID); - if (intent.getAction().equals(MediaControlIntent.ACTION_PLAY)) { - try { - mPlayer.reset(); + @Override + public boolean onControlRequest(Intent intent, ControlRequestCallback callback) { + String sessionId = intent.getStringExtra(MediaControlIntent.EXTRA_SESSION_ID); + String itemId = intent.getStringExtra(MediaControlIntent.EXTRA_ITEM_ID); + if (intent.getAction().equals(MediaControlIntent.ACTION_PLAY)) { + try { + mPlayer.reset(); mPlayer.setDataSource(mContext, intent.getData()); mPlayer.prepareAsync(); mItemId = intent.getDataString(); mState = MediaItemStatus.PLAYBACK_STATE_BUFFERING; getStatus(mItemId, mRouteId, callback); - return true; - } catch (IllegalArgumentException e) { - mState = MediaItemStatus.PLAYBACK_STATE_ERROR; - Log.d(TAG, "Failed to start playback", e); - } catch (IOException e) { + return true; + } + catch (IllegalArgumentException e) { mState = MediaItemStatus.PLAYBACK_STATE_ERROR; Log.d(TAG, "Failed to start playback", e); } - } - else if (intent.getAction().equals(MediaControlIntent.ACTION_PAUSE)) { - mPlayer.pause(); - mState = MediaItemStatus.PLAYBACK_STATE_PAUSED; - return true; - } - else if (intent.getAction().equals(MediaControlIntent.ACTION_RESUME)) { - mPlayer.start(); - mState = MediaItemStatus.PLAYBACK_STATE_PLAYING; - return true; - } - else if (intent.getAction().equals(MediaControlIntent.ACTION_STOP)) { - mPlayer.stop(); - mState = MediaItemStatus.PLAYBACK_STATE_CANCELED; - return true; - } - else if (intent.getAction().equals(MediaControlIntent.ACTION_SEEK)) { - mPlayer.seekTo((int) intent.getLongExtra( - MediaControlIntent.EXTRA_ITEM_CONTENT_POSITION, 0)); - getStatus(itemId, sessionId, callback); - return true; - } - else if(intent.getAction().equals(MediaControlIntent.ACTION_GET_STATUS)) { - getStatus(itemId, sessionId, callback); - return true; - } + catch (IOException e) { + mState = MediaItemStatus.PLAYBACK_STATE_ERROR; + Log.d(TAG, "Failed to start playback", e); + } + } + else if (intent.getAction().equals(MediaControlIntent.ACTION_PAUSE)) { + mPlayer.pause(); + mState = MediaItemStatus.PLAYBACK_STATE_PAUSED; + return true; + } + else if (intent.getAction().equals(MediaControlIntent.ACTION_RESUME)) { + mPlayer.start(); + mState = MediaItemStatus.PLAYBACK_STATE_PLAYING; + return true; + } + else if (intent.getAction().equals(MediaControlIntent.ACTION_STOP)) { + mPlayer.stop(); + mState = MediaItemStatus.PLAYBACK_STATE_CANCELED; + return true; + } + else if (intent.getAction().equals(MediaControlIntent.ACTION_SEEK)) { + mPlayer.seekTo((int) intent.getLongExtra( + MediaControlIntent.EXTRA_ITEM_CONTENT_POSITION, 0)); + getStatus(itemId, sessionId, callback); + return true; + } + else if(intent.getAction().equals(MediaControlIntent.ACTION_GET_STATUS)) { + getStatus(itemId, sessionId, callback); + return true; + } return false; - } - - private void getStatus(String itemId, String sessionId, ControlRequestCallback callback) { - if (callback == null) - return; + } + + private void getStatus(String itemId, String sessionId, ControlRequestCallback callback) { + if (callback == null) + return; Bundle status = null; @@ -161,24 +163,26 @@ public class Controller extends MediaRouteProvider.RouteController implements .setContentPosition(mPlayer.getCurrentPosition()) .setContentDuration(mPlayer.getDuration()) .setTimestamp(SystemClock.elapsedRealtime()) - .build().asBundle(); + .build() + .asBundle(); status.putString(MediaControlIntent.EXTRA_SESSION_ID, mRouteId); status.putString(MediaControlIntent.EXTRA_ITEM_ID, mItemId); } - else + else { status = new MediaItemStatus.Builder(MediaItemStatus.PLAYBACK_STATE_INVALIDATED) .build().asBundle(); + } - callback.onResult(status); - } + callback.onResult(status); + } - /** - * Sets state to finished. - * - * Note: Do not set the listener before play() is called - * (or this will be called immediately). - */ + /** + * Sets state to finished. + * + * Note: Do not set the listener before play() is called + * (or this will be called immediately). + */ @Override public void onCompletion(MediaPlayer mp) { mState = MediaItemStatus.PLAYBACK_STATE_FINISHED; @@ -191,7 +195,7 @@ public class Controller extends MediaRouteProvider.RouteController implements @Override public void onPrepared(MediaPlayer mp) { mPlayer.start(); - mState = MediaItemStatus.PLAYBACK_STATE_PLAYING; - mPlayer.setOnCompletionListener(this); + mState = MediaItemStatus.PLAYBACK_STATE_PLAYING; + mPlayer.setOnCompletionListener(this); } } diff --git a/src/com/github/nutomic/controldlna/localroute/Provider.java b/src/com/github/nutomic/controldlna/localroute/Provider.java index b4171d7..db25e51 100644 --- a/src/com/github/nutomic/controldlna/localroute/Provider.java +++ b/src/com/github/nutomic/controldlna/localroute/Provider.java @@ -4,14 +4,14 @@ All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED @@ -43,63 +43,64 @@ import android.support.v7.media.MediaRouter; import com.github.nutomic.controldlna.R; /** - * MediaRouteProvider that details the local audio route with its - * controls to the system. - * + * MediaRouteProvider that details the local audio route with its + * controls to the system. + * * @author felix * */ final class Provider extends MediaRouteProvider { - private static final String ROUTE_ID = "local_route"; - - AudioManager mAudio = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE); + private static final String ROUTE_ID = "local_route"; - private static final ArrayList CONTROL_FILTERS; - static { - IntentFilter f = new IntentFilter(); - f.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK); - f.addAction(MediaControlIntent.ACTION_PLAY); - f.addAction(MediaControlIntent.ACTION_PAUSE); - f.addAction(MediaControlIntent.ACTION_SEEK); - f.addAction(MediaControlIntent.ACTION_STOP); - f.addDataScheme("http"); - f.addDataScheme("https"); - addDataTypeUnchecked(f, "audio/*"); + AudioManager mAudio = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE); - CONTROL_FILTERS = new ArrayList(); - CONTROL_FILTERS.add(f); - } + private static final ArrayList CONTROL_FILTERS; + static { + IntentFilter f = new IntentFilter(); + f.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK); + f.addAction(MediaControlIntent.ACTION_PLAY); + f.addAction(MediaControlIntent.ACTION_PAUSE); + f.addAction(MediaControlIntent.ACTION_SEEK); + f.addAction(MediaControlIntent.ACTION_STOP); + f.addDataScheme("http"); + f.addDataScheme("https"); + addDataTypeUnchecked(f, "audio/*"); - private static void addDataTypeUnchecked(IntentFilter filter, String type) { - try { - filter.addDataType(type); - } catch (MalformedMimeTypeException ex) { - throw new RuntimeException(ex); - } - } + CONTROL_FILTERS = new ArrayList(); + CONTROL_FILTERS.add(f); + } - public Provider(Context context) { - super(context); + private static void addDataTypeUnchecked(IntentFilter filter, String type) { + try { + filter.addDataType(type); + } + catch (MalformedMimeTypeException ex) { + throw new RuntimeException(ex); + } + } - MediaRouteDescriptor routeDescriptor = new MediaRouteDescriptor.Builder( - ROUTE_ID, context.getResources().getString(R.string.local_device)) - .addControlFilters(CONTROL_FILTERS) - .setPlaybackType(MediaRouter.RouteInfo.PLAYBACK_TYPE_REMOTE) - .setVolumeHandling(MediaRouter.RouteInfo.PLAYBACK_VOLUME_VARIABLE) - .setVolume(mAudio.getStreamMaxVolume(AudioManager.STREAM_MUSIC)) - .build(); - + public Provider(Context context) { + super(context); - MediaRouteProviderDescriptor providerDescriptor = - new MediaRouteProviderDescriptor.Builder() - .addRoute(routeDescriptor) - .build(); - setDescriptor(providerDescriptor); - } + MediaRouteDescriptor routeDescriptor = new MediaRouteDescriptor.Builder( + ROUTE_ID, context.getResources().getString(R.string.local_device)) + .addControlFilters(CONTROL_FILTERS) + .setPlaybackType(MediaRouter.RouteInfo.PLAYBACK_TYPE_REMOTE) + .setVolumeHandling(MediaRouter.RouteInfo.PLAYBACK_VOLUME_VARIABLE) + .setVolume(mAudio.getStreamMaxVolume(AudioManager.STREAM_MUSIC)) + .build(); - @Override - public RouteController onCreateRouteController(String routeId) { - return new Controller(routeId, getContext()); - } + + MediaRouteProviderDescriptor providerDescriptor = + new MediaRouteProviderDescriptor.Builder() + .addRoute(routeDescriptor) + .build(); + setDescriptor(providerDescriptor); + } + + @Override + public RouteController onCreateRouteController(String routeId) { + return new Controller(routeId, getContext()); + } } \ No newline at end of file diff --git a/src/com/github/nutomic/controldlna/localroute/ProviderService.java b/src/com/github/nutomic/controldlna/localroute/ProviderService.java index 53eaa3b..5c704a9 100644 --- a/src/com/github/nutomic/controldlna/localroute/ProviderService.java +++ b/src/com/github/nutomic/controldlna/localroute/ProviderService.java @@ -4,14 +4,14 @@ All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED @@ -36,8 +36,9 @@ public class ProviderService extends MediaRouteProviderService { @Override public MediaRouteProvider onCreateMediaRouteProvider() { - if (mProvider == null) + if (mProvider == null) { mProvider = new Provider(this); + } return mProvider; } diff --git a/src/com/github/nutomic/controldlna/mediarouter/MediaRouterPlayService.java b/src/com/github/nutomic/controldlna/mediarouter/MediaRouterPlayService.java index d9e31fb..307f688 100644 --- a/src/com/github/nutomic/controldlna/mediarouter/MediaRouterPlayService.java +++ b/src/com/github/nutomic/controldlna/mediarouter/MediaRouterPlayService.java @@ -5,13 +5,13 @@ All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. + notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. * Neither the name of the nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED @@ -27,17 +27,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 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.PendingIntent; import android.app.Service; @@ -66,9 +55,20 @@ import com.github.nutomic.controldlna.gui.PreferencesActivity; import com.github.nutomic.controldlna.gui.RouteFragment; 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. - * + * * @author Felix Ableitner * */ @@ -120,22 +120,24 @@ public class MediaRouterPlayService extends Service { new MediaRouter.Callback() { @Override public void onRouteRemoved(MediaRouter router, RouteInfo route) { - if (route.equals(mCurrentRoute)) + if (route.equals(mCurrentRoute)) { stopForeground(true); + } - if (!mBound && !mPollingStatus) + if (!mBound && !mPollingStatus) { stopSelf(); + } } - @Override - public void onRouteAdded(MediaRouter router, RouteInfo route) { - if (route.getId().equals(mCurrentRoute.getId())) { - selectRoute(route); - new CreateNotificationTask().execute(mPlaylist.get(mCurrentTrack) - .getFirstPropertyValue(DIDLObject.Property.UPNP.ALBUM_ART_URI.class)); - } - } - }; + @Override + public void onRouteAdded(MediaRouter router, RouteInfo route) { + if (route.getId().equals(mCurrentRoute.getId())) { + selectRoute(route); + new CreateNotificationTask().execute(mPlaylist.get(mCurrentTrack) + .getFirstPropertyValue(DIDLObject.Property.UPNP.ALBUM_ART_URI.class)); + } + } + }; /** * Creates a notification after the icon bitmap is loaded. @@ -150,15 +152,16 @@ public class MediaRouterPlayService extends Service { title = mPlaylist.get(mCurrentTrack).getTitle(); if (mPlaylist.get(mCurrentTrack) instanceof MusicTrack) { MusicTrack track = (MusicTrack) mPlaylist.get(mCurrentTrack); - if (track.getArtists().length > 0) + if (track.getArtists().length > 0) { artist = track.getArtists()[0].getName(); + } } } Intent intent = new Intent(MediaRouterPlayService.this, MainActivity.class); intent.setAction("showRouteFragment"); Notification notification = new NotificationCompat.Builder(MediaRouterPlayService.this) - .setContentIntent(PendingIntent.getActivity(MediaRouterPlayService.this, 0, - intent, 0)) + .setContentIntent(PendingIntent.getActivity(MediaRouterPlayService.this, 0, + intent, 0)) .setContentTitle(title) .setContentText(artist) .setLargeIcon(result) @@ -170,35 +173,35 @@ public class MediaRouterPlayService extends Service { } - /** - * Listens for incoming phone calls and pauses playback then. - */ - private class PhoneCallListener extends PhoneStateListener { + /** + * Listens for incoming phone calls and pauses playback then. + */ + private class PhoneCallListener extends PhoneStateListener { - private boolean mPausedForCall = false; + private boolean mPausedForCall = false; - @Override - public void onCallStateChanged(int state, String incomingNumber) { + @Override + public void onCallStateChanged(int state, String incomingNumber) { - if (!PreferenceManager.getDefaultSharedPreferences(MediaRouterPlayService.this) - .getBoolean(PreferencesActivity.KEY_INCOMING_PHONE_CALL_PAUSE, true)) { - return; - } + if (!PreferenceManager.getDefaultSharedPreferences(MediaRouterPlayService.this) + .getBoolean(PreferencesActivity.KEY_INCOMING_PHONE_CALL_PAUSE, true)) { + return; + } - if (TelephonyManager.CALL_STATE_RINGING == state || - TelephonyManager.CALL_STATE_OFFHOOK == state) { - // phone ringing or call active - pause(); - mPausedForCall = true; - } + if (TelephonyManager.CALL_STATE_RINGING == state || + TelephonyManager.CALL_STATE_OFFHOOK == state) { + // phone ringing or call active + pause(); + mPausedForCall = true; + } - if (mPausedForCall && TelephonyManager.CALL_STATE_IDLE == state) { - // run when class initial and phone call ended - resume(); - mPausedForCall = false; - } - } - } + if (mPausedForCall && TelephonyManager.CALL_STATE_IDLE == state) { + // run when class initial and phone call ended + resume(); + mPausedForCall = false; + } + } + } @Override public void onCreate() { @@ -206,11 +209,10 @@ public class MediaRouterPlayService extends Service { mMediaRouter = MediaRouter.getInstance(this); pollStatus(); - PhoneCallListener phoneListener = new PhoneCallListener(); - TelephonyManager telephonyManager = (TelephonyManager) this - .getSystemService(Context.TELEPHONY_SERVICE); - telephonyManager.listen(phoneListener, - PhoneStateListener.LISTEN_CALL_STATE); + PhoneCallListener phoneListener = new PhoneCallListener(); + TelephonyManager telephonyManager = + (TelephonyManager) this.getSystemService(Context.TELEPHONY_SERVICE); + telephonyManager.listen(phoneListener, PhoneStateListener.LISTEN_CALL_STATE); } @Override @@ -225,8 +227,9 @@ public class MediaRouterPlayService extends Service { */ @Override public boolean onUnbind(Intent intent) { - if (!mPollingStatus) + if (!mPollingStatus) { stopSelf(); + } mBound = false; return super.onUnbind(intent); } @@ -239,8 +242,8 @@ public class MediaRouterPlayService extends Service { mMediaRouter.removeCallback(mRouteRemovedCallback); mMediaRouter.selectRoute(route); MediaRouteSelector selector = new MediaRouteSelector.Builder() - .addControlCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK) - .build(); + .addControlCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK) + .build(); mMediaRouter.addCallback(selector, mRouteRemovedCallback, 0); mCurrentRoute = route; @@ -287,8 +290,9 @@ public class MediaRouterPlayService extends Service { new CreateNotificationTask().execute(mPlaylist.get(mCurrentTrack) .getFirstPropertyValue(DIDLObject.Property.UPNP.ALBUM_ART_URI.class)); - if (mRouterFragment.get() != null) + if (mRouterFragment.get() != null) { mRouterFragment.get().scrollToCurrent(); + } } }); } @@ -347,23 +351,25 @@ public class MediaRouterPlayService extends Service { intent.addCategory(MediaControlIntent.CATEGORY_REMOTE_PLAYBACK); intent.putExtra(MediaControlIntent.EXTRA_SESSION_ID, mSessionId); intent.putExtra(MediaControlIntent.EXTRA_ITEM_ID, mItemId); - intent.putExtra(MediaControlIntent.EXTRA_ITEM_CONTENT_POSITION, - (long) seconds * 1000); + intent.putExtra(MediaControlIntent.EXTRA_ITEM_CONTENT_POSITION, (long) seconds * 1000); mMediaRouter.getSelectedRoute().sendControlRequest(intent, null); } /** * Sets a new playlist and starts playing. - * + * * @param playlist The media files in the playlist. */ public void setPlaylist(List playlist) { + + + mPlaylist = playlist; } /** * Plays the track after current in the playlist. - * + * * @return True if another item is played, false if the end * of the playlist is reached. */ @@ -389,8 +395,9 @@ public class MediaRouterPlayService extends Service { else { // Playlist over, stop playback. stop(); - if (!mBound) + if (!mBound) { stopSelf(); + } mPollingStatus = false; return false; } @@ -404,11 +411,13 @@ public class MediaRouterPlayService extends Service { if (mCurrentTrack == -1) return; - if (mShuffle) + if (mShuffle) { // Play random item. play(new Random().nextInt(mPlaylist.size())); - else + } + else { play(mCurrentTrack - 1); + } } /** @@ -437,16 +446,19 @@ public class MediaRouterPlayService extends Service { if (status == null) return; - if (mRouterFragment.get() != null) + if (mRouterFragment.get() != null) { mRouterFragment.get().receivePlaybackStatus(status); + } if (status.getPlaybackState() != MediaItemStatus.PLAYBACK_STATE_PENDING && status.getPlaybackState() != MediaItemStatus.PLAYBACK_STATE_BUFFERING && - status.getPlaybackState() != MediaItemStatus.PLAYBACK_STATE_PLAYING) + status.getPlaybackState() != MediaItemStatus.PLAYBACK_STATE_PLAYING) { stopForeground(true); + } if (status.getPlaybackState() == MediaItemStatus.PLAYBACK_STATE_FINISHED || - status.getPlaybackState() == MediaItemStatus.PLAYBACK_STATE_CANCELED) + status.getPlaybackState() == MediaItemStatus.PLAYBACK_STATE_CANCELED) { playNext(); + } } }); } diff --git a/src/com/github/nutomic/controldlna/mediarouter/MediaRouterPlayServiceBinder.java b/src/com/github/nutomic/controldlna/mediarouter/MediaRouterPlayServiceBinder.java index 4e98dbb..34fbf16 100644 --- a/src/com/github/nutomic/controldlna/mediarouter/MediaRouterPlayServiceBinder.java +++ b/src/com/github/nutomic/controldlna/mediarouter/MediaRouterPlayServiceBinder.java @@ -5,13 +5,13 @@ All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. + notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. * Neither the name of the nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED @@ -31,7 +31,7 @@ import android.os.Binder; /** * Provides connection to PlayService. - * + * * @author Felix Ableitner * */ diff --git a/src/com/github/nutomic/controldlna/upnp/IRemotePlayService.aidl b/src/com/github/nutomic/controldlna/upnp/IRemotePlayService.aidl index 757a69b..499896c 100644 --- a/src/com/github/nutomic/controldlna/upnp/IRemotePlayService.aidl +++ b/src/com/github/nutomic/controldlna/upnp/IRemotePlayService.aidl @@ -4,14 +4,14 @@ All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED @@ -24,11 +24,11 @@ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - + package com.github.nutomic.controldlna.upnp; import android.os.Messenger; - + interface IRemotePlayService { void startSearch(in Messenger listener); void selectRenderer(String id); diff --git a/src/com/github/nutomic/controldlna/upnp/Provider.java b/src/com/github/nutomic/controldlna/upnp/Provider.java index 8cecb9c..42bb069 100644 --- a/src/com/github/nutomic/controldlna/upnp/Provider.java +++ b/src/com/github/nutomic/controldlna/upnp/Provider.java @@ -5,13 +5,13 @@ All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. + notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. * Neither the name of the nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED @@ -27,12 +27,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 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.Context; 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.MediaRouter; import android.support.v7.media.MediaRouter.ControlRequestCallback; +import android.util.Log; import android.util.Pair; import android.util.SparseArray; 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. * @@ -65,6 +66,8 @@ import android.widget.Toast; */ final class Provider extends MediaRouteProvider { + private static final String TAG = "Provider"; + // Device has been added. // param: Device device public static final int MSG_RENDERER_ADDED = 1; @@ -93,8 +96,8 @@ final class Provider extends MediaRouteProvider { public int volume; public int volumeMax; - public static final Parcelable.Creator CREATOR - = new Parcelable.Creator() { + public static final Parcelable.Creator CREATOR = + new Parcelable.Creator() { public Device createFromParcel(Parcel in) { return new Device(in); } @@ -187,8 +190,9 @@ final class Provider extends MediaRouteProvider { @Override public void handleMessage(Message msg) { - if (mService.get() != null) + if (mService.get() != null) { mService.get().handleMessage(msg); + } } } @@ -196,11 +200,8 @@ final class Provider extends MediaRouteProvider { public Provider(Context context) { super(context); - context.bindService( - new Intent(context, RemotePlayService.class), - mConnection, - Context.BIND_AUTO_CREATE - ); + context.bindService(new Intent(context, RemotePlayService.class), + mConnection, Context.BIND_AUTO_CREATE); } public void close() { @@ -210,9 +211,11 @@ final class Provider extends MediaRouteProvider { @Override public void onDiscoveryRequestChanged(MediaRouteDiscoveryRequest request) { try { - if (request != null && request.isActiveScan() && mIRemotePlayService != null) + if (request != null && request.isActiveScan() && mIRemotePlayService != null) { mIRemotePlayService.startSearch(mListener); - } catch (RemoteException e) { + } + } + catch (RemoteException e) { e.printStackTrace(); } } @@ -259,7 +262,8 @@ final class Provider extends MediaRouteProvider { public void onSelect() { try { mIRemotePlayService.selectRenderer(mRouteId); - } catch (RemoteException e) { + } + catch (RemoteException e) { e.printStackTrace(); } } @@ -268,7 +272,8 @@ final class Provider extends MediaRouteProvider { public void onUnselect() { try { mIRemotePlayService.unselectRenderer(mRouteId); - } catch (RemoteException e) { + } + catch (RemoteException e) { e.printStackTrace(); } } @@ -280,7 +285,8 @@ final class Provider extends MediaRouteProvider { try { mIRemotePlayService.setVolume(volume); - } catch (RemoteException e) { + } + catch (RemoteException e) { e.printStackTrace(); } mDevices.get(mRouteId).volume = volume; @@ -301,13 +307,13 @@ final class Provider extends MediaRouteProvider { if (intent.getAction().equals(MediaControlIntent.ACTION_PLAY)) { String metadata = (intent.hasExtra(MediaControlIntent.EXTRA_ITEM_METADATA)) ? intent.getExtras().getString(MediaControlIntent.EXTRA_ITEM_METADATA) - : null; - mIRemotePlayService.play(intent.getDataString(), metadata); - // Store in intent extras for later. - intent.putExtra(MediaControlIntent.EXTRA_SESSION_ID, mRouteId); - intent.putExtra(MediaControlIntent.EXTRA_ITEM_ID, intent.getDataString()); - getItemStatus(intent, callback); - return true; + : null; + mIRemotePlayService.play(intent.getDataString(), metadata); + // Store in intent extras for later. + intent.putExtra(MediaControlIntent.EXTRA_SESSION_ID, mRouteId); + intent.putExtra(MediaControlIntent.EXTRA_ITEM_ID, intent.getDataString()); + getItemStatus(intent, callback); + return true; } else if (intent.getAction().equals(MediaControlIntent.ACTION_PAUSE)) { mIRemotePlayService.pause(mRouteId); @@ -323,10 +329,8 @@ final class Provider extends MediaRouteProvider { } else if (intent.getAction().equals(MediaControlIntent.ACTION_SEEK)) { mIRemotePlayService.seek(mRouteId, - intent.getStringExtra( - MediaControlIntent.EXTRA_ITEM_ID), - intent.getLongExtra( - MediaControlIntent.EXTRA_ITEM_CONTENT_POSITION, 0)); + intent.getStringExtra(MediaControlIntent.EXTRA_ITEM_ID), + intent.getLongExtra(MediaControlIntent.EXTRA_ITEM_CONTENT_POSITION, 0)); getItemStatus(intent, callback); return true; } @@ -334,8 +338,9 @@ final class Provider extends MediaRouteProvider { getItemStatus(intent, callback); return true; } - } catch (RemoteException e) { - e.printStackTrace(); + } + catch (RemoteException e) { + Log.w(TAG, "Failed to execute control request", e); } return false; } @@ -357,8 +362,7 @@ final class Provider extends MediaRouteProvider { mRequests.put(r, pair); mIRemotePlayService.getItemStatus( intent.getStringExtra(MediaControlIntent.EXTRA_SESSION_ID), - intent.getStringExtra(MediaControlIntent.EXTRA_ITEM_ID), - r); + intent.getStringExtra(MediaControlIntent.EXTRA_ITEM_ID), r); } /** @@ -382,12 +386,14 @@ final class Provider extends MediaRouteProvider { mRequests.get(data.getInt("hash")); 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, 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, pair.first.getStringExtra(MediaControlIntent.EXTRA_ITEM_ID)); + } pair.second.onResult(status); break; case MSG_ERROR: diff --git a/src/com/github/nutomic/controldlna/upnp/ProviderService.java b/src/com/github/nutomic/controldlna/upnp/ProviderService.java index 44085f0..90b7ca6 100644 --- a/src/com/github/nutomic/controldlna/upnp/ProviderService.java +++ b/src/com/github/nutomic/controldlna/upnp/ProviderService.java @@ -5,13 +5,13 @@ All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. + notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. * Neither the name of the nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED @@ -36,8 +36,9 @@ public class ProviderService extends MediaRouteProviderService { @Override public MediaRouteProvider onCreateMediaRouteProvider() { - if (mProvider == null) + if (mProvider == null) { mProvider = new Provider(this); + } return mProvider; } diff --git a/src/com/github/nutomic/controldlna/upnp/RemotePlayService.java b/src/com/github/nutomic/controldlna/upnp/RemotePlayService.java index 967cbff..6a64065 100644 --- a/src/com/github/nutomic/controldlna/upnp/RemotePlayService.java +++ b/src/com/github/nutomic/controldlna/upnp/RemotePlayService.java @@ -5,13 +5,13 @@ All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. + notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. * Neither the name of the nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED @@ -64,7 +64,7 @@ import android.util.Log; /** * Allows UPNP playback from different apps by providing a proxy interface. * You can communicate to this service via RemotePlayServiceBinder. - * + * * @author Felix Ableitner * */ @@ -87,11 +87,14 @@ public class RemotePlayService extends Service implements RegistryListener { public void onServiceConnected(ComponentName className, IBinder service) { mUpnpService = (AndroidUpnpService) service; mUpnpService.getRegistry().addListener(RemotePlayService.this); - for (Device d : mUpnpService.getControlPoint().getRegistry().getDevices()) - if (d instanceof LocalDevice) + for (Device d : mUpnpService.getControlPoint().getRegistry().getDevices()) { + if (d instanceof LocalDevice) { localDeviceAdded(mUpnpService.getRegistry(), (LocalDevice) d); - else + } + else { remoteDeviceAdded(mUpnpService.getRegistry(), (RemoteDevice) d); + } + } mUpnpService.getControlPoint().search(); } @@ -119,11 +122,8 @@ public class RemotePlayService extends Service implements RegistryListener { @Override public void onCreate() { super.onCreate(); - bindService( - new Intent(this, AndroidUpnpServiceImpl.class), - mUpnpServiceConnection, - Context.BIND_AUTO_CREATE - ); + bindService(new Intent(this, AndroidUpnpServiceImpl.class), + mUpnpServiceConnection, Context.BIND_AUTO_CREATE); IntentFilter filter = new IntentFilter(); filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); @@ -144,7 +144,8 @@ public class RemotePlayService extends Service implements RegistryListener { void sendMessage(Message msg) { try { mListener.send(msg); - } catch (RemoteException e) { + } + catch (RemoteException e) { e.printStackTrace(); } } @@ -173,21 +174,28 @@ public class RemotePlayService extends Service implements RegistryListener { if (wifi.isConnected()) { if (mUpnpService != null) { - for (Device d : mUpnpService.getControlPoint().getRegistry().getDevices()) + for (Device d : + mUpnpService.getControlPoint().getRegistry().getDevices()) { deviceAdded(d); + } mUpnpService.getControlPoint().search(); } - } else - for (Entry> d : mDevices.entrySet()) + } + else { + for (Entry> d : mDevices.entrySet()) { if (mUpnpService.getControlPoint().getRegistry() .getDevice(new UDN(d.getKey()), false) == null) { deviceRemoved(d.getValue()); - for (RemotePlayServiceBinder b : mBinders.keySet()) - if (b.mCurrentRenderer != null && b.mCurrentRenderer.equals(d.getValue())) { + for (RemotePlayServiceBinder b : mBinders.keySet()) { + if (b.mCurrentRenderer != null && + b.mCurrentRenderer.equals(d.getValue())) { b.mSubscriptionCallback.end(); b.mCurrentRenderer = null; } + } } + } + } } }; @@ -196,8 +204,7 @@ public class RemotePlayService extends Service implements RegistryListener { */ org.teleal.cling.model.meta.Service getService( Device device, String name) { - return device.findService( - new ServiceType("schemas-upnp-org", name)); + return device.findService(new ServiceType("schemas-upnp-org", name)); } /** @@ -207,8 +214,7 @@ public class RemotePlayService extends Service implements RegistryListener { if (mDevices.containsValue(device)) return; - final org.teleal.cling.model.meta.Service rc = - getService(device, "RenderingControl"); + final org.teleal.cling.model.meta.Service rc = getService(device, "RenderingControl"); if (rc == null || mListener == null) return; @@ -233,7 +239,8 @@ public class RemotePlayService extends Service implements RegistryListener { int maxVolume = 100; if (rc.getStateVariable("Volume") != null) { StateVariableAllowedValueRange volumeRange = - rc.getStateVariable("Volume").getTypeDetails().getAllowedValueRange(); + rc.getStateVariable("Volume") + .getTypeDetails().getAllowedValueRange(); maxVolume = (int) volumeRange.getMaximum(); } diff --git a/src/com/github/nutomic/controldlna/upnp/RemotePlayServiceBinder.java b/src/com/github/nutomic/controldlna/upnp/RemotePlayServiceBinder.java index f14c948..9b05106 100644 --- a/src/com/github/nutomic/controldlna/upnp/RemotePlayServiceBinder.java +++ b/src/com/github/nutomic/controldlna/upnp/RemotePlayServiceBinder.java @@ -5,13 +5,13 @@ All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. + notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. * Neither the name of the nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED @@ -83,26 +83,27 @@ public class RemotePlayServiceBinder extends IRemotePlayService.Stub { private RemotePlayService mRps; private boolean mStartingPlayback = false; + public RemotePlayServiceBinder(RemotePlayService rps) { mRps = rps; } @Override - public void startSearch(Messenger listener) - throws RemoteException { + public void startSearch(Messenger listener) throws RemoteException { mRps.mListener = listener; } @Override public void selectRenderer(String id) throws RemoteException { mCurrentRenderer = mRps.mDevices.get(id); - for (RemotePlayServiceBinder b : mRps.mBinders.keySet()) - if (b != this && mCurrentRenderer.equals(b.mCurrentRenderer)) + for (RemotePlayServiceBinder b : mRps.mBinders.keySet()) { + if (b != this && mCurrentRenderer.equals(b.mCurrentRenderer)) { b.unselectRenderer(""); + } + } - mSubscriptionCallback = new SubscriptionCallback( - mCurrentRenderer.findService( - new ServiceType("schemas-upnp-org", "AVTransport")), 600) { + mSubscriptionCallback = new SubscriptionCallback(mCurrentRenderer.findService( + new ServiceType("schemas-upnp-org", "AVTransport")), 600) { @SuppressWarnings("rawtypes") @Override @@ -111,8 +112,7 @@ public class RemotePlayServiceBinder extends IRemotePlayService.Stub { @SuppressWarnings("rawtypes") @Override - protected void ended(GENASubscription sub, CancelReason reason, - UpnpResponse response) { + protected void ended(GENASubscription sub, CancelReason reason, UpnpResponse response) { } @SuppressWarnings("rawtypes") @@ -121,16 +121,14 @@ public class RemotePlayServiceBinder extends IRemotePlayService.Stub { @SuppressWarnings("unchecked") Map m = sub.getCurrentValues(); try { - LastChange lastChange = new LastChange( - new AVTransportLastChangeParser(), + LastChange lastChange = new LastChange(new AVTransportLastChangeParser(), m.get("LastChange").toString()); if (mStartingPlayback || lastChange.getEventedValue(0, AVTransportVariable.TransportState.class) == null) return; switch (lastChange.getEventedValue(0, - AVTransportVariable.TransportState.class) - .getValue()) { + AVTransportVariable.TransportState.class).getValue()) { case PLAYING: mPlaybackState = MediaItemStatus.PLAYBACK_STATE_PLAYING; break; @@ -149,7 +147,8 @@ public class RemotePlayServiceBinder extends IRemotePlayService.Stub { default: } - } catch (Exception e) { + } + catch (Exception e) { Log.w(TAG, "Failed to parse UPNP event", e); mRps.sendError("Failed to parse UPNP event"); } @@ -157,8 +156,7 @@ public class RemotePlayServiceBinder extends IRemotePlayService.Stub { @SuppressWarnings("rawtypes") @Override - protected void eventsMissed(GENASubscription sub, - int numberOfMissedEvents) { + protected void eventsMissed(GENASubscription sub, int numberOfMissedEvents) { } @SuppressWarnings("rawtypes") @@ -177,10 +175,12 @@ public class RemotePlayServiceBinder extends IRemotePlayService.Stub { */ @Override public void unselectRenderer(String sessionId) throws RemoteException { - if (mRps.mDevices.get(sessionId) != null) + if (mRps.mDevices.get(sessionId) != null) { stop(sessionId); - if (mSubscriptionCallback != null) + } + if (mSubscriptionCallback != null) { mSubscriptionCallback.end(); + } mCurrentRenderer = null; } @@ -246,19 +246,19 @@ public class RemotePlayServiceBinder extends IRemotePlayService.Stub { new Play(mRps.getService(mCurrentRenderer, "AVTransport")) { - @Override - public void success(ActionInvocation invocation) { - mPlaybackState = MediaItemStatus.PLAYBACK_STATE_PLAYING; - mStartingPlayback = false; - } + @Override + public void success(ActionInvocation invocation) { + mPlaybackState = MediaItemStatus.PLAYBACK_STATE_PLAYING; + mStartingPlayback = false; + } - @Override - public void failure(ActionInvocation invocation, - UpnpResponse operation, String defaultMessage) { - Log.w(TAG, "Play failed: " + defaultMessage); - mRps.sendError("Play failed: " + defaultMessage); - mStartingPlayback = false; - } + @Override + public void failure(ActionInvocation invocation, + UpnpResponse operation, String defaultMessage) { + Log.w(TAG, "Play failed: " + defaultMessage); + mRps.sendError("Play failed: " + defaultMessage); + mStartingPlayback = false; + } }); } }); @@ -284,8 +284,10 @@ public class RemotePlayServiceBinder extends IRemotePlayService.Stub { // Sometimes stop works even though pause does not. try { 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, UpnpResponse operation, String defaultMessage) { Log.w(TAG, "Get position failed: " + defaultMessage); + mRps.sendError("Get position failed: " + defaultMessage); } @SuppressWarnings("rawtypes") @@ -381,17 +384,20 @@ public class RemotePlayServiceBinder extends IRemotePlayService.Stub { Message msg = Message.obtain(null, Provider.MSG_STATUS_INFO, 0, 0); Builder status = null; - status = new MediaItemStatus.Builder(mPlaybackState); - if (positionInfo.getTrackURI() != null && positionInfo.getTrackURI().equals(itemId)) { - try { - status.setContentPosition(positionInfo.getTrackElapsedSeconds() * 1000) - .setContentDuration(positionInfo.getTrackDurationSeconds() * 1000) - .setTimestamp(positionInfo.getAbsCount()); - } - catch (NumberFormatException e) { - Log.d(TAG, "Failed to read track position or duration", e); - } - } + status = new MediaItemStatus.Builder(mPlaybackState); + if (positionInfo.getTrackURI() != null && + positionInfo.getTrackURI().equals(itemId)) { + try { + status.setContentPosition(positionInfo.getTrackElapsedSeconds() * 1000) + .setContentDuration(positionInfo.getTrackDurationSeconds() * 1000) + .setTimestamp(positionInfo.getAbsCount()); + } + catch (NumberFormatException e) { + Log.d(TAG, "Failed to read track position or duration", e); + mRps.sendError("Failed to read track position or duration: " + + e.toString()); + } + } msg.getData().putBundle("media_item_status", status.build().asBundle()); msg.getData().putInt("hash", requestHash); diff --git a/src/com/github/nutomic/controldlna/utility/DeviceArrayAdapter.java b/src/com/github/nutomic/controldlna/utility/DeviceArrayAdapter.java index b2586bc..4f660d2 100644 --- a/src/com/github/nutomic/controldlna/utility/DeviceArrayAdapter.java +++ b/src/com/github/nutomic/controldlna/utility/DeviceArrayAdapter.java @@ -5,13 +5,13 @@ All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. + notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. * Neither the name of the nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED @@ -27,16 +27,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 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.content.Context; import android.util.Log; @@ -48,6 +38,16 @@ import android.widget.TextView; 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 * of type RENDERER or SERVER). @@ -60,8 +60,6 @@ public class DeviceArrayAdapter extends ArrayAdapter> private static final String TAG = "DeviceArrayAdapter"; - public static final String RENDERER = "MediaRenderer"; - public static final String SERVER = "MediaServer"; private Activity mActivity; @@ -91,15 +89,16 @@ public class DeviceArrayAdapter extends ArrayAdapter> if (getItem(position).hasIcons()) { URI uri = getItem(position).getIcons()[0].getUri(); - if (getItem(position) instanceof RemoteDevice) + if (getItem(position) instanceof RemoteDevice) { try { RemoteDevice device = (RemoteDevice) getItem(position); uri = device.normalizeURI(uri).toURI(); - } catch (URISyntaxException e) { + } + catch (URISyntaxException 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); } @@ -110,9 +109,11 @@ public class DeviceArrayAdapter extends ArrayAdapter> * Adds a new device to the list if its type equals mDeviceType. */ public void deviceAdded(final Device device) { - for (int i = 0; i < getCount(); i++) - if (getItem(i).equals(device)) + for (int i = 0; i < getCount(); i++) { + if (getItem(i).equals(device)) { return; + } + } mActivity.runOnUiThread(new Runnable() { @@ -141,8 +142,9 @@ public class DeviceArrayAdapter extends ArrayAdapter> @Override public void run() { - if (getPosition(device) != -1) + if (getPosition(device) != -1) { remove(device); + } } }); } diff --git a/src/com/github/nutomic/controldlna/utility/FileArrayAdapter.java b/src/com/github/nutomic/controldlna/utility/FileArrayAdapter.java index 53991a6..c347448 100644 --- a/src/com/github/nutomic/controldlna/utility/FileArrayAdapter.java +++ b/src/com/github/nutomic/controldlna/utility/FileArrayAdapter.java @@ -5,13 +5,13 @@ All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. + notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. * Neither the name of the nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED @@ -28,7 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. package com.github.nutomic.controldlna.utility; import java.net.URI; -import java.util.List; +import java.util.List; import org.teleal.cling.support.model.DIDLObject; import org.teleal.cling.support.model.item.AudioItem; @@ -78,32 +78,38 @@ public class FileArrayAdapter extends ArrayAdapter { MusicTrack track = (MusicTrack) item; String trackNumber = (track.getOriginalTrackNumber() != null) ? Integer.toString(track.getOriginalTrackNumber()) + ". " - : ""; + : ""; title.setText(trackNumber + item.getTitle()); - if (track.getArtists().length > 0) + if (track.getArtists().length > 0) { artist.setText(track.getArtists()[0].getName()); + } } - else + else { title.setText(item.getTitle()); + } RemoteImageView image = (RemoteImageView) convertView.findViewById(R.id.image); - URI icon = item.getFirstPropertyValue( - DIDLObject.Property.UPNP.ALBUM_ART_URI.class); + URI icon = item.getFirstPropertyValue(DIDLObject.Property.UPNP.ALBUM_ART_URI.class); if (icon != null) { image.setImageUri(icon); } else { int resId; - if (item instanceof AudioItem) + if (item instanceof AudioItem) { resId = R.drawable.ic_doc_audio_am; - else if (item instanceof VideoItem) + } + else if (item instanceof VideoItem) { resId = R.drawable.ic_doc_video_am; - else if (item instanceof ImageItem) + } + else if (item instanceof ImageItem) { resId = R.drawable.ic_doc_image; - else if (item instanceof PlaylistItem) + } + else if (item instanceof PlaylistItem) { resId = R.drawable.ic_doc_album; - else + } + else { resId = R.drawable.ic_root_folder_am; + } image.setImageResource(resId); } @@ -114,8 +120,9 @@ public class FileArrayAdapter extends ArrayAdapter { * Replacement for addAll, which is not implemented on lower API levels. */ public void add(List playlist) { - for (DIDLObject d : playlist) + for (DIDLObject d : playlist) { add(d); + } } } diff --git a/src/com/github/nutomic/controldlna/utility/LoadImageTask.java b/src/com/github/nutomic/controldlna/utility/LoadImageTask.java index 17c22e9..60b1b3c 100644 --- a/src/com/github/nutomic/controldlna/utility/LoadImageTask.java +++ b/src/com/github/nutomic/controldlna/utility/LoadImageTask.java @@ -5,13 +5,13 @@ All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. + notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. * Neither the name of the nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED @@ -40,8 +40,8 @@ import android.os.AsyncTask; 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 * */ @@ -56,15 +56,15 @@ public class LoadImageTask extends AsyncTask { Bitmap bm = null; try { - URLConnection conn = new URL(uri[0].toString()) - .openConnection(); + URLConnection conn = new URL(uri[0].toString()).openConnection(); conn.connect(); InputStream is = conn.getInputStream(); BufferedInputStream bis = new BufferedInputStream(is); bm = BitmapFactory.decodeStream(bis); bis.close(); is.close(); - } catch (IOException e) { + } + catch (IOException e) { Log.w(TAG, "Failed to load artwork image", e); } return bm; diff --git a/src/com/github/nutomic/controldlna/utility/RemoteImageView.java b/src/com/github/nutomic/controldlna/utility/RemoteImageView.java index 027b82a..d96f0c3 100644 --- a/src/com/github/nutomic/controldlna/utility/RemoteImageView.java +++ b/src/com/github/nutomic/controldlna/utility/RemoteImageView.java @@ -5,13 +5,13 @@ All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. + notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. * Neither the name of the nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED @@ -36,7 +36,7 @@ import android.widget.ImageView; /** * ImageView that can directly load from a UPNP URI. - * + * * @author Felix Ableitner * */ @@ -44,7 +44,7 @@ public class RemoteImageView extends ImageView { /** * Assigns the icon as image drawable when it is loaded. - * + * * @author Felix * */ @@ -52,8 +52,9 @@ public class RemoteImageView extends ImageView { @Override protected void onPostExecute(Bitmap bm) { - if (bm != null) + if (bm != null) { setImageBitmap(bm); + } } }; diff --git a/src/com/github/nutomic/controldlna/utility/RouteAdapter.java b/src/com/github/nutomic/controldlna/utility/RouteAdapter.java index b84cbcd..0835398 100644 --- a/src/com/github/nutomic/controldlna/utility/RouteAdapter.java +++ b/src/com/github/nutomic/controldlna/utility/RouteAdapter.java @@ -41,7 +41,7 @@ public class RouteAdapter extends ArrayAdapter { public void add(List routes) { for (RouteInfo r : routes) { add(r); - } + } } }