summaryrefslogtreecommitdiff
path: root/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java
diff options
context:
space:
mode:
Diffstat (limited to 'app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java')
-rw-r--r--app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java879
1 files changed, 879 insertions, 0 deletions
diff --git a/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java b/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java
new file mode 100644
index 000000000..ce8672b59
--- /dev/null
+++ b/app/src/main/java/de/danoeh/antennapod/activity/MediaplayerActivity.java
@@ -0,0 +1,879 @@
+package de.danoeh.antennapod.activity;
+
+import android.annotation.TargetApi;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.res.TypedArray;
+import android.graphics.Color;
+import android.graphics.PixelFormat;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Bundle;
+import android.support.v7.app.AlertDialog;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.Button;
+import android.widget.CheckBox;
+import android.widget.ImageButton;
+import android.widget.SeekBar;
+import android.widget.SeekBar.OnSeekBarChangeListener;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.afollestad.materialdialogs.MaterialDialog;
+import com.bumptech.glide.Glide;
+import com.joanzapata.iconify.IconDrawable;
+import com.joanzapata.iconify.fonts.FontAwesomeIcons;
+
+import java.util.Locale;
+
+import de.danoeh.antennapod.R;
+import de.danoeh.antennapod.core.feed.FeedItem;
+import de.danoeh.antennapod.core.feed.FeedMedia;
+import de.danoeh.antennapod.core.preferences.UserPreferences;
+import de.danoeh.antennapod.core.service.playback.PlaybackService;
+import de.danoeh.antennapod.core.storage.DBReader;
+import de.danoeh.antennapod.core.storage.DBTasks;
+import de.danoeh.antennapod.core.storage.DBWriter;
+import de.danoeh.antennapod.core.util.Converter;
+import de.danoeh.antennapod.core.util.Flavors;
+import de.danoeh.antennapod.core.util.ShareUtils;
+import de.danoeh.antennapod.core.util.StorageUtils;
+import de.danoeh.antennapod.core.util.playback.MediaPlayerError;
+import de.danoeh.antennapod.core.util.playback.Playable;
+import de.danoeh.antennapod.core.util.playback.PlaybackController;
+import de.danoeh.antennapod.dialog.SleepTimerDialog;
+import de.danoeh.antennapod.dialog.VariableSpeedDialog;
+import rx.Observable;
+import rx.android.schedulers.AndroidSchedulers;
+import rx.schedulers.Schedulers;
+
+
+/**
+ * Provides general features which are both needed for playing audio and video
+ * files.
+ */
+public abstract class MediaplayerActivity extends CastEnabledActivity implements OnSeekBarChangeListener {
+ private static final String TAG = "MediaplayerActivity";
+ private static final String PREFS = "MediaPlayerActivityPreferences";
+ private static final String PREF_SHOW_TIME_LEFT = "showTimeLeft";
+
+ protected PlaybackController controller;
+
+ protected TextView txtvPosition;
+ protected TextView txtvLength;
+ protected SeekBar sbPosition;
+ protected ImageButton butRev;
+ protected TextView txtvRev;
+ protected ImageButton butPlay;
+ protected ImageButton butFF;
+ protected TextView txtvFF;
+ protected ImageButton butSkip;
+
+ protected boolean showTimeLeft = false;
+
+ private boolean isFavorite = false;
+
+ private PlaybackController newPlaybackController() {
+ return new PlaybackController(this, false) {
+
+ @Override
+ public void setupGUI() {
+ MediaplayerActivity.this.setupGUI();
+ }
+
+ @Override
+ public void onPositionObserverUpdate() {
+ MediaplayerActivity.this.onPositionObserverUpdate();
+ }
+
+ @Override
+ public void onBufferStart() {
+ MediaplayerActivity.this.onBufferStart();
+ }
+
+ @Override
+ public void onBufferEnd() {
+ MediaplayerActivity.this.onBufferEnd();
+ }
+
+ @Override
+ public void onBufferUpdate(float progress) {
+ MediaplayerActivity.this.onBufferUpdate(progress);
+ }
+
+ @Override
+ public void handleError(int code) {
+ MediaplayerActivity.this.handleError(code);
+ }
+
+ @Override
+ public void onReloadNotification(int code) {
+ MediaplayerActivity.this.onReloadNotification(code);
+ }
+
+ @Override
+ public void onSleepTimerUpdate() {
+ supportInvalidateOptionsMenu();
+ }
+
+ @Override
+ public ImageButton getPlayButton() {
+ return butPlay;
+ }
+
+ @Override
+ public void postStatusMsg(int msg, boolean showToast) {
+ MediaplayerActivity.this.postStatusMsg(msg, showToast);
+ }
+
+ @Override
+ public void clearStatusMsg() {
+ MediaplayerActivity.this.clearStatusMsg();
+ }
+
+ @Override
+ public boolean loadMediaInfo() {
+ return MediaplayerActivity.this.loadMediaInfo();
+ }
+
+ @Override
+ public void onAwaitingVideoSurface() {
+ MediaplayerActivity.this.onAwaitingVideoSurface();
+ }
+
+ @Override
+ public void onServiceQueried() {
+ MediaplayerActivity.this.onServiceQueried();
+ }
+
+ @Override
+ public void onShutdownNotification() {
+ finish();
+ }
+
+ @Override
+ public void onPlaybackEnd() {
+ finish();
+ }
+
+ @Override
+ public void onPlaybackSpeedChange() {
+ MediaplayerActivity.this.onPlaybackSpeedChange();
+ }
+
+ @Override
+ protected void setScreenOn(boolean enable) {
+ super.setScreenOn(enable);
+ MediaplayerActivity.this.setScreenOn(enable);
+ }
+
+ @Override
+ public void onSetSpeedAbilityChanged() {
+ MediaplayerActivity.this.onSetSpeedAbilityChanged();
+ }
+ };
+ }
+
+ protected void onSetSpeedAbilityChanged() {
+ Log.d(TAG, "onSetSpeedAbilityChanged()");
+ updatePlaybackSpeedButton();
+ }
+
+ protected void onPlaybackSpeedChange() {
+ updatePlaybackSpeedButtonText();
+ }
+
+ protected void onServiceQueried() {
+ supportInvalidateOptionsMenu();
+ }
+
+ protected void chooseTheme() {
+ setTheme(UserPreferences.getTheme());
+ }
+
+ protected void setScreenOn(boolean enable) {
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ chooseTheme();
+ super.onCreate(savedInstanceState);
+
+ Log.d(TAG, "onCreate()");
+ StorageUtils.checkStorageAvailability(this);
+
+ orientation = getResources().getConfiguration().orientation;
+ getWindow().setFormat(PixelFormat.TRANSPARENT);
+ }
+
+ @Override
+ protected void onPause() {
+ if(controller != null) {
+ controller.reinitServiceIfPaused();
+ controller.pause();
+ }
+ super.onPause();
+ }
+
+ /**
+ * Should be used to switch to another player activity if the mime type is
+ * not the correct one for the current activity.
+ */
+ protected abstract void onReloadNotification(int notificationCode);
+
+ /**
+ * Should be used to inform the user that the PlaybackService is currently
+ * buffering.
+ */
+ protected abstract void onBufferStart();
+
+ /**
+ * Should be used to hide the view that was showing the 'buffering'-message.
+ */
+ protected abstract void onBufferEnd();
+
+ protected void onBufferUpdate(float progress) {
+ if (sbPosition != null) {
+ sbPosition.setSecondaryProgress((int) progress * sbPosition.getMax());
+ }
+ }
+
+ /**
+ * Current screen orientation.
+ */
+ protected int orientation;
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ if (controller != null) {
+ controller.release();
+ }
+ controller = newPlaybackController();
+ }
+
+ @Override
+ protected void onStop() {
+ Log.d(TAG, "onStop()");
+ if (controller != null) {
+ controller.release();
+ controller = null; // prevent leak
+ }
+ super.onStop();
+ }
+
+ @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
+ @Override
+ public void onTrimMemory(int level) {
+ super.onTrimMemory(level);
+ Glide.get(this).trimMemory(level);
+ }
+
+ @Override
+ public void onLowMemory() {
+ super.onLowMemory();
+ Glide.get(this).clearMemory();
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ super.onCreateOptionsMenu(menu);
+ if (Flavors.FLAVOR == Flavors.PLAY) {
+ requestCastButton(MenuItem.SHOW_AS_ACTION_ALWAYS);
+ }
+ MenuInflater inflater = getMenuInflater();
+ inflater.inflate(R.menu.mediaplayer, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onPrepareOptionsMenu(Menu menu) {
+ super.onPrepareOptionsMenu(menu);
+ if (controller == null) {
+ return false;
+ }
+ Playable media = controller.getMedia();
+
+ menu.findItem(R.id.support_item).setVisible(
+ media != null && media.getPaymentLink() != null &&
+ (media instanceof FeedMedia) &&
+ ((FeedMedia) media).getItem() != null &&
+ ((FeedMedia) media).getItem().getFlattrStatus().flattrable()
+ );
+
+ boolean hasWebsiteLink = media != null && media.getWebsiteLink() != null;
+ menu.findItem(R.id.visit_website_item).setVisible(hasWebsiteLink);
+
+ boolean isItemAndHasLink = media != null && (media instanceof FeedMedia) &&
+ ((FeedMedia) media).getItem() != null && ((FeedMedia) media).getItem().getLink() != null;
+ menu.findItem(R.id.share_link_item).setVisible(isItemAndHasLink);
+ menu.findItem(R.id.share_link_with_position_item).setVisible(isItemAndHasLink);
+
+ boolean isItemHasDownloadLink = media != null && (media instanceof FeedMedia) && ((FeedMedia) media).getDownload_url() != null;
+ menu.findItem(R.id.share_download_url_item).setVisible(isItemHasDownloadLink);
+ menu.findItem(R.id.share_download_url_with_position_item).setVisible(isItemHasDownloadLink);
+
+ menu.findItem(R.id.share_item).setVisible(hasWebsiteLink || isItemAndHasLink || isItemHasDownloadLink);
+
+ menu.findItem(R.id.add_to_favorites_item).setVisible(false);
+ menu.findItem(R.id.remove_from_favorites_item).setVisible(false);
+ if(media != null && media instanceof FeedMedia) {
+ menu.findItem(R.id.add_to_favorites_item).setVisible(!isFavorite);
+ menu.findItem(R.id.remove_from_favorites_item).setVisible(isFavorite);
+ }
+
+ boolean sleepTimerSet = controller.sleepTimerActive();
+ boolean sleepTimerNotSet = controller.sleepTimerNotActive();
+ menu.findItem(R.id.set_sleeptimer_item).setVisible(sleepTimerNotSet);
+ menu.findItem(R.id.disable_sleeptimer_item).setVisible(sleepTimerSet);
+
+ if (this instanceof AudioplayerActivity) {
+ int[] attrs = {R.attr.action_bar_icon_color};
+ TypedArray ta = obtainStyledAttributes(UserPreferences.getTheme(), attrs);
+ int textColor = ta.getColor(0, Color.GRAY);
+ ta.recycle();
+ menu.findItem(R.id.audio_controls).setIcon(new IconDrawable(this,
+ FontAwesomeIcons.fa_sliders).color(textColor).actionBarSize());
+ } else {
+ menu.findItem(R.id.audio_controls).setVisible(false);
+ }
+
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ if (controller == null) {
+ return false;
+ }
+ Playable media = controller.getMedia();
+ if (item.getItemId() == android.R.id.home) {
+ Intent intent = new Intent(MediaplayerActivity.this,
+ MainActivity.class);
+ intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP
+ | Intent.FLAG_ACTIVITY_NEW_TASK);
+ startActivity(intent);
+ return true;
+ } else {
+ if (media != null) {
+ switch (item.getItemId()) {
+ case R.id.add_to_favorites_item:
+ if(media instanceof FeedMedia) {
+ FeedItem feedItem = ((FeedMedia)media).getItem();
+ if(feedItem != null) {
+ DBWriter.addFavoriteItem(feedItem);
+ isFavorite = true;
+ invalidateOptionsMenu();
+ Toast.makeText(this, R.string.added_to_favorites, Toast.LENGTH_SHORT)
+ .show();
+ }
+ }
+ break;
+ case R.id.remove_from_favorites_item:
+ if(media instanceof FeedMedia) {
+ FeedItem feedItem = ((FeedMedia)media).getItem();
+ if(feedItem != null) {
+ DBWriter.removeFavoriteItem(feedItem);
+ isFavorite = false;
+ invalidateOptionsMenu();
+ Toast.makeText(this, R.string.removed_from_favorites, Toast.LENGTH_SHORT)
+ .show();
+ }
+ }
+ break;
+ case R.id.disable_sleeptimer_item:
+ if (controller.serviceAvailable()) {
+
+ MaterialDialog.Builder stDialog = new MaterialDialog.Builder(this);
+ stDialog.title(R.string.sleep_timer_label);
+ stDialog.content(getString(R.string.time_left_label)
+ + Converter.getDurationStringLong((int) controller
+ .getSleepTimerTimeLeft()));
+ stDialog.positiveText(R.string.disable_sleeptimer_label);
+ stDialog.negativeText(R.string.cancel_label);
+ stDialog.onPositive((dialog, which) -> {
+ dialog.dismiss();
+ controller.disableSleepTimer();
+ });
+ stDialog.onNegative((dialog, which) -> dialog.dismiss());
+ stDialog.build().show();
+ }
+ break;
+ case R.id.set_sleeptimer_item:
+ if (controller.serviceAvailable()) {
+ SleepTimerDialog td = new SleepTimerDialog(this) {
+ @Override
+ public void onTimerSet(long millis, boolean shakeToReset, boolean vibrate) {
+ controller.setSleepTimer(millis, shakeToReset, vibrate);
+ }
+ };
+ td.createNewDialog().show();
+ }
+ break;
+ case R.id.audio_controls:
+ MaterialDialog dialog = new MaterialDialog.Builder(this)
+ .title(R.string.audio_controls)
+ .customView(R.layout.audio_controls, true)
+ .neutralText(R.string.close_label)
+ .onNeutral((dialog1, which) -> {
+ final SeekBar left = (SeekBar) dialog1.findViewById(R.id.volume_left);
+ final SeekBar right = (SeekBar) dialog1.findViewById(R.id.volume_right);
+ UserPreferences.setVolume(left.getProgress(), right.getProgress());
+ })
+ .show();
+ final SeekBar barPlaybackSpeed = (SeekBar) dialog.findViewById(R.id.playback_speed);
+ final Button butDecSpeed = (Button) dialog.findViewById(R.id.butDecSpeed);
+ butDecSpeed.setOnClickListener(v -> {
+ if(controller != null && controller.canSetPlaybackSpeed()) {
+ barPlaybackSpeed.setProgress(barPlaybackSpeed.getProgress() - 2);
+ } else {
+ VariableSpeedDialog.showGetPluginDialog(this);
+ }
+ });
+ final Button butIncSpeed = (Button) dialog.findViewById(R.id.butIncSpeed);
+ butIncSpeed.setOnClickListener(v -> {
+ if(controller != null && controller.canSetPlaybackSpeed()) {
+ barPlaybackSpeed.setProgress(barPlaybackSpeed.getProgress() + 2);
+ } else {
+ VariableSpeedDialog.showGetPluginDialog(this);
+ }
+ });
+
+ final TextView txtvPlaybackSpeed = (TextView) dialog.findViewById(R.id.txtvPlaybackSpeed);
+ float currentSpeed = 1.0f;
+ try {
+ currentSpeed = Float.parseFloat(UserPreferences.getPlaybackSpeed());
+ } catch (NumberFormatException e) {
+ Log.e(TAG, Log.getStackTraceString(e));
+ UserPreferences.setPlaybackSpeed(String.valueOf(currentSpeed));
+ }
+
+ txtvPlaybackSpeed.setText(String.format("%.2fx", currentSpeed));
+ barPlaybackSpeed.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+ if(controller != null && controller.canSetPlaybackSpeed()) {
+ float playbackSpeed = (progress + 10) / 20.0f;
+ controller.setPlaybackSpeed(playbackSpeed);
+ String speedPref = String.format(Locale.US, "%.2f", playbackSpeed);
+ UserPreferences.setPlaybackSpeed(speedPref);
+ String speedStr = String.format("%.2fx", playbackSpeed);
+ txtvPlaybackSpeed.setText(speedStr);
+ } else if(fromUser) {
+ float speed = Float.valueOf(UserPreferences.getPlaybackSpeed());
+ barPlaybackSpeed.post(() -> barPlaybackSpeed.setProgress((int) (20 * speed) - 10));
+ }
+ }
+
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {
+ if(controller != null && !controller.canSetPlaybackSpeed()) {
+ VariableSpeedDialog.showGetPluginDialog(MediaplayerActivity.this);
+ }
+ }
+
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {
+ }
+ });
+ barPlaybackSpeed.setProgress((int) (20 * currentSpeed) - 10);
+
+ final SeekBar barLeftVolume = (SeekBar) dialog.findViewById(R.id.volume_left);
+ barLeftVolume.setProgress(UserPreferences.getLeftVolumePercentage());
+ final SeekBar barRightVolume = (SeekBar) dialog.findViewById(R.id.volume_right);
+ barRightVolume.setProgress(UserPreferences.getRightVolumePercentage());
+ final CheckBox stereoToMono = (CheckBox) dialog.findViewById(R.id.stereo_to_mono);
+ stereoToMono.setChecked(UserPreferences.stereoToMono());
+ if (controller != null && !controller.canDownmix()) {
+ stereoToMono.setEnabled(false);
+ String sonicOnly = getString(R.string.sonic_only);
+ stereoToMono.setText(stereoToMono.getText() + " [" + sonicOnly + "]");
+ }
+
+ barLeftVolume.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+ controller.setVolume(
+ Converter.getVolumeFromPercentage(progress),
+ Converter.getVolumeFromPercentage(barRightVolume.getProgress()));
+ }
+
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {
+ }
+
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {
+ }
+ });
+ barRightVolume.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
+ @Override
+ public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
+ controller.setVolume(
+ Converter.getVolumeFromPercentage(barLeftVolume.getProgress()),
+ Converter.getVolumeFromPercentage(progress));
+ }
+
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {
+ }
+
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {
+ }
+ });
+ stereoToMono.setOnCheckedChangeListener((buttonView, isChecked) -> {
+ UserPreferences.stereoToMono(isChecked);
+ if (controller != null) {
+ controller.setDownmix(isChecked);
+ }
+ });
+ break;
+ case R.id.visit_website_item:
+ Uri uri = Uri.parse(media.getWebsiteLink());
+ startActivity(new Intent(Intent.ACTION_VIEW, uri));
+ break;
+ case R.id.support_item:
+ if (media instanceof FeedMedia) {
+ DBTasks.flattrItemIfLoggedIn(this, ((FeedMedia) media).getItem());
+ }
+ break;
+ case R.id.share_link_item:
+ if (media instanceof FeedMedia) {
+ ShareUtils.shareFeedItemLink(this, ((FeedMedia) media).getItem());
+ }
+ break;
+ case R.id.share_download_url_item:
+ if (media instanceof FeedMedia) {
+ ShareUtils.shareFeedItemDownloadLink(this, ((FeedMedia) media).getItem());
+ }
+ break;
+ case R.id.share_link_with_position_item:
+ if (media instanceof FeedMedia) {
+ ShareUtils.shareFeedItemLink(this, ((FeedMedia) media).getItem(), true);
+ }
+ break;
+ case R.id.share_download_url_with_position_item:
+ if (media instanceof FeedMedia) {
+ ShareUtils.shareFeedItemDownloadLink(this, ((FeedMedia) media).getItem(), true);
+ }
+ break;
+ default:
+ return false;
+ }
+ return true;
+ } else {
+ return false;
+ }
+ }
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ Log.d(TAG, "onResume()");
+ StorageUtils.checkStorageAvailability(this);
+ if(controller != null) {
+ controller.init();
+ }
+ }
+
+ /**
+ * Called by 'handleStatus()' when the PlaybackService is waiting for
+ * a video surface.
+ */
+ protected abstract void onAwaitingVideoSurface();
+
+ protected abstract void postStatusMsg(int resId, boolean showToast);
+
+ protected abstract void clearStatusMsg();
+
+ protected void onPositionObserverUpdate() {
+ if (controller == null || txtvPosition == null || txtvLength == null) {
+ return;
+ }
+ int currentPosition = controller.getPosition();
+ int duration = controller.getDuration();
+ Log.d(TAG, "currentPosition " + Converter.getDurationStringLong(currentPosition));
+ if (currentPosition == PlaybackService.INVALID_TIME ||
+ duration == PlaybackService.INVALID_TIME) {
+ Log.w(TAG, "Could not react to position observer update because of invalid time");
+ return;
+ }
+ txtvPosition.setText(Converter.getDurationStringLong(currentPosition));
+ if (showTimeLeft) {
+ txtvLength.setText("-" + Converter.getDurationStringLong(duration - currentPosition));
+ } else {
+ txtvLength.setText(Converter.getDurationStringLong(duration));
+ }
+ updateProgressbarPosition(currentPosition, duration);
+ }
+
+ private void updateProgressbarPosition(int position, int duration) {
+ Log.d(TAG, "updateProgressbarPosition(" + position + ", " + duration + ")");
+ if(sbPosition == null) {
+ return;
+ }
+ float progress = ((float) position) / duration;
+ sbPosition.setProgress((int) (progress * sbPosition.getMax()));
+ }
+
+ /**
+ * Load information about the media that is going to be played or currently
+ * being played. This method will be called when the activity is connected
+ * to the PlaybackService to ensure that the activity has the right
+ * FeedMedia object.
+ */
+ protected boolean loadMediaInfo() {
+ Log.d(TAG, "loadMediaInfo()");
+ Playable media = controller.getMedia();
+ SharedPreferences prefs = getSharedPreferences(PREFS, MODE_PRIVATE);
+ showTimeLeft = prefs.getBoolean(PREF_SHOW_TIME_LEFT, false);
+ if (media != null) {
+ onPositionObserverUpdate();
+ checkFavorite();
+ updatePlaybackSpeedButton();
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ protected void updatePlaybackSpeedButton() {
+ // Only meaningful on AudioplayerActivity, where it is overridden.
+ }
+
+ protected void updatePlaybackSpeedButtonText() {
+ // Only meaningful on AudioplayerActivity, where it is overridden.
+ }
+
+
+ protected void setupGUI() {
+ setContentView(getContentViewResourceId());
+ sbPosition = (SeekBar) findViewById(R.id.sbPosition);
+ txtvPosition = (TextView) findViewById(R.id.txtvPosition);
+
+ SharedPreferences prefs = getSharedPreferences(PREFS, MODE_PRIVATE);
+ showTimeLeft = prefs.getBoolean(PREF_SHOW_TIME_LEFT, false);
+ Log.d("timeleft", showTimeLeft ? "true" : "false");
+ txtvLength = (TextView) findViewById(R.id.txtvLength);
+ if (txtvLength != null) {
+ txtvLength.setOnClickListener(v -> {
+ showTimeLeft = !showTimeLeft;
+ Playable media = controller.getMedia();
+ if (media == null) {
+ return;
+ }
+
+ String length;
+ if (showTimeLeft) {
+ length = "-" + Converter.getDurationStringLong(media.getDuration() - media.getPosition());
+ } else {
+ length = Converter.getDurationStringLong(media.getDuration());
+ }
+ txtvLength.setText(length);
+
+ SharedPreferences.Editor editor = prefs.edit();
+ editor.putBoolean(PREF_SHOW_TIME_LEFT, showTimeLeft);
+ editor.apply();
+ Log.d("timeleft on click", showTimeLeft ? "true" : "false");
+ });
+ }
+
+ butRev = (ImageButton) findViewById(R.id.butRev);
+ txtvRev = (TextView) findViewById(R.id.txtvRev);
+ if (txtvRev != null) {
+ txtvRev.setText(String.valueOf(UserPreferences.getRewindSecs()));
+ }
+ butPlay = (ImageButton) findViewById(R.id.butPlay);
+ butFF = (ImageButton) findViewById(R.id.butFF);
+ txtvFF = (TextView) findViewById(R.id.txtvFF);
+ if (txtvFF != null) {
+ txtvFF.setText(String.valueOf(UserPreferences.getFastFowardSecs()));
+ }
+ butSkip = (ImageButton) findViewById(R.id.butSkip);
+
+ // SEEKBAR SETUP
+
+ sbPosition.setOnSeekBarChangeListener(this);
+
+ // BUTTON SETUP
+
+ if (butRev != null) {
+ butRev.setOnClickListener(v -> onRewind());
+ butRev.setOnLongClickListener(new View.OnLongClickListener() {
+
+ int choice;
+
+ @Override
+ public boolean onLongClick(View v) {
+ int checked = 0;
+ int rewindSecs = UserPreferences.getRewindSecs();
+ final int[] values = getResources().getIntArray(R.array.seek_delta_values);
+ final String[] choices = new String[values.length];
+ for (int i = 0; i < values.length; i++) {
+ if (rewindSecs == values[i]) {
+ checked = i;
+ }
+ choices[i] = String.valueOf(values[i]) + " " + getString(R.string.time_seconds);
+ }
+ choice = values[checked];
+ AlertDialog.Builder builder = new AlertDialog.Builder(MediaplayerActivity.this);
+ builder.setTitle(R.string.pref_rewind);
+ builder.setSingleChoiceItems(choices, checked,
+ (dialog, which) -> {
+ choice = values[which];
+ });
+ builder.setNegativeButton(R.string.cancel_label, null);
+ builder.setPositiveButton(R.string.confirm_label, (dialog, which) -> {
+ UserPreferences.setPrefRewindSecs(choice);
+ if(txtvRev != null){
+ txtvRev.setText(String.valueOf(choice));
+ }
+ });
+ builder.create().show();
+ return true;
+ }
+ });
+ }
+
+ butPlay.setOnClickListener(v -> onPlayPause());
+
+ if (butFF != null) {
+ butFF.setOnClickListener(v -> onFastForward());
+ butFF.setOnLongClickListener(new View.OnLongClickListener() {
+
+ int choice;
+
+ @Override
+ public boolean onLongClick(View v) {
+ int checked = 0;
+ int rewindSecs = UserPreferences.getFastFowardSecs();
+ final int[] values = getResources().getIntArray(R.array.seek_delta_values);
+ final String[] choices = new String[values.length];
+ for (int i = 0; i < values.length; i++) {
+ if (rewindSecs == values[i]) {
+ checked = i;
+ }
+ choices[i] = String.valueOf(values[i]) + " " + getString(R.string.time_seconds);
+ }
+ choice = values[checked];
+ AlertDialog.Builder builder = new AlertDialog.Builder(MediaplayerActivity.this);
+ builder.setTitle(R.string.pref_fast_forward);
+ builder.setSingleChoiceItems(choices, checked,
+ (dialog, which) -> {
+ choice = values[which];
+ });
+ builder.setNegativeButton(R.string.cancel_label, null);
+ builder.setPositiveButton(R.string.confirm_label, (dialog, which) -> {
+ UserPreferences.setPrefFastForwardSecs(choice);
+ if(txtvFF != null) {
+ txtvFF.setText(String.valueOf(choice));
+ }
+ });
+ builder.create().show();
+ return true;
+ }
+ });
+ }
+
+ if (butSkip != null) {
+ butSkip.setOnClickListener(v -> sendBroadcast(new Intent(PlaybackService.ACTION_SKIP_CURRENT_EPISODE)));
+ }
+ }
+
+ protected void onRewind() {
+ if (controller == null) {
+ return;
+ }
+ int curr = controller.getPosition();
+ controller.seekTo(curr - UserPreferences.getRewindSecs() * 1000);
+ }
+
+ protected void onPlayPause() {
+ if(controller == null) {
+ return;
+ }
+ controller.playPause();
+ }
+
+ protected void onFastForward() {
+ if (controller == null) {
+ return;
+ }
+ int curr = controller.getPosition();
+ controller.seekTo(curr + UserPreferences.getFastFowardSecs() * 1000);
+ }
+
+ protected abstract int getContentViewResourceId();
+
+ void handleError(int errorCode) {
+ final AlertDialog.Builder errorDialog = new AlertDialog.Builder(this);
+ errorDialog.setTitle(R.string.error_label);
+ errorDialog.setMessage(MediaPlayerError.getErrorString(this, errorCode));
+ errorDialog.setNeutralButton("OK",
+ (dialog, which) -> {
+ dialog.dismiss();
+ finish();
+ }
+ );
+ errorDialog.create().show();
+ }
+
+ float prog;
+
+ @Override
+ public void onProgressChanged (SeekBar seekBar,int progress, boolean fromUser) {
+ if (controller == null || txtvLength == null) {
+ return;
+ }
+ prog = controller.onSeekBarProgressChanged(seekBar, progress, fromUser, txtvPosition);
+ if (showTimeLeft && prog != 0) {
+ int duration = controller.getDuration();
+ String length = "-" + Converter.getDurationStringLong(duration - (int) (prog * duration));
+ txtvLength.setText(length);
+ }
+ }
+
+ @Override
+ public void onStartTrackingTouch(SeekBar seekBar) {
+ if (controller != null) {
+ controller.onSeekBarStartTrackingTouch(seekBar);
+ }
+ }
+
+ @Override
+ public void onStopTrackingTouch(SeekBar seekBar) {
+ if (controller != null) {
+ controller.onSeekBarStopTrackingTouch(seekBar, prog);
+ }
+ }
+
+ private void checkFavorite() {
+ Playable playable = controller.getMedia();
+ if (playable != null && playable instanceof FeedMedia) {
+ FeedItem feedItem = ((FeedMedia) playable).getItem();
+ if (feedItem != null) {
+ Observable.fromCallable(() -> DBReader.getFeedItem(feedItem.getId()))
+ .subscribeOn(Schedulers.newThread())
+ .observeOn(AndroidSchedulers.mainThread())
+ .subscribe(
+ item -> {
+ boolean isFav = item.isTagged(FeedItem.TAG_FAVORITE);
+ if (isFavorite != isFav) {
+ isFavorite = isFav;
+ invalidateOptionsMenu();
+ }
+ }, error -> {
+ Log.e(TAG, Log.getStackTraceString(error));
+ }
+ );
+ }
+ }
+ }
+
+}