Skip to content

Commit

Permalink
Gesture support
Browse files Browse the repository at this point in the history
  • Loading branch information
AndreyPavlenko committed Jun 1, 2020
1 parent ff5abc5 commit b1bafff
Show file tree
Hide file tree
Showing 5 changed files with 169 additions and 60 deletions.
2 changes: 1 addition & 1 deletion depends/utils
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
Expand Down Expand Up @@ -96,11 +95,6 @@ public MediaSessionCallback getMediaSessionCallback() {
return sessionCallback;
}

@NonNull
public MediaControllerCompat getMediaController() {
return mediaController;
}

@NonNull
public MediaLib getLib() {
return getMediaSessionCallback().getMediaLib();
Expand All @@ -126,19 +120,12 @@ public void playItem(PlayableItem i) {
}

public void playItem(PlayableItem i, long pos) {
MediaControllerCompat mediaController = getMediaController();

if (i.equals(getCurrentItem()) && (pos <= 0)) {
PlaybackStateCompat st = mediaController.getPlaybackState();
if ((st != null) && (st.getState() == PlaybackStateCompat.STATE_PAUSED)) {
mediaController.getTransportControls().play();
if (sessionCallback.getPlaybackState().getState() == PlaybackStateCompat.STATE_PAUSED) {
sessionCallback.onPlay();
}
} else if (pos > 0) {
Bundle b = new Bundle();
b.putLong(MediaSessionCallback.EXTRA_POS, pos);
mediaController.getTransportControls().playFromMediaId(i.getId(), b);
} else {
mediaController.getTransportControls().playFromMediaId(i.getId(), null);
sessionCallback.playItem(i, pos);
}
}

Expand Down Expand Up @@ -166,24 +153,16 @@ private boolean onPlayPauseButtonLongClick(View v) {

public void bindPrevButton(View v) {
prevButton = v;
v.setOnClickListener(this::onPrevButtonClick);
v.setOnClickListener(this::onPrevNextButtonClick);
v.setOnLongClickListener(this::onPrevNextButtonLongClick);
}

private void onPrevButtonClick(View v) {
mediaController.getTransportControls().skipToPrevious();
}

public void bindNextButton(View v) {
nextButton = v;
v.setOnClickListener(this::onNextButtonClick);
v.setOnClickListener(this::onPrevNextButtonClick);
v.setOnLongClickListener(this::onPrevNextButtonLongClick);
}

private void onNextButtonClick(View v) {
mediaController.getTransportControls().skipToNext();
}

public void bindRwButton(View v) {
rwButton = v;
v.setOnClickListener(this::onRwFfButtonClick);
Expand All @@ -196,6 +175,37 @@ public void bindFfButton(View v) {
v.setOnLongClickListener(this::onRwFfButtonLongClick);
}

private void onPrevNextButtonClick(View v) {
onPrevNextButtonClick(v == nextButton);
}

public void onPrevNextButtonClick(boolean next) {
if (next) mediaController.getTransportControls().skipToNext();
else mediaController.getTransportControls().skipToPrevious();
}

private boolean onPrevNextButtonLongClick(View v) {
onPrevNextButtonLongClick(v == nextButton);
return true;
}

public void onPrevNextButtonLongClick(boolean next) {
MediaSessionCallback cb = getMediaSessionCallback();
PlaybackControlPrefs pp = cb.getPlaybackControlPrefs();
cb.rewindFastForward(next, pp.getPrevNextLongTimePref(),
pp.getPrevNextLongTimeUnitPref(), 1);
}

public void onPrevNextFolderClick(boolean next) {
PlayableItem i = sessionCallback.getCurrentItem();
if (i == null) return;
MediaLib.BrowsableItem p = i.getParent();
FutureSupplier<PlayableItem> f = next ? p.getNextPlayable() : p.getPrevPlayable();
f.onSuccess(pi -> {
if (pi != null) sessionCallback.playItem(pi, 0);
});
}

private void onRwFfButtonClick(View v) {
onRwFfButtonClick(v == ffButton);
}
Expand All @@ -219,14 +229,6 @@ public void onRwFfButtonLongClick(boolean ff) {
cb.rewindFastForward(ff, pp.getRwFfLongTimePref(), pp.getRwFfLongTimeUnitPref(), 1);
}

private boolean onPrevNextButtonLongClick(View v) {
MediaSessionCallback cb = getMediaSessionCallback();
PlaybackControlPrefs pp = cb.getPlaybackControlPrefs();
cb.rewindFastForward(v == nextButton, pp.getPrevNextLongTimePref(),
pp.getPrevNextLongTimeUnitPref(), 1);
return true;
}

public void bindProgressBar(SeekBar progressBar) {
this.progressBar = progressBar;
progressBar.setEnabled(false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,7 @@ private FutureSupplier<Void> play() {
case PlaybackStateCompat.STATE_STOPPED:
case PlaybackStateCompat.STATE_ERROR:
return lib.getLastPlayedItem().then(this::prepareItem).then(i -> {
if (i != null) playItem(i, lib.getLastPlayedPosition(i));
if (i != null) playPreparedItem(i, lib.getLastPlayedPosition(i));
return completedVoid();
});
case PlaybackStateCompat.STATE_PAUSED:
Expand Down Expand Up @@ -437,7 +437,7 @@ private FutureSupplier<Void> playFromMediaId(String mediaId, Bundle extras) {
}).then(this::prepareItem).then(pi -> {
if (pi != null) {
long pos = (extras == null) ? 0 : extras.getLong(EXTRA_POS, 0);
playItem(pi, pos);
playPreparedItem(pi, pos);
} else {
String msg = lib.getContext().getResources().getString(R.string.err_failed_to_play, mediaId);
Log.w(msg);
Expand Down Expand Up @@ -568,7 +568,7 @@ private void skipTo(boolean next, PlayableItem i) {
b.setState(next ? STATE_SKIPPING_TO_NEXT : STATE_SKIPPING_TO_PREVIOUS, state.getPosition(),
state.getPlaybackSpeed());
setPlaybackState(b.build());
playItem(i, 0);
playPreparedItem(i, 0);
}

@Override
Expand Down Expand Up @@ -749,7 +749,7 @@ private FutureSupplier<Void> skipToQueueItem(PlayableItem pi, long queueId) {
b.setState(PlaybackStateCompat.STATE_SKIPPING_TO_QUEUE_ITEM, state.getPosition(),
state.getPlaybackSpeed());
setPlaybackState(b.build());
playItem(i, 0);
playPreparedItem(i, 0);
return completedVoid();
});
}
Expand Down Expand Up @@ -1030,23 +1030,28 @@ public void onAudioFocusChange(int focusChange) {
}
}

private void playItem(PlayableItem i, long pos) {
public void playItem(PlayableItem i, long pos) {
playerTask.cancel();
playerTask = prepareItem(i).onSuccess(pi -> playPreparedItem(i, pos));
}

private void playPreparedItem(PlayableItem i, long pos) {
MediaEngine eng = getEngine();

if (eng != null) {
PlayableItem current = eng.getSource();

if ((current != null) && !current.isExternal()) {
eng.getPosition().main().onSuccess(currentPos
-> playItem(eng, i, pos, current, currentPos));
-> playPreparedItem(eng, i, pos, current, currentPos));
return;
}
}

playItem(eng, i, pos, null, -1);
playPreparedItem(eng, i, pos, null, -1);
}

private void playItem(MediaEngine eng, PlayableItem i, long pos, PlayableItem current, long currentPos) {
private void playPreparedItem(MediaEngine eng, PlayableItem i, long pos, PlayableItem current, long currentPos) {
engine = eng = getEngineManager().createEngine(eng, i, this);

if (eng == null) {
Expand Down
132 changes: 118 additions & 14 deletions fermata/src/main/java/me/aap/fermata/ui/view/ControlPanelView.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.media.AudioManager;
import android.os.Bundle;
import android.os.Parcelable;
import android.util.AttributeSet;
Expand All @@ -13,6 +14,7 @@

import androidx.annotation.Nullable;
import androidx.appcompat.widget.LinearLayoutCompat;
import androidx.core.view.GestureDetectorCompat;

import java.util.List;

Expand Down Expand Up @@ -43,23 +45,33 @@
import me.aap.utils.ui.UiUtils;
import me.aap.utils.ui.menu.OverlayMenu;
import me.aap.utils.ui.menu.OverlayMenuItem;
import me.aap.utils.ui.view.GestureListener;
import me.aap.utils.ui.view.ImageButton;

import static android.media.AudioManager.ADJUST_LOWER;
import static android.media.AudioManager.ADJUST_RAISE;
import static android.media.AudioManager.FLAG_SHOW_UI;
import static android.media.AudioManager.STREAM_MUSIC;

/**
* @author Andrey Pavlenko
*/
public class ControlPanelView extends LinearLayoutCompat implements MainActivityListener,
PreferenceStore.Listener, OverlayMenu.SelectionHandler {
PreferenceStore.Listener, OverlayMenu.SelectionHandler, GestureListener {
private static final byte MASK_VISIBLE = 1;
private static final byte MASK_VIDEO_MODE = 2;
private final GestureDetectorCompat gestureDetector;
private final ImageButton showHideBars;
private PlaybackControlPrefs prefs;
private HideTimer hideTimer;
private byte mask;
private View gestureSource;
private long scrollStamp;

@SuppressLint("PrivateResource")
public ControlPanelView(Context context, AttributeSet attrs) {
super(context, attrs, R.attr.appControlPanelStyle);
gestureDetector = new GestureDetectorCompat(context, this);
setOrientation(VERTICAL);
inflate(context, R.layout.control_panel_view, this);

Expand Down Expand Up @@ -120,15 +132,6 @@ public boolean isActive() {
return mask != 0;
}

@Override
public boolean onInterceptTouchEvent(MotionEvent e) {
if (hideTimer != null) {
hideTimer = new HideTimer(hideTimer.views);
FermataApplication.get().getHandler().postDelayed(hideTimer, getTouchDelay());
}
return getActivity().interceptTouchEvent(e, super::onTouchEvent);
}

@Override
public void setVisibility(int visibility) {
if (visibility == VISIBLE) {
Expand Down Expand Up @@ -197,12 +200,102 @@ public void disableVideoMode() {
setShowHideBarsIcon(a);
}

public void onVideoViewTouch(VideoView view) {
@Override
public boolean onInterceptTouchEvent(MotionEvent e) {
if (hideTimer != null) {
hideTimer = new HideTimer(hideTimer.views);
FermataApplication.get().getHandler().postDelayed(hideTimer, getTouchDelay());
}
return getActivity().interceptTouchEvent(e, me -> {
gestureSource = this;
gestureDetector.onTouchEvent(me);
return super.onTouchEvent(me);
});
}

@Override
public boolean onSwipeLeft(MotionEvent e1, MotionEvent e2) {
getActivity().getMediaServiceBinder().onPrevNextButtonClick(true);
return true;
}

@Override
public boolean onSwipeRight(MotionEvent e1, MotionEvent e2) {
getActivity().getMediaServiceBinder().onPrevNextButtonClick(false);
return true;
}

@Override
public boolean onSwipeUp(MotionEvent e1, MotionEvent e2) {
getActivity().getMediaServiceBinder().onPrevNextFolderClick(false);
return true;
}

@Override
public boolean onSwipeDown(MotionEvent e1, MotionEvent e2) {
getActivity().getMediaServiceBinder().onPrevNextFolderClick(true);
return true;
}

@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
boolean horizontal = Math.abs(distanceX) >= Math.abs(distanceY);
long time = System.currentTimeMillis();
long diff;

if (horizontal) {
diff = time - scrollStamp;
if (diff < 100) return true;
scrollStamp = time;
} else {
diff = time + scrollStamp;
if (diff < 100) return true;
scrollStamp = -time;
}

if (diff > 500) return true;

if (horizontal) {
FermataServiceUiBinder b = getActivity().getMediaServiceBinder();

switch (e2.getPointerCount()) {
case 1:
b.onRwFfButtonClick(distanceX < 0);
break;
case 2:
b.onRwFfButtonLongClick(distanceX < 0);
break;
default:
b.onPrevNextButtonLongClick(distanceX < 0);
break;
}

onVideoSeek();
} else {
AudioManager amgr = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
if (amgr == null) return false;
amgr.adjustStreamVolume(STREAM_MUSIC, (distanceY > 0) ? ADJUST_RAISE : ADJUST_LOWER, FLAG_SHOW_UI);
}

return true;
}

@Override
public boolean onDoubleTap(MotionEvent e) {
if (!(gestureSource instanceof VideoView)) return false;
getActivity().getMediaServiceBinder().onPlayPauseButtonClick();
return true;
}

@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
if (!(gestureSource instanceof VideoView)) return false;

int delay = getTouchDelay();
if (delay == 0) return;
if (delay == 0) return false;

MainActivityDelegate a = getActivity();
View title = view.getTitle();
View title = ((VideoView) gestureSource).getTitle();
View fb = a.getFloatingButton();

if (getVisibility() == VISIBLE) {
Expand All @@ -217,12 +310,23 @@ public void onVideoViewTouch(VideoView view) {
hideTimer = new HideTimer(title, fb);
App.get().getHandler().postDelayed(hideTimer, delay);
}

return true;
}

public void onVideoViewTouch(VideoView view, MotionEvent e) {
gestureSource = view;
gestureDetector.onTouchEvent(e);
}

public void onVideoSeek() {
MainActivityDelegate a = getActivity();
VideoView vv = a.getMediaServiceBinder().getMediaSessionCallback().getVideoView();
if (vv == null) return;

if (vv == null) {
if (gestureSource instanceof VideoView) vv = (VideoView) gestureSource;
else return;
}

View title = vv.getTitle();
View fb = a.getFloatingButton();
Expand Down
Loading

0 comments on commit b1bafff

Please sign in to comment.