Fix seeking voice notes that do not have waveforms.
This commit is contained in:
parent
082d9e852c
commit
bd3b14a27f
9 changed files with 56 additions and 50 deletions
|
@ -57,8 +57,8 @@ public interface BindableConversationItem extends Unbindable {
|
|||
void onRegisterVoiceNoteCallbacks(@NonNull Observer<VoiceNotePlaybackState> onPlaybackStartObserver);
|
||||
void onUnregisterVoiceNoteCallbacks(@NonNull Observer<VoiceNotePlaybackState> onPlaybackStartObserver);
|
||||
void onVoiceNotePause(@NonNull Uri uri);
|
||||
void onVoiceNotePlay(@NonNull Uri uri, long messageId, long position);
|
||||
void onVoiceNoteSeekTo(@NonNull Uri uri, long position);
|
||||
void onVoiceNotePlay(@NonNull Uri uri, long messageId, double position);
|
||||
void onVoiceNoteSeekTo(@NonNull Uri uri, double position);
|
||||
|
||||
/** @return true if handled, false if you want to let the normal url handling continue */
|
||||
boolean onUrlClicked(@NonNull String url);
|
||||
|
|
|
@ -192,7 +192,7 @@ public final class AudioView extends FrameLayout {
|
|||
private void onPlaybackState(@NonNull VoiceNotePlaybackState voiceNotePlaybackState) {
|
||||
onStart(voiceNotePlaybackState.getUri(), voiceNotePlaybackState.isAutoReset());
|
||||
onProgress(voiceNotePlaybackState.getUri(),
|
||||
(double) voiceNotePlaybackState.getPlayheadPositionMillis() / durationMillis,
|
||||
(double) voiceNotePlaybackState.getPlayheadPositionMillis() / voiceNotePlaybackState.getTrackDuration(),
|
||||
voiceNotePlaybackState.getPlayheadPositionMillis());
|
||||
}
|
||||
|
||||
|
@ -258,7 +258,7 @@ public final class AudioView extends FrameLayout {
|
|||
}
|
||||
|
||||
private void onProgress(@NonNull Uri uri, double progress, long millis) {
|
||||
if (!Objects.equals(uri, audioSlide.getUri())) {
|
||||
if (audioSlide == null || !Objects.equals(uri, audioSlide.getUri())) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -358,7 +358,7 @@ public final class AudioView extends FrameLayout {
|
|||
|
||||
if (callbacks != null) {
|
||||
if (lottieDirection == REVERSE) {
|
||||
callbacks.onPlay(audioSlide.getUri(), getPosition());
|
||||
callbacks.onPlay(audioSlide.getUri(), getProgress());
|
||||
} else {
|
||||
callbacks.onPause(audioSlide.getUri());
|
||||
}
|
||||
|
@ -371,10 +371,6 @@ public final class AudioView extends FrameLayout {
|
|||
updateProgress(0, 0);
|
||||
}
|
||||
|
||||
private long getPosition() {
|
||||
return (long) (getProgress() * durationMillis);
|
||||
}
|
||||
|
||||
private class DownloadClickedListener implements View.OnClickListener {
|
||||
private final @NonNull AudioSlide slide;
|
||||
|
||||
|
@ -394,10 +390,6 @@ public final class AudioView extends FrameLayout {
|
|||
|
||||
@Override
|
||||
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
|
||||
if (fromUser && durationMillis > 0) {
|
||||
float progressFloat = progress / (float) seekBar.getMax();
|
||||
updateProgress(progressFloat, (long) (durationMillis * progressFloat));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -418,7 +410,7 @@ public final class AudioView extends FrameLayout {
|
|||
|
||||
if (callbacks != null) {
|
||||
if (wasPlaying) {
|
||||
callbacks.onSeekTo(audioSlide.getUri(), getPosition());
|
||||
callbacks.onSeekTo(audioSlide.getUri(), getProgress());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -439,9 +431,9 @@ public final class AudioView extends FrameLayout {
|
|||
}
|
||||
|
||||
public interface Callbacks {
|
||||
void onPlay(@NonNull Uri audioUri, long position);
|
||||
void onPlay(@NonNull Uri audioUri, double progress);
|
||||
void onPause(@NonNull Uri audioUri);
|
||||
void onSeekTo(@NonNull Uri audioUri, long position);
|
||||
void onSeekTo(@NonNull Uri audioUri, double progress);
|
||||
void onStopAndReset(@NonNull Uri audioUri);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ import java.util.Objects;
|
|||
public class VoiceNoteMediaController implements DefaultLifecycleObserver {
|
||||
|
||||
public static final String EXTRA_MESSAGE_ID = "voice.note.message_id";
|
||||
public static final String EXTRA_PLAYHEAD = "voice.note.playhead";
|
||||
public static final String EXTRA_PROGRESS = "voice.note.playhead";
|
||||
public static final String EXTRA_PLAY_SINGLE = "voice.note.play.single";
|
||||
|
||||
private static final String TAG = Log.tag(VoiceNoteMediaController.class);
|
||||
|
@ -97,12 +97,12 @@ public class VoiceNoteMediaController implements DefaultLifecycleObserver {
|
|||
}
|
||||
|
||||
|
||||
public void startConsecutivePlayback(@NonNull Uri audioSlideUri, long messageId, long position) {
|
||||
startPlayback(audioSlideUri, messageId, position, false);
|
||||
public void startConsecutivePlayback(@NonNull Uri audioSlideUri, long messageId, double progress) {
|
||||
startPlayback(audioSlideUri, messageId, progress, false);
|
||||
}
|
||||
|
||||
public void startSinglePlayback(@NonNull Uri audioSlideUri, long messageId, long position) {
|
||||
startPlayback(audioSlideUri, messageId, position, true);
|
||||
public void startSinglePlayback(@NonNull Uri audioSlideUri, long messageId, double progress) {
|
||||
startPlayback(audioSlideUri, messageId, progress, true);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -111,17 +111,19 @@ public class VoiceNoteMediaController implements DefaultLifecycleObserver {
|
|||
*
|
||||
* @param audioSlideUri The Uri of the desired audio slide
|
||||
* @param messageId The Message id of the given audio slide
|
||||
* @param position The desired position in milliseconds at which to start playback.
|
||||
* @param progress The desired progress % to seek to.
|
||||
* @param singlePlayback The player will only play back the specified Uri, and not build a playlist.
|
||||
*/
|
||||
private void startPlayback(@NonNull Uri audioSlideUri, long messageId, long position, boolean singlePlayback) {
|
||||
private void startPlayback(@NonNull Uri audioSlideUri, long messageId, double progress, boolean singlePlayback) {
|
||||
if (isCurrentTrack(audioSlideUri)) {
|
||||
getMediaController().getTransportControls().seekTo(position);
|
||||
long duration = getMediaController().getMetadata().getLong(MediaMetadataCompat.METADATA_KEY_DURATION);
|
||||
|
||||
getMediaController().getTransportControls().seekTo((long) (duration * progress));
|
||||
getMediaController().getTransportControls().play();
|
||||
} else {
|
||||
Bundle extras = new Bundle();
|
||||
extras.putLong(EXTRA_MESSAGE_ID, messageId);
|
||||
extras.putLong(EXTRA_PLAYHEAD, position);
|
||||
extras.putDouble(EXTRA_PROGRESS, progress);
|
||||
extras.putBoolean(EXTRA_PLAY_SINGLE, singlePlayback);
|
||||
|
||||
getMediaController().getTransportControls().playFromUri(audioSlideUri, extras);
|
||||
|
@ -144,12 +146,14 @@ public class VoiceNoteMediaController implements DefaultLifecycleObserver {
|
|||
* is ignored if the given audio slide is not currently playing.
|
||||
*
|
||||
* @param audioSlideUri The Uri of the audio slide to seek.
|
||||
* @param position The position in milliseconds to seek to.
|
||||
* @param progress The progress percentage to seek to.
|
||||
*/
|
||||
public void seekToPosition(@NonNull Uri audioSlideUri, long position) {
|
||||
public void seekToPosition(@NonNull Uri audioSlideUri, double progress) {
|
||||
if (isCurrentTrack(audioSlideUri)) {
|
||||
long duration = getMediaController().getMetadata().getLong(MediaMetadataCompat.METADATA_KEY_DURATION);
|
||||
|
||||
getMediaController().getTransportControls().pause();
|
||||
getMediaController().getTransportControls().seekTo(position);
|
||||
getMediaController().getTransportControls().seekTo((long) (duration * progress));
|
||||
getMediaController().getTransportControls().play();
|
||||
}
|
||||
}
|
||||
|
@ -226,6 +230,7 @@ public class VoiceNoteMediaController implements DefaultLifecycleObserver {
|
|||
|
||||
voiceNotePlaybackState.postValue(new VoiceNotePlaybackState(mediaUri,
|
||||
mediaController.getPlaybackState().getPosition(),
|
||||
mediaMetadataCompat.getLong(MediaMetadataCompat.METADATA_KEY_DURATION),
|
||||
autoReset));
|
||||
|
||||
sendEmptyMessageDelayed(0, 50);
|
||||
|
|
|
@ -89,7 +89,7 @@ final class VoiceNotePlaybackPreparer implements MediaSessionConnector.PlaybackP
|
|||
@Override
|
||||
public void onPrepareFromUri(final Uri uri, Bundle extras) {
|
||||
long messageId = extras.getLong(VoiceNoteMediaController.EXTRA_MESSAGE_ID);
|
||||
long position = extras.getLong(VoiceNoteMediaController.EXTRA_PLAYHEAD, 0);
|
||||
double progress = extras.getDouble(VoiceNoteMediaController.EXTRA_PROGRESS, 0);
|
||||
boolean singlePlayback = extras.getBoolean(VoiceNoteMediaController.EXTRA_PLAY_SINGLE, false);
|
||||
|
||||
canLoadMore = false;
|
||||
|
@ -116,7 +116,7 @@ final class VoiceNotePlaybackPreparer implements MediaSessionConnector.PlaybackP
|
|||
@Override
|
||||
public void onTimelineChanged(Timeline timeline, @Nullable Object manifest, int reason) {
|
||||
if (timeline.getWindowCount() >= window) {
|
||||
player.seekTo(window, position);
|
||||
player.seekTo(window, (long) (player.getDuration() * progress));
|
||||
player.removeListener(this);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,15 +9,17 @@ import androidx.annotation.NonNull;
|
|||
*/
|
||||
public class VoiceNotePlaybackState {
|
||||
|
||||
public static final VoiceNotePlaybackState NONE = new VoiceNotePlaybackState(Uri.EMPTY, 0, false);
|
||||
public static final VoiceNotePlaybackState NONE = new VoiceNotePlaybackState(Uri.EMPTY, 0, 0, false);
|
||||
|
||||
private final Uri uri;
|
||||
private final long playheadPositionMillis;
|
||||
private final long trackDuration;
|
||||
private final boolean autoReset;
|
||||
|
||||
public VoiceNotePlaybackState(@NonNull Uri uri, long playheadPositionMillis, boolean autoReset) {
|
||||
public VoiceNotePlaybackState(@NonNull Uri uri, long playheadPositionMillis, long trackDuration, boolean autoReset) {
|
||||
this.uri = uri;
|
||||
this.playheadPositionMillis = playheadPositionMillis;
|
||||
this.trackDuration = trackDuration;
|
||||
this.autoReset = autoReset;
|
||||
}
|
||||
|
||||
|
@ -35,6 +37,13 @@ public class VoiceNotePlaybackState {
|
|||
return playheadPositionMillis;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The track duration in ms
|
||||
*/
|
||||
public long getTrackDuration() {
|
||||
return trackDuration;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if we should reset the currently playing clip.
|
||||
*/
|
||||
|
|
|
@ -1377,13 +1377,13 @@ public class ConversationFragment extends LoggingFragment {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onVoiceNotePlay(@NonNull Uri uri, long messageId, long position) {
|
||||
voiceNoteMediaController.startConsecutivePlayback(uri, messageId, position);
|
||||
public void onVoiceNotePlay(@NonNull Uri uri, long messageId, double progress) {
|
||||
voiceNoteMediaController.startConsecutivePlayback(uri, messageId, progress);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onVoiceNoteSeekTo(@NonNull Uri uri, long position) {
|
||||
voiceNoteMediaController.seekToPosition(uri, position);
|
||||
public void onVoiceNoteSeekTo(@NonNull Uri uri, double progress) {
|
||||
voiceNoteMediaController.seekToPosition(uri, progress);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1548,10 +1548,10 @@ public class ConversationItem extends LinearLayout implements BindableConversati
|
|||
private final class AudioViewCallbacks implements AudioView.Callbacks {
|
||||
|
||||
@Override
|
||||
public void onPlay(@NonNull Uri audioUri, long position) {
|
||||
public void onPlay(@NonNull Uri audioUri, double progress) {
|
||||
if (eventListener == null) return;
|
||||
|
||||
eventListener.onVoiceNotePlay(audioUri, messageRecord.getId(), position);
|
||||
eventListener.onVoiceNotePlay(audioUri, messageRecord.getId(), progress);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1562,10 +1562,10 @@ public class ConversationItem extends LinearLayout implements BindableConversati
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onSeekTo(@NonNull Uri audioUri, long position) {
|
||||
public void onSeekTo(@NonNull Uri audioUri, double progress) {
|
||||
if (eventListener == null) return;
|
||||
|
||||
eventListener.onVoiceNoteSeekTo(audioUri, position);
|
||||
eventListener.onVoiceNoteSeekTo(audioUri, progress);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -502,8 +502,8 @@ final class MediaGalleryAllAdapter extends StickyHeaderGridAdapter {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onPlay(@NonNull Uri audioUri, long position) {
|
||||
audioItemListener.onPlay(audioUri, position, messageId);
|
||||
public void onPlay(@NonNull Uri audioUri, double progress) {
|
||||
audioItemListener.onPlay(audioUri, progress, messageId);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -512,8 +512,8 @@ final class MediaGalleryAllAdapter extends StickyHeaderGridAdapter {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onSeekTo(@NonNull Uri audioUri, long position) {
|
||||
audioItemListener.onSeekTo(audioUri, position);
|
||||
public void onSeekTo(@NonNull Uri audioUri, double progress) {
|
||||
audioItemListener.onSeekTo(audioUri, progress);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -528,9 +528,9 @@ final class MediaGalleryAllAdapter extends StickyHeaderGridAdapter {
|
|||
}
|
||||
|
||||
interface AudioItemListener {
|
||||
void onPlay(@NonNull Uri audioUri, long position, long messageId);
|
||||
void onPlay(@NonNull Uri audioUri, double progress, long messageId);
|
||||
void onPause(@NonNull Uri audioUri);
|
||||
void onSeekTo(@NonNull Uri audioUri, long position);
|
||||
void onSeekTo(@NonNull Uri audioUri, double progress);
|
||||
void onStopAndReset(@NonNull Uri audioUri);
|
||||
void registerPlaybackStateObserver(@NonNull Observer<VoiceNotePlaybackState> observer);
|
||||
void unregisterPlaybackStateObserver(@NonNull Observer<VoiceNotePlaybackState> observer);
|
||||
|
|
|
@ -311,8 +311,8 @@ public final class MediaOverviewPageFragment extends Fragment
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onPlay(@NonNull Uri audioUri, long position, long messageId) {
|
||||
voiceNoteMediaController.startSinglePlayback(audioUri, messageId, position);
|
||||
public void onPlay(@NonNull Uri audioUri, double progress, long messageId) {
|
||||
voiceNoteMediaController.startSinglePlayback(audioUri, messageId, progress);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -321,8 +321,8 @@ public final class MediaOverviewPageFragment extends Fragment
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onSeekTo(@NonNull Uri audioUri, long position) {
|
||||
voiceNoteMediaController.seekToPosition(audioUri, position);
|
||||
public void onSeekTo(@NonNull Uri audioUri, double progress) {
|
||||
voiceNoteMediaController.seekToPosition(audioUri, progress);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
Loading…
Add table
Reference in a new issue