* @see WebVTT specification
*/
public final class WebvttDecoder extends SimpleSubtitleDecoder {
private static final int EVENT_NONE = -1;
private static final int EVENT_END_OF_FILE = 0;
private static final int EVENT_COMMENT = 1;
private static final int EVENT_STYLE_BLOCK = 2;
private static final int EVENT_CUE = 3;
private static final String COMMENT_START = "NOTE";
private static final String STYLE_START = "STYLE";
private final WebvttCueParser cueParser;
private final ParsableByteArray parsableWebvttData;
private final WebvttCue.Builder webvttCueBuilder;
private final CssParser cssParser;
private final List
* It can be workaround by forcing {@link android.media.MediaPlayer#start()} when it was already playing.
*/
class BuggyVideoDriverPreventer {
private final MediaPlayerTypeReader mediaPlayerTypeReader;
private OnPotentialBuggyDriverLayoutListener preventerListener;
BuggyVideoDriverPreventer(MediaPlayerTypeReader mediaPlayerTypeReader) {
this.mediaPlayerTypeReader = mediaPlayerTypeReader;
}
void preventVideoDriverBug(NoPlayer player, View containerView) {
if (videoDriverCanBeBuggy()) {
attemptToCorrectMediaPlayerStatus(player, containerView);
}
}
private boolean videoDriverCanBeBuggy() {
return mediaPlayerTypeReader.getPlayerType() == AndroidMediaPlayerType.AWESOME;
}
private void attemptToCorrectMediaPlayerStatus(NoPlayer player, View containerView) {
preventerListener = new OnPotentialBuggyDriverLayoutListener(player);
containerView.addOnLayoutChangeListener(preventerListener);
}
void clear(View containerView) {
containerView.removeOnLayoutChangeListener(preventerListener);
preventerListener = null;
}
}
================================================
FILE: core/src/main/java/com/novoda/noplayer/internal/mediaplayer/CheckBufferHeartbeatCallback.java
================================================
package com.novoda.noplayer.internal.mediaplayer;
import com.novoda.noplayer.NoPlayer;
public class CheckBufferHeartbeatCallback implements NoPlayer.HeartbeatCallback {
private static final int FORCED_BUFFERING_BEATS_THRESHOLD = 4;
private BufferListener bufferListener = BufferListener.NULL_IMPL;
private long previousPositionInMillis = -1;
private int beatsPlayed;
public void bind(BufferListener bufferListener) {
this.bufferListener = bufferListener;
}
@Override
public void onBeat(NoPlayer player) {
if (mediaPlayerIsUnavailable(player)) {
stopBuffering();
return;
}
long currentPositionInMillis = player.playheadPositionInMillis();
if (positionNotUpdating(currentPositionInMillis)) {
beatsPlayed = 0;
startBuffering();
} else {
previousPositionInMillis = currentPositionInMillis;
beatsPlayed++;
if (beatsPlayed > FORCED_BUFFERING_BEATS_THRESHOLD) {
stopBuffering();
}
}
}
private boolean positionNotUpdating(long currentPositionInMillis) {
return currentPositionInMillis == previousPositionInMillis;
}
private void stopBuffering() {
bufferListener.onBufferComplete();
}
private void startBuffering() {
bufferListener.onBufferStart();
}
private boolean mediaPlayerIsUnavailable(NoPlayer player) {
try {
return !player.isPlaying();
} catch (IllegalStateException e) {
// The mediaplayer has not been initialized or has been released
return true;
}
}
public interface BufferListener {
void onBufferStart();
void onBufferComplete();
BufferListener NULL_IMPL = new BufferListener() {
@Override
public void onBufferStart() {
// do nothing
}
@Override
public void onBufferComplete() {
// do nothing
}
};
}
}
================================================
FILE: core/src/main/java/com/novoda/noplayer/internal/mediaplayer/DelayedActionExecutor.java
================================================
package com.novoda.noplayer.internal.mediaplayer;
import android.os.Handler;
import java.util.Iterator;
import java.util.Map;
class DelayedActionExecutor {
private final Handler handler;
private final Map