package org.commcare.views.media;
import android.animation.ObjectAnimator;
import android.annotation.TargetApi;
import android.content.Context;
import android.os.Build;
import android.os.Handler;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.LinearInterpolator;
import android.widget.ProgressBar;
import android.widget.TextView;
import org.commcare.dalvik.R;
import java.util.concurrent.TimeUnit;
/**
* Audio playback widget with clickable horizontal progress bar
*
* @author Phillip Mates (pmates@dimagi.com)
*/
@TargetApi(Build.VERSION_CODES.KITKAT)
public class ExpandedAudioPlaybackView extends AudioPlaybackButtonBase {
private ProgressBar seekBar;
private ObjectAnimator animation;
private Handler handler;
private TextView progressText;
private int playbackDurationMillis;
/**
* Used by media inflater.
*/
public ExpandedAudioPlaybackView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ExpandedAudioPlaybackView(Context context, String URI, int questionIndex) {
super(context, URI, ViewId.buildListViewId(questionIndex), true);
}
@Override
protected void setupView(Context context) {
super.setupView(context);
progressText = (TextView)findViewById(R.id.duration_info);
setupProgressBar();
setupProgressAnimation();
}
private void setupProgressBar() {
seekBar = (ProgressBar)findViewById(R.id.seek_bar);
seekBar.setEnabled(true);
seekBar.setOnTouchListener(
new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return performProgressBarTouch(v, event);
}
});
}
private void setupProgressAnimation() {
final int startPosition = 0;
animation = ObjectAnimator.ofInt(seekBar, "progress", startPosition, seekBar.getMax());
animation.setInterpolator(new LinearInterpolator());
}
@Override
protected int getLayout() {
return R.layout.expanded_audio_playback;
}
@Override
protected void startProgressBar(int currentPositionMillis, int milliDuration) {
playbackDurationMillis = milliDuration;
animation.setCurrentPlayTime(currentPositionMillis);
animation.setDuration(playbackDurationMillis);
animation.start();
launchElapseTextUpdaterThread();
}
private boolean performProgressBarTouch(View v, MotionEvent event) {
int progress = (int)(playbackDurationMillis * (event.getX() / v.getWidth()));
animation.setCurrentPlayTime(progress);
updateProgressText(progress, playbackDurationMillis);
if (AudioController.INSTANCE.doesCurrentMediaCorrespondToButton(ExpandedAudioPlaybackView.this)) {
AudioController.INSTANCE.seekTo(progress);
}
return true;
}
private void launchElapseTextUpdaterThread() {
handler = new Handler();
this.post(new Runnable() {
@Override
public void run() {
// make sure we are playing this audio
if (AudioController.INSTANCE.doesCurrentMediaCorrespondToButton(ExpandedAudioPlaybackView.this)) {
int pos = AudioController.INSTANCE.getCurrentPosition();
updateProgressText(pos, playbackDurationMillis);
handler.postDelayed(this, 20);
}
}
});
}
@Override
protected void resetProgressBar() {
if (handler != null) {
handler.removeCallbacksAndMessages(null);
handler = null;
}
if (animation != null) {
animation.removeAllListeners();
animation.end();
animation.cancel();
}
if (seekBar != null) {
seekBar.clearAnimation();
seekBar.setProgress(0);
updateProgressText(0, seekBar.getMax());
}
}
@Override
protected void pauseProgressBar() {
if (handler != null) {
handler.removeCallbacksAndMessages(null);
}
animation.pause();
}
private void updateProgressText(int progress, int max) {
progressText.setText(milliToHumanReadable(progress) + " / " + milliToHumanReadable(max));
}
private static String milliToHumanReadable(int millis) {
return String.format("%02d:%02d",
TimeUnit.MILLISECONDS.toMinutes(millis),
TimeUnit.MILLISECONDS.toSeconds(millis) -
TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(millis))
);
}
}