Merge branch 'playback-speed' of git://github.com/TheRealFalcon/AntennaPod into playback-speed-tmp
Conflicts: src/de/danoeh/antennapod/activity/AudioplayerActivity.java src/de/danoeh/antennapod/activity/PreferenceActivity.java src/de/danoeh/antennapod/service/PlaybackService.java src/de/danoeh/antennapod/util/playback/PlaybackController.java
This commit is contained in:
commit
8337739ab4
|
@ -1,6 +1,16 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<resources>
|
<resources>
|
||||||
|
|
||||||
|
<string-array name="update_intervall_options">
|
||||||
|
<item>Manual</item>
|
||||||
|
<item>1 hour</item>
|
||||||
|
<item>2 hours</item>
|
||||||
|
<item>4 hours</item>
|
||||||
|
<item>8 hours</item>
|
||||||
|
<item>12 hours</item>
|
||||||
|
<item>24 hours</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
<string-array name="update_intervall_values">
|
<string-array name="update_intervall_values">
|
||||||
<item>0</item>
|
<item>0</item>
|
||||||
<item>1</item>
|
<item>1</item>
|
||||||
|
@ -28,6 +38,50 @@
|
||||||
<item>80</item>
|
<item>80</item>
|
||||||
<item>100</item>
|
<item>100</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
<string-array name="playback_speed_values">
|
||||||
|
<item>1.0</item>
|
||||||
|
<item>1.05</item>
|
||||||
|
<item>1.10</item>
|
||||||
|
<item>1.15</item>
|
||||||
|
<item>1.20</item>
|
||||||
|
<item>1.25</item>
|
||||||
|
<item>1.30</item>
|
||||||
|
<item>1.35</item>
|
||||||
|
<item>1.40</item>
|
||||||
|
<item>1.45</item>
|
||||||
|
<item>1.50</item>
|
||||||
|
<item>1.55</item>
|
||||||
|
<item>1.60</item>
|
||||||
|
<item>1.65</item>
|
||||||
|
<item>1.70</item>
|
||||||
|
<item>1.75</item>
|
||||||
|
<item>1.80</item>
|
||||||
|
<item>1.85</item>
|
||||||
|
<item>1.90</item>
|
||||||
|
<item>1.95</item>
|
||||||
|
<item>2.00</item>
|
||||||
|
<item>2.10</item>
|
||||||
|
<item>2.20</item>
|
||||||
|
<item>2.30</item>
|
||||||
|
<item>2.40</item>
|
||||||
|
<item>2.50</item>
|
||||||
|
<item>2.60</item>
|
||||||
|
<item>2.70</item>
|
||||||
|
<item>2.80</item>
|
||||||
|
<item>2.90</item>
|
||||||
|
<item>3.00</item>
|
||||||
|
<item>3.10</item>
|
||||||
|
<item>3.20</item>
|
||||||
|
<item>3.30</item>
|
||||||
|
<item>3.40</item>
|
||||||
|
<item>3.50</item>
|
||||||
|
<item>3.60</item>
|
||||||
|
<item>3.70</item>
|
||||||
|
<item>3.80</item>
|
||||||
|
<item>3.90</item>
|
||||||
|
<item>4.00</item>
|
||||||
|
</string-array>
|
||||||
|
|
||||||
<string-array name="autodl_select_networks_default_entries">
|
<string-array name="autodl_select_networks_default_entries">
|
||||||
<item>N/A</item>
|
<item>N/A</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
@ -42,5 +96,6 @@
|
||||||
<item>0</item>
|
<item>0</item>
|
||||||
<item>1</item>
|
<item>1</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
||||||
|
|
||||||
</resources>
|
</resources>
|
|
@ -47,6 +47,8 @@
|
||||||
<string name="processing_label">Processing</string>
|
<string name="processing_label">Processing</string>
|
||||||
<string name="loading_label">Loading...</string>
|
<string name="loading_label">Loading...</string>
|
||||||
<string name="image_of_prefix">Image of:\u0020</string>
|
<string name="image_of_prefix">Image of:\u0020</string>
|
||||||
|
<string name="close_label">Close</string>
|
||||||
|
|
||||||
|
|
||||||
<!-- 'Add Feed' Activity labels -->
|
<!-- 'Add Feed' Activity labels -->
|
||||||
<string name="feedurl_label">Feed URL</string>
|
<string name="feedurl_label">Feed URL</string>
|
||||||
|
@ -143,6 +145,12 @@
|
||||||
<string name="access_revoked_info">You have successfully revoked AntennaPod\'s access token to your account. In order to complete the process, you have to remove this app from the list of approved applications in your account settings on the flattr website.</string>
|
<string name="access_revoked_info">You have successfully revoked AntennaPod\'s access token to your account. In order to complete the process, you have to remove this app from the list of approved applications in your account settings on the flattr website.</string>
|
||||||
<string name="flattr_click_success">Successfully flattred this thing!</string>
|
<string name="flattr_click_success">Successfully flattred this thing!</string>
|
||||||
<string name="flattring_label">Flattring</string>
|
<string name="flattring_label">Flattring</string>
|
||||||
|
|
||||||
|
<!-- Variable Speed -->
|
||||||
|
<string name="download_plugin_label">Download Plugin</string>
|
||||||
|
<string name="no_playback_plugin_title">Plugin Not Installed</string>
|
||||||
|
<string name="no_playback_plugin_msg">For variable speed playback to work, a third party library must be installed.\n\nTap \'Download Plugin\' to download a free plugin from the Play Store\n\nAny problems found using this plugin are not the responsibility of AntennaPod and should be reported to the plugin owner.</string>
|
||||||
|
<string name="set_playback_speed_label">Playback Speeds</string>
|
||||||
|
|
||||||
<!-- Empty list labels -->
|
<!-- Empty list labels -->
|
||||||
<string name="no_items_label">There are no items in this list.</string>
|
<string name="no_items_label">There are no items in this list.</string>
|
||||||
|
@ -185,9 +193,11 @@
|
||||||
<string name="pref_theme_title_light">Light</string>
|
<string name="pref_theme_title_light">Light</string>
|
||||||
<string name="pref_theme_title_dark">Dark</string>
|
<string name="pref_theme_title_dark">Dark</string>
|
||||||
<string name="pref_episode_cache_unlimited">Unlimited</string>
|
<string name="pref_episode_cache_unlimited">Unlimited</string>
|
||||||
<string name="pref_update_interval_hours_plural">hours</string>
|
<string name="pref_update_interval_hours_plural">hours</string>
|
||||||
<string name="pref_update_interval_hours_singular">hour</string>
|
<string name="pref_update_interval_hours_singular">hour</string>
|
||||||
<string name="pref_update_interval_hours_manual">Manual</string>
|
<string name="pref_update_interval_hours_manual">Manual</string>
|
||||||
|
<string name="pref_playback_speed_title">Playback Speeds</string>
|
||||||
|
<string name="pref_playback_speed_sum">Customize the speeds available for variable speed audio playback</string>
|
||||||
|
|
||||||
|
|
||||||
<!-- Search -->
|
<!-- Search -->
|
||||||
|
@ -251,4 +261,4 @@
|
||||||
<string name="folder_not_empty_dialog_msg">The folder you have selected is not empty. Media downloads and other files will be placed directly in this folder. Continue anyway?</string>
|
<string name="folder_not_empty_dialog_msg">The folder you have selected is not empty. Media downloads and other files will be placed directly in this folder. Continue anyway?</string>
|
||||||
<string name="set_to_default_folder">Choose default folder</string>
|
<string name="set_to_default_folder">Choose default folder</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -17,6 +17,10 @@
|
||||||
android:key="prefFollowQueue"
|
android:key="prefFollowQueue"
|
||||||
android:summary="@string/pref_followQueue_sum"
|
android:summary="@string/pref_followQueue_sum"
|
||||||
android:title="@string/pref_followQueue_title" />
|
android:title="@string/pref_followQueue_title" />
|
||||||
|
<Preference
|
||||||
|
android:key="prefPlaybackSpeedLauncher"
|
||||||
|
android:summary="@string/pref_playback_speed_sum"
|
||||||
|
android:title="@string/pref_playback_speed_title" />
|
||||||
|
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
<PreferenceCategory android:title="@string/network_pref" >
|
<PreferenceCategory android:title="@string/network_pref" >
|
||||||
|
|
|
@ -12,6 +12,7 @@ import android.util.Log;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.View.OnClickListener;
|
import android.view.View.OnClickListener;
|
||||||
import android.view.Window;
|
import android.view.Window;
|
||||||
|
import android.view.View.OnLongClickListener;
|
||||||
import android.widget.ArrayAdapter;
|
import android.widget.ArrayAdapter;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
import android.widget.ImageButton;
|
import android.widget.ImageButton;
|
||||||
|
@ -23,11 +24,14 @@ import de.danoeh.antennapod.AppConfig;
|
||||||
import de.danoeh.antennapod.R;
|
import de.danoeh.antennapod.R;
|
||||||
import de.danoeh.antennapod.adapter.ChapterListAdapter;
|
import de.danoeh.antennapod.adapter.ChapterListAdapter;
|
||||||
import de.danoeh.antennapod.asynctask.ImageLoader;
|
import de.danoeh.antennapod.asynctask.ImageLoader;
|
||||||
|
import de.danoeh.antennapod.dialog.VariableSpeedDialog;
|
||||||
import de.danoeh.antennapod.feed.Chapter;
|
import de.danoeh.antennapod.feed.Chapter;
|
||||||
import de.danoeh.antennapod.feed.MediaType;
|
import de.danoeh.antennapod.feed.MediaType;
|
||||||
import de.danoeh.antennapod.feed.SimpleChapter;
|
import de.danoeh.antennapod.feed.SimpleChapter;
|
||||||
import de.danoeh.antennapod.fragment.CoverFragment;
|
import de.danoeh.antennapod.fragment.CoverFragment;
|
||||||
import de.danoeh.antennapod.fragment.ItemDescriptionFragment;
|
import de.danoeh.antennapod.fragment.ItemDescriptionFragment;
|
||||||
|
import de.danoeh.antennapod.preferences.UserPreferences;
|
||||||
|
import de.danoeh.antennapod.preferences.UserPreferences;
|
||||||
import de.danoeh.antennapod.service.PlaybackService;
|
import de.danoeh.antennapod.service.PlaybackService;
|
||||||
import de.danoeh.antennapod.util.playback.ExternalMedia;
|
import de.danoeh.antennapod.util.playback.ExternalMedia;
|
||||||
import de.danoeh.antennapod.util.playback.Playable;
|
import de.danoeh.antennapod.util.playback.Playable;
|
||||||
|
@ -396,29 +400,46 @@ public class AudioplayerActivity extends MediaplayerActivity {
|
||||||
|
|
||||||
butPlaybackSpeed.setOnClickListener(new OnClickListener() {
|
butPlaybackSpeed.setOnClickListener(new OnClickListener() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View v) {
|
public void onClick(View v) {
|
||||||
final double PLAYBACK_SPEED_STEP = 0.5;
|
if (controller != null && controller.canSetPlaybackSpeed()) {
|
||||||
final double PLAYBACK_SPEED_MAX = 2.0;
|
String[] availableSpeeds = UserPreferences
|
||||||
final double PLAYBACK_SPEED_DEFAULT = 1.0;
|
.getPlaybackSpeedArray();
|
||||||
|
String currentSpeed = UserPreferences.getPlaybackSpeed();
|
||||||
|
|
||||||
if (controller != null && controller.canSetPlaybackSpeed()) {
|
// Provide initial value in case the speed list has changed
|
||||||
double currentPlaybackSpeed = controller
|
// out from under us
|
||||||
.getCurrentPlaybackSpeedMultiplier();
|
// and our current speed isn't in the new list
|
||||||
if (currentPlaybackSpeed != -1) {
|
String newSpeed;
|
||||||
if (currentPlaybackSpeed >= PLAYBACK_SPEED_MAX) {
|
if (availableSpeeds.length > 0) {
|
||||||
controller.setPlaybackSpeed(PLAYBACK_SPEED_DEFAULT);
|
newSpeed = availableSpeeds[0];
|
||||||
} else {
|
} else {
|
||||||
controller.setPlaybackSpeed(currentPlaybackSpeed
|
newSpeed = "1.0";
|
||||||
+ PLAYBACK_SPEED_STEP);
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < availableSpeeds.length; i++) {
|
||||||
|
if (availableSpeeds[i].equals(currentSpeed)) {
|
||||||
|
if (i == availableSpeeds.length - 1) {
|
||||||
|
newSpeed = availableSpeeds[0];
|
||||||
|
} else {
|
||||||
|
newSpeed = availableSpeeds[i + 1];
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
controller.setPlaybackSpeed(PLAYBACK_SPEED_DEFAULT);
|
|
||||||
}
|
}
|
||||||
|
UserPreferences.setPlaybackSpeed(newSpeed);
|
||||||
|
controller.setPlaybackSpeed(Float.parseFloat(newSpeed));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
}
|
butPlaybackSpeed.setOnLongClickListener(new OnLongClickListener() {
|
||||||
}
|
@Override
|
||||||
});
|
public boolean onLongClick(View v) {
|
||||||
|
VariableSpeedDialog.showDialog(AudioplayerActivity.this);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -428,14 +449,12 @@ public class AudioplayerActivity extends MediaplayerActivity {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateButPlaybackSpeed() {
|
private void updateButPlaybackSpeed() {
|
||||||
double playbackSpeed;
|
|
||||||
if (controller == null
|
if (controller == null
|
||||||
|| (playbackSpeed = controller
|
|| (controller.getCurrentPlaybackSpeedMultiplier() == -1)) {
|
||||||
.getCurrentPlaybackSpeedMultiplier()) == -1) {
|
|
||||||
butPlaybackSpeed.setVisibility(View.GONE);
|
butPlaybackSpeed.setVisibility(View.GONE);
|
||||||
} else {
|
} else {
|
||||||
butPlaybackSpeed.setVisibility(View.VISIBLE);
|
butPlaybackSpeed.setVisibility(View.VISIBLE);
|
||||||
butPlaybackSpeed.setText(String.format("%.1fx", playbackSpeed));
|
butPlaybackSpeed.setText(UserPreferences.getPlaybackSpeed());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,7 @@ import de.danoeh.antennapod.AppConfig;
|
||||||
import de.danoeh.antennapod.R;
|
import de.danoeh.antennapod.R;
|
||||||
import de.danoeh.antennapod.asynctask.FlattrClickWorker;
|
import de.danoeh.antennapod.asynctask.FlattrClickWorker;
|
||||||
import de.danoeh.antennapod.asynctask.OpmlExportWorker;
|
import de.danoeh.antennapod.asynctask.OpmlExportWorker;
|
||||||
|
import de.danoeh.antennapod.dialog.VariableSpeedDialog;
|
||||||
import de.danoeh.antennapod.preferences.UserPreferences;
|
import de.danoeh.antennapod.preferences.UserPreferences;
|
||||||
import de.danoeh.antennapod.util.flattr.FlattrUtils;
|
import de.danoeh.antennapod.util.flattr.FlattrUtils;
|
||||||
|
|
||||||
|
@ -41,7 +42,8 @@ public class PreferenceActivity extends android.preference.PreferenceActivity {
|
||||||
private static final String PREF_ABOUT = "prefAbout";
|
private static final String PREF_ABOUT = "prefAbout";
|
||||||
private static final String PREF_CHOOSE_DATA_DIR = "prefChooseDataDir";
|
private static final String PREF_CHOOSE_DATA_DIR = "prefChooseDataDir";
|
||||||
private static final String AUTO_DL_PREF_SCREEN = "prefAutoDownloadSettings";
|
private static final String AUTO_DL_PREF_SCREEN = "prefAutoDownloadSettings";
|
||||||
|
private static final String PREF_PLAYBACK_SPEED_LAUNCHER = "prefPlaybackSpeedLauncher";
|
||||||
|
|
||||||
private CheckBoxPreference[] selectedNetworks;
|
private CheckBoxPreference[] selectedNetworks;
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
@SuppressWarnings("deprecation")
|
||||||
|
@ -156,6 +158,14 @@ public class PreferenceActivity extends android.preference.PreferenceActivity {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
findPreference(PREF_PLAYBACK_SPEED_LAUNCHER)
|
||||||
|
.setOnPreferenceClickListener(new OnPreferenceClickListener() {
|
||||||
|
@Override
|
||||||
|
public boolean onPreferenceClick(Preference preference) {
|
||||||
|
VariableSpeedDialog.showDialog(PreferenceActivity.this);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
buildUpdateIntervalPreference();
|
buildUpdateIntervalPreference();
|
||||||
buildAutodownloadSelectedNetworsPreference();
|
buildAutodownloadSelectedNetworsPreference();
|
||||||
setSelectedNetworksEnabled(UserPreferences
|
setSelectedNetworksEnabled(UserPreferences
|
||||||
|
|
|
@ -0,0 +1,94 @@
|
||||||
|
package de.danoeh.antennapod.dialog;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import android.app.AlertDialog;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.DialogInterface;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.net.Uri;
|
||||||
|
import de.danoeh.antennapod.R;
|
||||||
|
import de.danoeh.antennapod.preferences.UserPreferences;
|
||||||
|
|
||||||
|
public class VariableSpeedDialog {
|
||||||
|
private VariableSpeedDialog() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void showDialog(final Context context) {
|
||||||
|
if (com.aocate.media.MediaPlayer.isPrestoLibraryInstalled(context)) {
|
||||||
|
showSpeedSelectorDialog(context);
|
||||||
|
} else {
|
||||||
|
showGetPluginDialog(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void showGetPluginDialog(final Context context) {
|
||||||
|
AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
||||||
|
builder.setTitle(R.string.no_playback_plugin_title);
|
||||||
|
builder.setMessage(R.string.no_playback_plugin_msg);
|
||||||
|
builder.setNegativeButton(R.string.close_label, null);
|
||||||
|
builder.setPositiveButton(R.string.download_plugin_label,
|
||||||
|
new DialogInterface.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
|
Intent playStoreIntent = new Intent(
|
||||||
|
Intent.ACTION_VIEW,
|
||||||
|
Uri.parse("market://details?id=com.falconware.prestissimo"));
|
||||||
|
context.startActivity(playStoreIntent);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
builder.create().show();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void showSpeedSelectorDialog(final Context context) {
|
||||||
|
final String[] speedValues = context.getResources().getStringArray(
|
||||||
|
R.array.playback_speed_values);
|
||||||
|
// According to Java spec these get initialized to false on creation
|
||||||
|
final boolean[] speedChecked = new boolean[speedValues.length];
|
||||||
|
|
||||||
|
// Build the "isChecked" array so that multiChoice dialog is
|
||||||
|
// populated correctly
|
||||||
|
List<String> selectedSpeedList = Arrays.asList(UserPreferences
|
||||||
|
.getPlaybackSpeedArray());
|
||||||
|
for (int i = 0; i < speedValues.length; i++) {
|
||||||
|
speedChecked[i] = selectedSpeedList.contains(speedValues[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
||||||
|
builder.setTitle(R.string.set_playback_speed_label);
|
||||||
|
builder.setMultiChoiceItems(R.array.playback_speed_values,
|
||||||
|
speedChecked, new DialogInterface.OnMultiChoiceClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialog, int which,
|
||||||
|
boolean isChecked) {
|
||||||
|
speedChecked[which] = isChecked;
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
builder.setNegativeButton(android.R.string.cancel, null);
|
||||||
|
builder.setPositiveButton(android.R.string.ok,
|
||||||
|
new DialogInterface.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(DialogInterface dialog, int which) {
|
||||||
|
int choiceCount = 0;
|
||||||
|
for (int i = 0; i < speedChecked.length; i++) {
|
||||||
|
if (speedChecked[i]) {
|
||||||
|
choiceCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String[] newSpeedValues = new String[choiceCount];
|
||||||
|
int newSpeedIndex = 0;
|
||||||
|
for (int i = 0; i < speedChecked.length; i++) {
|
||||||
|
if (speedChecked[i]) {
|
||||||
|
newSpeedValues[newSpeedIndex++] = speedValues[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UserPreferences.setPlaybackSpeedArray(newSpeedValues);
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
builder.create().show();
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,9 +2,13 @@ package de.danoeh.antennapod.preferences;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONException;
|
||||||
|
|
||||||
import android.app.AlarmManager;
|
import android.app.AlarmManager;
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
|
@ -41,11 +45,13 @@ public class UserPreferences implements
|
||||||
public static final String PREF_ENABLE_AUTODL_WIFI_FILTER = "prefEnableAutoDownloadWifiFilter";
|
public static final String PREF_ENABLE_AUTODL_WIFI_FILTER = "prefEnableAutoDownloadWifiFilter";
|
||||||
private static final String PREF_AUTODL_SELECTED_NETWORKS = "prefAutodownloadSelectedNetworks";
|
private static final String PREF_AUTODL_SELECTED_NETWORKS = "prefAutodownloadSelectedNetworks";
|
||||||
public static final String PREF_EPISODE_CACHE_SIZE = "prefEpisodeCacheSize";
|
public static final String PREF_EPISODE_CACHE_SIZE = "prefEpisodeCacheSize";
|
||||||
|
private static final String PREF_PLAYBACK_SPEED = "prefPlaybackSpeed";
|
||||||
|
private static final String PREF_PLAYBACK_SPEED_ARRAY = "prefPlaybackSpeedArray";
|
||||||
|
|
||||||
private static int EPISODE_CACHE_SIZE_UNLIMITED = -1;
|
private static int EPISODE_CACHE_SIZE_UNLIMITED = -1;
|
||||||
|
|
||||||
private static UserPreferences instance;
|
private static UserPreferences instance;
|
||||||
private Context context;
|
private final Context context;
|
||||||
|
|
||||||
// Preferences
|
// Preferences
|
||||||
private boolean pauseOnHeadsetDisconnect;
|
private boolean pauseOnHeadsetDisconnect;
|
||||||
|
@ -60,6 +66,8 @@ public class UserPreferences implements
|
||||||
private boolean enableAutodownloadWifiFilter;
|
private boolean enableAutodownloadWifiFilter;
|
||||||
private String[] autodownloadSelectedNetworks;
|
private String[] autodownloadSelectedNetworks;
|
||||||
private int episodeCacheSize;
|
private int episodeCacheSize;
|
||||||
|
private String playbackSpeed;
|
||||||
|
private String[] playbackSpeedArray;
|
||||||
|
|
||||||
private UserPreferences(Context context) {
|
private UserPreferences(Context context) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
|
@ -83,6 +91,7 @@ public class UserPreferences implements
|
||||||
createNoMediaFile();
|
createNoMediaFile();
|
||||||
PreferenceManager.getDefaultSharedPreferences(context)
|
PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
.registerOnSharedPreferenceChangeListener(instance);
|
.registerOnSharedPreferenceChangeListener(instance);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadPreferences() {
|
private void loadPreferences() {
|
||||||
|
@ -108,6 +117,9 @@ public class UserPreferences implements
|
||||||
episodeCacheSize = readEpisodeCacheSize(sp.getString(
|
episodeCacheSize = readEpisodeCacheSize(sp.getString(
|
||||||
PREF_EPISODE_CACHE_SIZE, "20"));
|
PREF_EPISODE_CACHE_SIZE, "20"));
|
||||||
enableAutodownload = sp.getBoolean(PREF_ENABLE_AUTODL, false);
|
enableAutodownload = sp.getBoolean(PREF_ENABLE_AUTODL, false);
|
||||||
|
playbackSpeed = sp.getString(PREF_PLAYBACK_SPEED, "1.0");
|
||||||
|
playbackSpeedArray = readPlaybackSpeedArray(sp.getString(
|
||||||
|
PREF_PLAYBACK_SPEED_ARRAY, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
private int readThemeValue(String valueFromPrefs) {
|
private int readThemeValue(String valueFromPrefs) {
|
||||||
|
@ -135,6 +147,36 @@ public class UserPreferences implements
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String[] readPlaybackSpeedArray(String valueFromPrefs) {
|
||||||
|
String[] selectedSpeeds = null;
|
||||||
|
// If this preference hasn't been set yet, return the default options
|
||||||
|
if (valueFromPrefs == null) {
|
||||||
|
String[] allSpeeds = context.getResources().getStringArray(
|
||||||
|
R.array.playback_speed_values);
|
||||||
|
List<String> speedList = new LinkedList<String>();
|
||||||
|
for (String speedStr : allSpeeds) {
|
||||||
|
float speed = Float.parseFloat(speedStr);
|
||||||
|
if (speed < 2.0001 && speed * 10 % 1 == 0) {
|
||||||
|
speedList.add(speedStr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
selectedSpeeds = speedList.toArray(new String[speedList.size()]);
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
JSONArray jsonArray = new JSONArray(valueFromPrefs);
|
||||||
|
selectedSpeeds = new String[jsonArray.length()];
|
||||||
|
for (int i = 0; i < jsonArray.length(); i++) {
|
||||||
|
selectedSpeeds[i] = jsonArray.getString(i);
|
||||||
|
}
|
||||||
|
} catch (JSONException e) {
|
||||||
|
Log.e(TAG,
|
||||||
|
"Got JSON error when trying to get speeds from JSONArray");
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return selectedSpeeds;
|
||||||
|
}
|
||||||
|
|
||||||
private static void instanceAvailable() {
|
private static void instanceAvailable() {
|
||||||
if (instance == null) {
|
if (instance == null) {
|
||||||
throw new IllegalStateException(
|
throw new IllegalStateException(
|
||||||
|
@ -196,6 +238,16 @@ public class UserPreferences implements
|
||||||
return EPISODE_CACHE_SIZE_UNLIMITED;
|
return EPISODE_CACHE_SIZE_UNLIMITED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String getPlaybackSpeed() {
|
||||||
|
instanceAvailable();
|
||||||
|
return instance.playbackSpeed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String[] getPlaybackSpeedArray() {
|
||||||
|
instanceAvailable();
|
||||||
|
return instance.playbackSpeedArray;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the capacity of the episode cache. This method will return the
|
* Returns the capacity of the episode cache. This method will return the
|
||||||
* negative integer EPISODE_CACHE_SIZE_UNLIMITED if the cache size is set to
|
* negative integer EPISODE_CACHE_SIZE_UNLIMITED if the cache size is set to
|
||||||
|
@ -250,9 +302,29 @@ public class UserPreferences implements
|
||||||
PREF_EPISODE_CACHE_SIZE, "20"));
|
PREF_EPISODE_CACHE_SIZE, "20"));
|
||||||
} else if (key.equals(PREF_ENABLE_AUTODL)) {
|
} else if (key.equals(PREF_ENABLE_AUTODL)) {
|
||||||
enableAutodownload = sp.getBoolean(PREF_ENABLE_AUTODL, false);
|
enableAutodownload = sp.getBoolean(PREF_ENABLE_AUTODL, false);
|
||||||
|
} else if (key.equals(PREF_PLAYBACK_SPEED)) {
|
||||||
|
playbackSpeed = sp.getString(PREF_PLAYBACK_SPEED, "1.0");
|
||||||
|
} else if (key.equals(PREF_PLAYBACK_SPEED_ARRAY)) {
|
||||||
|
playbackSpeedArray = readPlaybackSpeedArray(sp.getString(
|
||||||
|
PREF_PLAYBACK_SPEED_ARRAY, null));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void setPlaybackSpeed(String speed) {
|
||||||
|
PreferenceManager.getDefaultSharedPreferences(instance.context).edit()
|
||||||
|
.putString(PREF_PLAYBACK_SPEED, speed).apply();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setPlaybackSpeedArray(String[] speeds) {
|
||||||
|
JSONArray jsonArray = new JSONArray();
|
||||||
|
for (String speed : speeds) {
|
||||||
|
jsonArray.put(speed);
|
||||||
|
}
|
||||||
|
PreferenceManager.getDefaultSharedPreferences(instance.context).edit()
|
||||||
|
.putString(PREF_PLAYBACK_SPEED_ARRAY, jsonArray.toString())
|
||||||
|
.apply();
|
||||||
|
}
|
||||||
|
|
||||||
public static void setAutodownloadSelectedNetworks(Context context,
|
public static void setAutodownloadSelectedNetworks(Context context,
|
||||||
String[] value) {
|
String[] value) {
|
||||||
SharedPreferences.Editor editor = PreferenceManager
|
SharedPreferences.Editor editor = PreferenceManager
|
||||||
|
|
|
@ -141,12 +141,12 @@ public class PlaybackService extends Service {
|
||||||
|
|
||||||
private static final int NOTIFICATION_ID = 1;
|
private static final int NOTIFICATION_ID = 1;
|
||||||
|
|
||||||
private IPlayer player;
|
private volatile IPlayer player;
|
||||||
private RemoteControlClient remoteControlClient;
|
private RemoteControlClient remoteControlClient;
|
||||||
private AudioManager audioManager;
|
private AudioManager audioManager;
|
||||||
private ComponentName mediaButtonReceiver;
|
private ComponentName mediaButtonReceiver;
|
||||||
|
|
||||||
private Playable media;
|
private volatile Playable media;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* True if media should be streamed (Extracted from Intent Extra) .
|
* True if media should be streamed (Extracted from Intent Extra) .
|
||||||
|
@ -260,8 +260,6 @@ public class PlaybackService extends Service {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
dbLoaderExecutor = Executors.newSingleThreadExecutor();
|
dbLoaderExecutor = Executors.newSingleThreadExecutor();
|
||||||
player = createMediaPlayer();
|
|
||||||
|
|
||||||
|
|
||||||
mediaButtonReceiver = new ComponentName(getPackageName(),
|
mediaButtonReceiver = new ComponentName(getPackageName(),
|
||||||
MediaButtonReceiver.class.getName());
|
MediaButtonReceiver.class.getName());
|
||||||
|
@ -598,6 +596,7 @@ public class PlaybackService extends Service {
|
||||||
Log.d(TAG, "Setting up media player");
|
Log.d(TAG, "Setting up media player");
|
||||||
try {
|
try {
|
||||||
MediaType mediaType = media.getMediaType();
|
MediaType mediaType = media.getMediaType();
|
||||||
|
player = createMediaPlayer();
|
||||||
if (mediaType == MediaType.AUDIO) {
|
if (mediaType == MediaType.AUDIO) {
|
||||||
if (AppConfig.DEBUG)
|
if (AppConfig.DEBUG)
|
||||||
Log.d(TAG, "Mime type is audio");
|
Log.d(TAG, "Mime type is audio");
|
||||||
|
@ -1033,6 +1032,7 @@ public class PlaybackService extends Service {
|
||||||
Log.d(TAG, "Resuming/Starting playback");
|
Log.d(TAG, "Resuming/Starting playback");
|
||||||
writePlaybackPreferences();
|
writePlaybackPreferences();
|
||||||
|
|
||||||
|
setSpeed(Float.parseFloat(UserPreferences.getPlaybackSpeed()));
|
||||||
player.start();
|
player.start();
|
||||||
if (status != PlayerStatus.PAUSED) {
|
if (status != PlayerStatus.PAUSED) {
|
||||||
player.seekTo((int) media.getPosition());
|
player.seekTo((int) media.getPosition());
|
||||||
|
@ -1579,6 +1579,53 @@ public class PlaybackService extends Service {
|
||||||
postStatusUpdateIntent();
|
postStatusUpdateIntent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean canSetSpeed() {
|
||||||
|
if (player != null && media != null && media.getMediaType() == MediaType.AUDIO) {
|
||||||
|
return ((AudioPlayer) player).canSetSpeed();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean canSetPitch() {
|
||||||
|
if (player != null && media != null && media.getMediaType() == MediaType.AUDIO) {
|
||||||
|
return ((AudioPlayer) player).canSetPitch();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSpeed(float speed) {
|
||||||
|
if (media != null && media.getMediaType() == MediaType.AUDIO) {
|
||||||
|
AudioPlayer audioPlayer = (AudioPlayer) player;
|
||||||
|
if (audioPlayer.canSetSpeed()) {
|
||||||
|
audioPlayer.setPlaybackSpeed((float) speed);
|
||||||
|
if (AppConfig.DEBUG)
|
||||||
|
Log.d(TAG, "Playback speed was set to " + speed);
|
||||||
|
sendNotificationBroadcast(
|
||||||
|
NOTIFICATION_TYPE_PLAYBACK_SPEED_CHANGE, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPitch(float pitch) {
|
||||||
|
if (media != null && media.getMediaType() == MediaType.AUDIO) {
|
||||||
|
AudioPlayer audioPlayer = (AudioPlayer) player;
|
||||||
|
if (audioPlayer.canSetPitch()) {
|
||||||
|
audioPlayer.setPlaybackPitch((float) pitch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getCurrentPlaybackSpeed() {
|
||||||
|
if (media.getMediaType() == MediaType.AUDIO
|
||||||
|
&& player instanceof AudioPlayer) {
|
||||||
|
AudioPlayer audioPlayer = (AudioPlayer) player;
|
||||||
|
if (audioPlayer.canSetSpeed()) {
|
||||||
|
return audioPlayer.getCurrentSpeedMultiplier();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* call getDuration() on mediaplayer or return INVALID_TIME if player is in
|
* call getDuration() on mediaplayer or return INVALID_TIME if player is in
|
||||||
* an invalid state. This method should be used instead of calling
|
* an invalid state. This method should be used instead of calling
|
||||||
|
@ -1633,52 +1680,6 @@ public class PlaybackService extends Service {
|
||||||
editor.commit();
|
editor.commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean canSetSpeed() {
|
|
||||||
if (media != null && media.getMediaType() == MediaType.AUDIO) {
|
|
||||||
return player.canSetSpeed();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean canSetPitch() {
|
|
||||||
if (media != null && media.getMediaType() == MediaType.AUDIO) {
|
|
||||||
return player.canSetPitch();
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSpeed(double speed) {
|
|
||||||
if (media != null && media.getMediaType() == MediaType.AUDIO) {
|
|
||||||
AudioPlayer audioPlayer = (AudioPlayer) player;
|
|
||||||
if (audioPlayer.canSetSpeed()) {
|
|
||||||
audioPlayer.setPlaybackSpeed((float) speed);
|
|
||||||
if (AppConfig.DEBUG)
|
|
||||||
Log.d(TAG, "Playback speed was set to " + speed);
|
|
||||||
sendNotificationBroadcast(
|
|
||||||
NOTIFICATION_TYPE_PLAYBACK_SPEED_CHANGE, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPitch(double pitch) {
|
|
||||||
if (media != null && media.getMediaType() == MediaType.AUDIO) {
|
|
||||||
if (player.canSetPitch()) {
|
|
||||||
player.setPlaybackPitch((float) pitch);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getCurrentPlaybackSpeed() {
|
|
||||||
if (media.getMediaType() == MediaType.AUDIO
|
|
||||||
&& player instanceof AudioPlayer) {
|
|
||||||
AudioPlayer audioPlayer = (AudioPlayer) player;
|
|
||||||
if (audioPlayer.canSetSpeed()) {
|
|
||||||
return audioPlayer.getCurrentSpeedMultiplier();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class InitTask extends AsyncTask<Playable, Void, Playable> {
|
private static class InitTask extends AsyncTask<Playable, Void, Playable> {
|
||||||
private Playable playable;
|
private Playable playable;
|
||||||
public PlayableException exception;
|
public PlayableException exception;
|
||||||
|
|
|
@ -668,6 +668,24 @@ public abstract class PlaybackController {
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean canSetPlaybackSpeed() {
|
||||||
|
return playbackService != null && playbackService.canSetSpeed();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPlaybackSpeed(float speed) {
|
||||||
|
if (playbackService != null) {
|
||||||
|
playbackService.setSpeed(speed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getCurrentPlaybackSpeedMultiplier() {
|
||||||
|
if (canSetPlaybackSpeed()) {
|
||||||
|
return playbackService.getCurrentPlaybackSpeed();
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isPlayingVideo() {
|
public boolean isPlayingVideo() {
|
||||||
if (playbackService != null) {
|
if (playbackService != null) {
|
||||||
return PlaybackService.isPlayingVideo();
|
return PlaybackService.isPlayingVideo();
|
||||||
|
@ -675,23 +693,6 @@ public abstract class PlaybackController {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean canSetPlaybackSpeed() {
|
|
||||||
return playbackService != null && playbackService.canSetSpeed();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setPlaybackSpeed(double speed) {
|
|
||||||
if (playbackService != null) {
|
|
||||||
playbackService.setSpeed(speed);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getCurrentPlaybackSpeedMultiplier() {
|
|
||||||
if (canSetPlaybackSpeed()) {
|
|
||||||
return playbackService.getCurrentPlaybackSpeed();
|
|
||||||
} else {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if PlaybackController can communicate with the playback
|
* Returns true if PlaybackController can communicate with the playback
|
||||||
|
|
Loading…
Reference in New Issue