Added Android code
[wl-app.git] / Android / folioreader / src / main / java / com / folioreader / ui / folio / mediaoverlay / MediaController.java
diff --git a/Android/folioreader/src/main/java/com/folioreader/ui/folio/mediaoverlay/MediaController.java b/Android/folioreader/src/main/java/com/folioreader/ui/folio/mediaoverlay/MediaController.java
new file mode 100755 (executable)
index 0000000..f197530
--- /dev/null
@@ -0,0 +1,243 @@
+package com.folioreader.ui.folio.mediaoverlay;
+
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.media.MediaPlayer;
+import android.os.Build;
+import android.os.Handler;
+import android.speech.tts.TextToSpeech;
+import android.support.v7.app.AppCompatActivity;
+import android.util.Log;
+
+import com.folioreader.Constants;
+import com.folioreader.model.event.MediaOverlayPlayPauseEvent;
+import com.folioreader.model.event.MediaOverlaySpeedEvent;
+import com.folioreader.model.media_overlay.OverlayItems;
+import com.folioreader.util.UiUtil;
+
+import org.readium.r2_streamer.model.publication.SMIL.Clip;
+import org.readium.r2_streamer.model.publication.SMIL.MediaOverlays;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+
+/**
+ * @author gautam chibde on 21/6/17.
+ */
+
+public class MediaController {
+
+    private static final String TAG = MediaController.class.getSimpleName();
+
+    public enum MediaType {
+        TTS, SMIL,
+    }
+
+    private MediaType mediaType;
+    private MediaControllerCallbacks callbacks;
+    private Context context;
+
+    //**********************************//
+    //          MEDIA OVERLAY           //
+    //**********************************//
+    private MediaOverlays mediaOverlays;
+    private List<OverlayItems> mediaItems = new ArrayList<>();
+    private int mediaItemPosition = 0;
+    private MediaPlayer mediaPlayer;
+
+    private Clip currentClip;
+
+    private boolean isMediaPlayerReady;
+    private Handler mediaHandler;
+
+    //*********************************//
+    //              TTS                //
+    //*********************************//
+    private TextToSpeech mTextToSpeech;
+    private boolean mIsSpeaking = false;
+
+    public MediaController(Context context, MediaType mediaType, MediaControllerCallbacks callbacks) {
+        this.mediaType = mediaType;
+        this.callbacks = callbacks;
+        this.context = context;
+    }
+
+    private Runnable mHighlightTask = new Runnable() {
+        @Override
+        public void run() {
+            int currentPosition = mediaPlayer.getCurrentPosition();
+            if (mediaPlayer.getDuration() != currentPosition) {
+                if (mediaItemPosition < mediaItems.size()) {
+                    int end = (int) currentClip.end * 1000;
+                    if (currentPosition > end) {
+                        mediaItemPosition++;
+                        currentClip = mediaOverlays.clip(mediaItems.get(mediaItemPosition).getId());
+                        if (currentClip != null) {
+                            callbacks.highLightText(mediaItems.get(mediaItemPosition).getId());
+                        } else {
+                            mediaItemPosition++;
+                        }
+                    }
+                    mediaHandler.postDelayed(mHighlightTask, 10);
+                } else {
+                    mediaHandler.removeCallbacks(mHighlightTask);
+                }
+            }
+        }
+    };
+
+    public void resetMediaPosition() {
+        mediaItemPosition = 0;
+    }
+
+    public void setSMILItems(List<OverlayItems> overlayItems) {
+        this.mediaItems = overlayItems;
+    }
+
+    public void next() {
+        mediaItemPosition++;
+    }
+
+    public void setTextToSpeech(final Context context) {
+        mTextToSpeech = new TextToSpeech(context, new TextToSpeech.OnInitListener() {
+            @Override
+            public void onInit(int status) {
+                if (status != TextToSpeech.ERROR) {
+                    mTextToSpeech.setLanguage(Locale.getDefault());
+                    mTextToSpeech.setSpeechRate(0.70f);
+                }
+
+                mTextToSpeech.setOnUtteranceCompletedListener(
+                        new TextToSpeech.OnUtteranceCompletedListener() {
+                            @Override
+                            public void onUtteranceCompleted(String utteranceId) {
+                                ((AppCompatActivity) context).runOnUiThread(new Runnable() {
+                                    @Override
+                                    public void run() {
+                                        if (mIsSpeaking) {
+                                            callbacks.highLightTTS();
+                                        }
+                                    }
+                                });
+                            }
+                        });
+            }
+        });
+    }
+
+    public void setUpMediaPlayer(MediaOverlays mediaOverlays, String path, String mBookTitle) {
+        this.mediaOverlays = mediaOverlays;
+        mediaHandler = new Handler();
+        try {
+            mediaItemPosition = 0;
+            String uri = Constants.LOCALHOST + mBookTitle + "/" + path;
+            mediaPlayer = new MediaPlayer();
+            mediaPlayer.setDataSource(uri);
+            mediaPlayer.prepare();
+            isMediaPlayerReady = true;
+        } catch (IOException e) {
+            Log.d(TAG, e.getMessage());
+        }
+    }
+
+    public void setSpeed(MediaOverlaySpeedEvent.Speed speed) {
+        switch (speed) {
+            case HALF:
+                setPlaybackSpeed(0.5f);
+                break;
+            case ONE:
+                setPlaybackSpeed(1.0f);
+                break;
+            case ONE_HALF:
+                setPlaybackSpeed(1.5f);
+                break;
+            case TWO:
+                setPlaybackSpeed(2.0f);
+                break;
+        }
+    }
+
+    @TargetApi(Build.VERSION_CODES.M)
+    private void setPlaybackSpeed(float speed) {
+        if (mediaType == MediaType.SMIL) {
+            if (mediaPlayer != null && mediaPlayer.isPlaying()) {
+                mediaPlayer.setPlaybackParams(mediaPlayer.getPlaybackParams().setSpeed(speed));
+            }
+        } else {
+            mTextToSpeech.setSpeechRate(speed);
+        }
+    }
+
+    public void stateChanged(MediaOverlayPlayPauseEvent event) {
+        if (event.isStateChanged()) {
+            if (mediaPlayer != null) {
+                mediaPlayer.pause();
+            }
+            if (mTextToSpeech != null && mTextToSpeech.isSpeaking()) {
+                mTextToSpeech.stop();
+            }
+        } else {
+            if (event.isPlay()) {
+                UiUtil.keepScreenAwake(true, context);
+            } else {
+                UiUtil.keepScreenAwake(false, context);
+            }
+            if (mediaType == MediaType.SMIL) {
+                playSMIL();
+            } else {
+                if (mTextToSpeech.isSpeaking()) {
+                    mTextToSpeech.stop();
+                    mIsSpeaking = false;
+                    callbacks.resetCurrentIndex();
+                } else {
+                    mIsSpeaking = true;
+                    callbacks.highLightTTS();
+                }
+            }
+        }
+    }
+
+    private void playSMIL() {
+        if (mediaPlayer != null && isMediaPlayerReady) {
+            if (mediaPlayer.isPlaying()) {
+                mediaPlayer.pause();
+            } else {
+                currentClip = mediaOverlays.clip(mediaItems.get(mediaItemPosition).getId());
+                if (currentClip != null) {
+                    mediaPlayer.start();
+                    mediaHandler.post(mHighlightTask);
+                } else {
+                    mediaItemPosition++;
+                    mediaPlayer.start();
+                    mediaHandler.post(mHighlightTask);
+                }
+            }
+        }
+    }
+
+    public void speakAudio(String sentence) {
+        if (mediaType == MediaType.TTS) {
+            HashMap<String, String> params = new HashMap<>();
+            params.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID, "stringId");
+            mTextToSpeech.speak(sentence, TextToSpeech.QUEUE_FLUSH, params);
+        }
+    }
+
+    public void stop() {
+        if (mTextToSpeech != null) {
+            if (mTextToSpeech.isSpeaking()) {
+                mTextToSpeech.stop();
+            }
+            mTextToSpeech.shutdown();
+        }
+        if (mediaPlayer != null && mediaPlayer.isPlaying()) {
+            mediaPlayer.stop();
+            mediaPlayer.release();
+            mediaPlayer = null;
+            mediaHandler.removeCallbacks(mHighlightTask);
+        }
+    }
+}