Formatting fixes.
- add braces to if/for - indent with tabs instead of spaces - remove trailing whitespaces
This commit is contained in:
parent
59df28b2bd
commit
105bb9de94
30 changed files with 980 additions and 913 deletions
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.v4.view.ViewPager
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/pager"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/pager"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
|
|
@ -1,38 +1,38 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="?android:attr/listPreferredItemHeight"
|
||||
android:orientation="horizontal" >
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="?android:attr/listPreferredItemHeight"
|
||||
android:orientation="horizontal" >
|
||||
|
||||
<com.github.nutomic.controldlna.utility.RemoteImageView
|
||||
android:id="@+id/image"
|
||||
android:layout_width="?android:attr/listPreferredItemHeight"
|
||||
android:layout_height="?android:attr/listPreferredItemHeight"
|
||||
android:padding="4dip"
|
||||
android:contentDescription="@string/album_art" />
|
||||
<com.github.nutomic.controldlna.utility.RemoteImageView
|
||||
android:id="@+id/image"
|
||||
android:layout_width="?android:attr/listPreferredItemHeight"
|
||||
android:layout_height="?android:attr/listPreferredItemHeight"
|
||||
android:padding="4dip"
|
||||
android:contentDescription="@string/album_art" />
|
||||
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:orientation="vertical"
|
||||
android:layout_marginTop="4dip" >
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:orientation="vertical"
|
||||
android:layout_marginTop="4dip" >
|
||||
|
||||
<TextView
|
||||
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/title"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:lines="1"
|
||||
android:ellipsize="end" />
|
||||
|
||||
<TextView
|
||||
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" />
|
||||
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" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
|
|
@ -1,102 +1,102 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical" >
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical" >
|
||||
|
||||
<ListView
|
||||
android:id="@+id/listview"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_above="@+id/controls"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignParentTop="true" />
|
||||
<ListView
|
||||
android:id="@+id/listview"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_above="@+id/controls"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignParentTop="true" />
|
||||
|
||||
<TextView
|
||||
android:id="@id/android:empty"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="10dip"
|
||||
android:text="@string/route_list_empty"
|
||||
android:layout_centerInParent="true"
|
||||
android:gravity="center" />
|
||||
<TextView
|
||||
android:id="@id/android:empty"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="10dip"
|
||||
android:text="@string/route_list_empty"
|
||||
android:layout_centerInParent="true"
|
||||
android:gravity="center" />
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:orientation="vertical"
|
||||
android:id="@+id/controls"
|
||||
android:visibility="gone"
|
||||
android:background="@android:color/white" >
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:orientation="vertical"
|
||||
android:id="@+id/controls"
|
||||
android:visibility="gone"
|
||||
android:background="@android:color/white" >
|
||||
|
||||
<SeekBar
|
||||
android:id="@+id/progressBar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
<SeekBar
|
||||
android:id="@+id/progressBar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content" />
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:paddingLeft="10dip"
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:paddingLeft="10dip"
|
||||
android:paddingRight="10dip" >
|
||||
|
||||
<TextView
|
||||
android:id="@+id/current_time"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:gravity="right"
|
||||
android:minEms="2" />
|
||||
<TextView
|
||||
android:id="@+id/current_time"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:gravity="right"
|
||||
android:minEms="2" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/shuffle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:contentDescription="@string/shuffle"
|
||||
android:layout_toLeftOf="@+id/previous" />
|
||||
<ImageButton
|
||||
android:id="@+id/shuffle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:contentDescription="@string/shuffle"
|
||||
android:layout_toLeftOf="@+id/previous" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/previous"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:contentDescription="@string/previous"
|
||||
android:layout_toLeftOf="@+id/playpause" />
|
||||
<ImageButton
|
||||
android:id="@+id/previous"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:contentDescription="@string/previous"
|
||||
android:layout_toLeftOf="@+id/playpause" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/playpause"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:contentDescription="@string/play"
|
||||
android:layout_centerHorizontal="true"/>
|
||||
<ImageButton
|
||||
android:id="@+id/playpause"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:contentDescription="@string/play"
|
||||
android:layout_centerHorizontal="true"/>
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/next"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:contentDescription="@string/next"
|
||||
android:layout_toRightOf="@id/playpause" />
|
||||
<ImageButton
|
||||
android:id="@+id/next"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:contentDescription="@string/next"
|
||||
android:layout_toRightOf="@id/playpause" />
|
||||
|
||||
<ImageButton
|
||||
android:id="@+id/repeat"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:contentDescription="@string/repeat"
|
||||
android:layout_toRightOf="@id/next" />
|
||||
<ImageButton
|
||||
android:id="@+id/repeat"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:contentDescription="@string/repeat"
|
||||
android:layout_toRightOf="@id/next" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/total_time"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:gravity="right"
|
||||
android:minEms="2"/>
|
||||
<TextView
|
||||
android:id="@+id/total_time"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_alignParentTop="true"
|
||||
android:gravity="right"
|
||||
android:minEms="2"/>
|
||||
|
||||
</RelativeLayout>
|
||||
</RelativeLayout>
|
||||
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
|
||||
</RelativeLayout>
|
||||
|
|
|
@ -1,21 +1,21 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical" >
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical" >
|
||||
|
||||
<ListView
|
||||
android:id="@id/android:list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
<ListView
|
||||
android:id="@id/android:list"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@id/android:empty"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="10dip"
|
||||
android:text="@string/device_list_empty"
|
||||
android:layout_centerInParent="true"
|
||||
android:gravity="center" />
|
||||
<TextView
|
||||
android:id="@id/android:empty"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="10dip"
|
||||
android:text="@string/device_list_empty"
|
||||
android:layout_centerInParent="true"
|
||||
android:gravity="center" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<item
|
||||
android:id="@+id/preferences"
|
||||
android:title="@string/settings_title" />
|
||||
<item
|
||||
android:id="@+id/preferences"
|
||||
android:title="@string/settings_title" />
|
||||
|
||||
</menu>
|
|
@ -1,8 +1,8 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<array name="enable_wifi_values">
|
||||
<item>yes</item>
|
||||
<item>no</item>
|
||||
<item>ask</item>
|
||||
</array>
|
||||
<array name="enable_wifi_values">
|
||||
<item>yes</item>
|
||||
<item>no</item>
|
||||
<item>ask</item>
|
||||
</array>
|
||||
</resources>
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="currently_playing_background">#BB99CC00</color>
|
||||
<color name="button_highlight">#ff33b5e5</color>
|
||||
<color name="currently_playing_background">#BB99CC00</color>
|
||||
<color name="button_highlight">#ff33b5e5</color>
|
||||
</resources>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<resources>
|
||||
|
||||
<!-- Default screen margins, per the Android Design guidelines. -->
|
||||
<dimen name="activity_horizontal_margin">16dp</dimen>
|
||||
<dimen name="activity_vertical_margin">16dp</dimen>
|
||||
<!-- Default screen margins, per the Android Design guidelines. -->
|
||||
<dimen name="activity_horizontal_margin">16dp</dimen>
|
||||
<dimen name="activity_vertical_margin">16dp</dimen>
|
||||
|
||||
</resources>
|
||||
|
|
|
@ -1,42 +1,42 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
|
||||
<string name="app_name">ControlDLNA</string>
|
||||
<string name="app_name">ControlDLNA</string>
|
||||
|
||||
<!-- Server Fragment -->
|
||||
<string name="title_server">Server</string>
|
||||
<!-- Server Fragment -->
|
||||
<string name="title_server">Server</string>
|
||||
<string name="folder_list_empty">Folder is empty</string>
|
||||
<string name="device_list_empty">No UPNP devices found.
|
||||
\nNew devices will be added automatically when they are available.</string>
|
||||
<string name="device_list_empty">No UPNP devices found.
|
||||
\nNew devices will be added automatically when they are available.</string>
|
||||
|
||||
<!-- Route Fragment -->
|
||||
<string name="title_route">Route</string>
|
||||
<!-- Route Fragment -->
|
||||
<string name="title_route">Route</string>
|
||||
<string name="playlist_empty">Playlist is empty</string>
|
||||
<string name="route_list_empty">No routes found.
|
||||
\nNew routes will be added automatically when they are available.</string>
|
||||
<string name="route_list_empty">No routes found.
|
||||
\nNew routes will be added automatically when they are available.</string>
|
||||
|
||||
<!-- Playback controls -->
|
||||
<string name="play">Play</string>
|
||||
<string name="pause">Pause</string>
|
||||
<string name="previous">Previous</string>
|
||||
<string name="next">Next</string>
|
||||
<string name="shuffle">Shuffle</string>
|
||||
<string name="repeat">Repeat</string>
|
||||
<!-- Playback controls -->
|
||||
<string name="play">Play</string>
|
||||
<string name="pause">Pause</string>
|
||||
<string name="previous">Previous</string>
|
||||
<string name="next">Next</string>
|
||||
<string name="shuffle">Shuffle</string>
|
||||
<string name="repeat">Repeat</string>
|
||||
|
||||
<!-- Toasts/Dialogs -->
|
||||
<string name="exit_renderer">Do you really want to exit the renderer?
|
||||
Playback will be stopped.</string>
|
||||
<string name="select_route">Please select a route</string>
|
||||
<string name="enable_wifi_dialog">Wifi needs to be connected for playback.
|
||||
Do you want to enable it now?</string>
|
||||
<!-- Toasts/Dialogs -->
|
||||
<string name="exit_renderer">Do you really want to exit the renderer?
|
||||
Playback will be stopped.</string>
|
||||
<string name="select_route">Please select a route</string>
|
||||
<string name="enable_wifi_dialog">Wifi needs to be connected for playback.
|
||||
Do you want to enable it now?</string>
|
||||
|
||||
<!-- Description for local playback device -->
|
||||
<string name="local_device">Local Device</string>
|
||||
<!-- Description for local playback device -->
|
||||
<string name="local_device">Local Device</string>
|
||||
|
||||
<!-- Image alt text -->
|
||||
<string name="album_art">Album Art</string>
|
||||
<!-- Image alt text -->
|
||||
<string name="album_art">Album Art</string>
|
||||
|
||||
<!-- MediaRouter strings -->
|
||||
<!-- MediaRouter strings -->
|
||||
<string name="upnp_route_provider_service">UPNP Route Provider Service</string>
|
||||
|
||||
<!-- Developer contact mail with '@', '.' replaced -->
|
||||
|
@ -45,18 +45,18 @@
|
|||
<!-- Title for the SettingsActivity -->
|
||||
<string name="settings_title">Preferences</string>
|
||||
|
||||
<!-- Title for preference to enable wifi on start -->
|
||||
<string name="enable_wifi_title">Automatically enable Wifi on start</string>
|
||||
<!-- Title for preference to enable wifi on start -->
|
||||
<string name="enable_wifi_title">Automatically enable Wifi on start</string>
|
||||
|
||||
<!-- Values for preference to auto-enable wifi on start -->
|
||||
<string-array name="enable_wifi_value_titles">
|
||||
<item>yes</item>
|
||||
<item>no</item>
|
||||
<item>ask</item>
|
||||
</string-array>
|
||||
<!-- Values for preference to auto-enable wifi on start -->
|
||||
<string-array name="enable_wifi_value_titles">
|
||||
<item>yes</item>
|
||||
<item>no</item>
|
||||
<item>ask</item>
|
||||
</string-array>
|
||||
|
||||
<!-- Title for the pause playback on call preference -->
|
||||
<string name="incoming_phone_call_pause">Pause playback on incoming phone call</string>
|
||||
<!-- Title for the pause playback on call preference -->
|
||||
<string name="incoming_phone_call_pause">Pause playback on incoming phone call</string>
|
||||
|
||||
<!-- Title for the contact developer preference -->
|
||||
<string name="contact_dev_title">Contact Developer</string>
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
<resources>
|
||||
|
||||
<!--
|
||||
Base application theme, dependent on API level. This theme is replaced
|
||||
by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
|
||||
-->
|
||||
<style name="AppBaseTheme" parent="android:Theme.Light">
|
||||
<!--
|
||||
Theme customizations available in newer API levels can go in
|
||||
res/values-vXX/styles.xml, while customizations related to
|
||||
backward-compatibility can go here.
|
||||
-->
|
||||
</style>
|
||||
<!--
|
||||
Base application theme, dependent on API level. This theme is replaced
|
||||
by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
|
||||
-->
|
||||
<style name="AppBaseTheme" parent="android:Theme.Light">
|
||||
<!--
|
||||
Theme customizations available in newer API levels can go in
|
||||
res/values-vXX/styles.xml, while customizations related to
|
||||
backward-compatibility can go here.
|
||||
-->
|
||||
</style>
|
||||
|
||||
<!-- Application theme. -->
|
||||
<style name="AppTheme" parent="AppBaseTheme">
|
||||
<!-- All customizations that are NOT specific to a particular API-level can go here. -->
|
||||
</style>
|
||||
<!-- Application theme. -->
|
||||
<style name="AppTheme" parent="AppBaseTheme">
|
||||
<!-- All customizations that are NOT specific to a particular API-level can go here. -->
|
||||
</style>
|
||||
|
||||
</resources>
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<ListPreference
|
||||
android:key="enable_wifi_on_start"
|
||||
android:title="@string/enable_wifi_title"
|
||||
android:entries="@array/enable_wifi_value_titles"
|
||||
android:entryValues="@array/enable_wifi_values"
|
||||
android:defaultValue="ask"/>
|
||||
<ListPreference
|
||||
android:key="enable_wifi_on_start"
|
||||
android:title="@string/enable_wifi_title"
|
||||
android:entries="@array/enable_wifi_value_titles"
|
||||
android:entryValues="@array/enable_wifi_values"
|
||||
android:defaultValue="ask"/>
|
||||
|
||||
<CheckBoxPreference
|
||||
android:key="incoming_phone_call_pause"
|
||||
android:title="@string/incoming_phone_call_pause"
|
||||
android:defaultValue="true" />
|
||||
<CheckBoxPreference
|
||||
android:key="incoming_phone_call_pause"
|
||||
android:title="@string/incoming_phone_call_pause"
|
||||
android:defaultValue="true" />
|
||||
|
||||
<Preference
|
||||
android:key="contact_dev"
|
||||
android:title="@string/contact_dev_title" />
|
||||
<Preference
|
||||
android:key="contact_dev"
|
||||
android:title="@string/contact_dev_title" />
|
||||
|
||||
</PreferenceScreen>
|
|
@ -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 <organization> 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);
|
||||
|
|
|
@ -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 <organization> 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());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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 <organization> 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();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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 <organization> 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,6 +52,24 @@ 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.
|
||||
|
@ -107,6 +107,8 @@ public class ServerFragment extends ListFragment implements OnBackPressedListene
|
|||
*/
|
||||
private Stack<String> mCurrentPath = new Stack<String>();
|
||||
|
||||
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<String>(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<Item> playlist = new ArrayList<Item>();
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -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 <organization> 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 <organization> nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
|
@ -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,6 +39,8 @@ 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.
|
||||
*
|
||||
|
@ -56,103 +56,105 @@ public class Controller extends MediaRouteProvider.RouteController implements
|
|||
|
||||
private AudioManager mAudio;
|
||||
|
||||
AudioManager.OnAudioFocusChangeListener mFocusListener;
|
||||
AudioManager.OnAudioFocusChangeListener mFocusListener;
|
||||
|
||||
private final String mRouteId;
|
||||
private final String mRouteId;
|
||||
|
||||
private String mItemId;
|
||||
private String mItemId;
|
||||
|
||||
private int mState;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 <organization> 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 <organization> nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
|
@ -51,55 +51,56 @@ import com.github.nutomic.controldlna.R;
|
|||
*/
|
||||
final class Provider extends MediaRouteProvider {
|
||||
|
||||
private static final String ROUTE_ID = "local_route";
|
||||
private static final String ROUTE_ID = "local_route";
|
||||
|
||||
AudioManager mAudio = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
|
||||
AudioManager mAudio = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
|
||||
|
||||
private static final ArrayList<IntentFilter> 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 final ArrayList<IntentFilter> 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/*");
|
||||
|
||||
CONTROL_FILTERS = new ArrayList<IntentFilter>();
|
||||
CONTROL_FILTERS.add(f);
|
||||
}
|
||||
CONTROL_FILTERS = new ArrayList<IntentFilter>();
|
||||
CONTROL_FILTERS.add(f);
|
||||
}
|
||||
|
||||
private static void addDataTypeUnchecked(IntentFilter filter, String type) {
|
||||
try {
|
||||
filter.addDataType(type);
|
||||
} catch (MalformedMimeTypeException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
private static void addDataTypeUnchecked(IntentFilter filter, String type) {
|
||||
try {
|
||||
filter.addDataType(type);
|
||||
}
|
||||
catch (MalformedMimeTypeException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public Provider(Context context) {
|
||||
super(context);
|
||||
public Provider(Context context) {
|
||||
super(context);
|
||||
|
||||
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();
|
||||
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();
|
||||
|
||||
|
||||
MediaRouteProviderDescriptor providerDescriptor =
|
||||
new MediaRouteProviderDescriptor.Builder()
|
||||
.addRoute(routeDescriptor)
|
||||
.build();
|
||||
setDescriptor(providerDescriptor);
|
||||
}
|
||||
MediaRouteProviderDescriptor providerDescriptor =
|
||||
new MediaRouteProviderDescriptor.Builder()
|
||||
.addRoute(routeDescriptor)
|
||||
.build();
|
||||
setDescriptor(providerDescriptor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RouteController onCreateRouteController(String routeId) {
|
||||
return new Controller(routeId, getContext());
|
||||
}
|
||||
@Override
|
||||
public RouteController onCreateRouteController(String routeId) {
|
||||
return new Controller(routeId, getContext());
|
||||
}
|
||||
}
|
|
@ -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 <organization> 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 <organization> nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 <organization> 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,6 +55,17 @@ 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.
|
||||
*
|
||||
|
@ -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,8 +351,7 @@ 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);
|
||||
}
|
||||
|
||||
|
@ -358,6 +361,9 @@ public class MediaRouterPlayService extends Service {
|
|||
* @param playlist The media files in the playlist.
|
||||
*/
|
||||
public void setPlaylist(List<Item> playlist) {
|
||||
|
||||
|
||||
|
||||
mPlaylist = playlist;
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -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 <organization> 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
|
||||
|
|
|
@ -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 <organization> 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 <organization> nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
|
|
|
@ -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 <organization> 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<Device> CREATOR
|
||||
= new Parcelable.Creator<Device>() {
|
||||
public static final Parcelable.Creator<Device> CREATOR =
|
||||
new Parcelable.Creator<Device>() {
|
||||
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:
|
||||
|
|
|
@ -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 <organization> 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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 <organization> 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
|
||||
|
@ -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<String, Device<?, ?, ?>> d : mDevices.entrySet())
|
||||
}
|
||||
else {
|
||||
for (Entry<String, Device<?, ?, ?>> 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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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 <organization> 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<String, StateVariableValue> 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);
|
||||
|
|
|
@ -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 <organization> 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<Device<?, ?, ?>>
|
|||
|
||||
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<Device<?, ?, ?>>
|
|||
|
||||
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<Device<?, ?, ?>>
|
|||
* 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<Device<?, ?, ?>>
|
|||
|
||||
@Override
|
||||
public void run() {
|
||||
if (getPosition(device) != -1)
|
||||
if (getPosition(device) != -1) {
|
||||
remove(device);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -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 <organization> 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
|
||||
|
@ -78,32 +78,38 @@ public class FileArrayAdapter extends ArrayAdapter<DIDLObject> {
|
|||
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<DIDLObject> {
|
|||
* Replacement for addAll, which is not implemented on lower API levels.
|
||||
*/
|
||||
public void add(List<Item> playlist) {
|
||||
for (DIDLObject d : playlist)
|
||||
for (DIDLObject d : playlist) {
|
||||
add(d);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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 <organization> 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,7 +40,7 @@ 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<URI, Void, Bitmap> {
|
|||
|
||||
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;
|
||||
|
|
|
@ -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 <organization> 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
|
||||
|
@ -52,8 +52,9 @@ public class RemoteImageView extends ImageView {
|
|||
|
||||
@Override
|
||||
protected void onPostExecute(Bitmap bm) {
|
||||
if (bm != null)
|
||||
if (bm != null) {
|
||||
setImageBitmap(bm);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
|
|
@ -41,7 +41,7 @@ public class RouteAdapter extends ArrayAdapter<RouteInfo> {
|
|||
public void add(List<RouteInfo> routes) {
|
||||
for (RouteInfo r : routes) {
|
||||
add(r);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Reference in a new issue