<commit_before>package es.flakiness.hiccup.play;

import android.content.Context;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;

import java.io.IOException;

import rx.Observable;
import rx.Subscription;
import rx.functions.Action1;
import rx.subjects.PublishSubject;

public class Player {
    private final String TAG = getClass().getSimpleName();

    private final Context context;
    private final MediaPlayer player;
    private final Uri uri;
    private boolean startRequested;
    private PlayerState state;
    private Subscription gestureSubscription;
    private PublishSubject<PlayerState> stateSubject = PublishSubject.create();
    private PublishSubject<PlayerProgress> progressSubject = PublishSubject.create();
    private Seeker seeker;

    private static int UPDATE_INTERVAL = 1000;
    private Handler progressHandler;
    private Runnable postProgress = new Runnable() {
        @Override
        public void run() {
            notifyProgress();
            if (progressHandler != null) {
                int delay = UPDATE_INTERVAL - player.getCurrentPosition() % UPDATE_INTERVAL;
                progressHandler.postDelayed(postProgress, delay);
            }
        }
    };


    public Player(Context context, Uri uri) throws IOException {
        this.context = context;
        this.uri = uri;
        this.player = new MediaPlayer();

        // This makes sure that |player| stay STARTED state internally.
        this.player.setLooping(true);

        this.player.setDataSource(context, uri);
        this.player.prepareAsync();
        this.player.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
            @Override
            public void onPrepared(MediaPlayer mediaPlayer) {
                Player.this.onPlayerPrepared();
            }
        });

        this.player.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
            @Override
            public void onCompletion(MediaPlayer mediaPlayer) {
                onPlayerCompleted();
            }
        });

        this.player.setOnSeekCompleteListener(new MediaPlayer.OnSeekCompleteListener() {
            @Override
            public void onSeekComplete(MediaPlayer mediaPlayer) {
                onPlayerSeekComplete();
            }
        });
        setState(PlayerState.PREPARING);

        this.progressHandler = new Handler(Looper.myLooper());
        this.progressHandler.postDelayed(postProgress, 0);
    }

    private void onPlayerSeekComplete() {
        if (state != PlayerState.SEEKING) {
            // This does happen. MediaPlayer calls onPlayerSeekComplete() even when
            // the user doesn't request seekTo().
            return;
        }

        setState(PlayerState.SEEKED);
        startIfNeededAndPossible();
        notifyProgress();
    }

    private void onPlayerCompleted() {
        this.pause();
        setState(PlayerState.COMPLETED);
    }

    public void onPlayerPrepared() {
        setState(PlayerState.PREPARED);
        startIfNeededAndPossible();
    }

    public void start() {
        startRequested = true;
        startIfNeededAndPossible();
    }

    private void startIfNeededAndPossible() {
       if (startRequested && state.isReadyToStart()) {
           player.start();
           startRequested = false;
           setState(PlayerState.PLAYING);
       }
    }

    public void toggle() {
        if (state == PlayerState.PLAYING)
            pause();
        else
            start();
    }

    private void pause() {
        if (state.isPauseable()) {<commit_msg>Fix #4.<commit_after>package es.flakiness.hiccup.play;

import android.content.Context;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;

import java.io.IOException;

import rx.Observable;
import rx.Subscription;
import rx.functions.Action1;
import rx.subjects.PublishSubject;

public class Player {
    private final String TAG = getClass().getSimpleName();

    private final Context context;
    private final MediaPlayer player;
    private final Uri uri;
    private boolean startRequested;
    private PlayerState state;
    private Subscription gestureSubscription;
    private PublishSubject<PlayerState> stateSubject = PublishSubject.create();
    private PublishSubject<PlayerProgress> progressSubject = PublishSubject.create();
    private Seeker seeker;

    private static int UPDATE_INTERVAL = 1000;
    private Handler progressHandler;
    private Runnable postProgress = new Runnable() {
        @Override
        public void run() {
            notifyProgress();
            if (progressHandler != null) {
                int delay = UPDATE_INTERVAL - player.getCurrentPosition() % UPDATE_INTERVAL;
                progressHandler.postDelayed(postProgress, delay);
            }
        }
    };


    public Player(Context context, Uri uri) throws IOException {
        this.context = context;
        this.uri = uri;
        this.player = new MediaPlayer();

        this.player.setDataSource(context, uri);
        this.player.prepareAsync();
        this.player.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
            @Override
            public void onPrepared(MediaPlayer mediaPlayer) {
                Player.this.onPlayerPrepared();
            }
        });

        this.player.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
            @Override
            public void onCompletion(MediaPlayer mediaPlayer) {
                onPlayerCompleted();
            }
        });

        this.player.setOnSeekCompleteListener(new MediaPlayer.OnSeekCompleteListener() {
            @Override
            public void onSeekComplete(MediaPlayer mediaPlayer) {
                onPlayerSeekComplete();
            }
        });
        setState(PlayerState.PREPARING);

        this.progressHandler = new Handler(Looper.myLooper());
        this.progressHandler.postDelayed(postProgress, 0);
    }

    private void onPlayerSeekComplete() {
        if (state != PlayerState.SEEKING) {
            // This does happen. MediaPlayer calls onPlayerSeekComplete() even when
            // the user doesn't request seekTo().
            return;
        }

        setState(PlayerState.SEEKED);
        startIfNeededAndPossible();
        notifyProgress();
    }

    private void onPlayerCompleted() {
        player.seekTo(player.getDuration() - 1);
        pause();
    }

    public void onPlayerPrepared() {
        setState(PlayerState.PREPARED);
        startIfNeededAndPossible();
    }

    public void start() {
        startRequested = true;
        startIfNeededAndPossible();
    }

    private void startIfNeededAndPossible() {
       if (startRequested && state.isReadyToStart()) {
           player.start();
           startRequested = false;
           setState(PlayerState.PLAYING);
       }
    }

    public void toggle() {
        if (state == PlayerState.PLAYING)
            pause();
        else
            start();
    }

    private void pause() {
        if (state.isPauseable()) {
{'fraction_non_alphanumeric': 0.08950230029276453, 'fraction_numerical': 0.0019517635577861424, 'mean_word_length': 2.3823668081093823, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3430906', 'n_tokens_mistral': 1906, 'n_tokens_neox': 1822, 'n_words': 414}