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>
|
||||||
@ -43,4 +97,5 @@
|
|||||||
<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>
|
||||||
@ -144,6 +146,12 @@
|
|||||||
<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>
|
||||||
<string name="no_feeds_label">You haven\'t subscribed to any feeds yet.</string>
|
<string name="no_feeds_label">You haven\'t subscribed to any feeds yet.</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 -->
|
||||||
|
@ -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,6 +42,7 @@ 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;
|
||||||
|
|
||||||
@ -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
|
||||||
|
94
src/de/danoeh/antennapod/dialog/VariableSpeedDialog.java
Normal file
94
src/de/danoeh/antennapod/dialog/VariableSpeedDialog.java
Normal file
@ -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…
x
Reference in New Issue
Block a user