/** * The MIT License (MIT) * Copyright (c) 2014 David Carver * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS * OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ package us.nineworlds.serenity.ui.video.player; import javax.inject.Inject; import us.nineworlds.serenity.injection.BaseInjector; import android.app.Activity; import android.content.SharedPreferences; import android.media.MediaPlayer; import android.os.Handler; import android.util.Log; import android.view.KeyEvent; import android.view.View; public class VideoPlayerKeyCodeHandler extends BaseInjector { @Inject protected SharedPreferences preferences; protected MediaPlayer mediaPlayer; protected MediaController mediaController; protected Handler progressReportinHandler; protected Runnable progressRunnable; protected View timeOfDayView; protected Activity videoPlayerActivity; protected int osdDelayTime; public VideoPlayerKeyCodeHandler(MediaPlayer mediaPlayer, MediaController mediaController, int osdDelayTime, Handler progressReportingHandler, Runnable progressRunnable, View timeOfDay, Activity videoPlayerActivity) { this.mediaPlayer = mediaPlayer; this.mediaController = mediaController; this.osdDelayTime = osdDelayTime; this.progressReportinHandler = progressReportingHandler; this.progressRunnable = progressRunnable; this.videoPlayerActivity = videoPlayerActivity; this.timeOfDayView = timeOfDay; } public boolean onKeyDown(int keyCode, KeyEvent event, boolean isMediaPlayerStateValid) { // All actions from here on require media to be in a valid state if (!isMediaPlayerStateValid) { return false; } final String nextPrevBehavior = preferences.getString( "next_prev_behavior", "queue"); if (isKeyCodeInfo(keyCode)) { if (mediaController.isShowing()) { mediaController.hide(); } else { mediaController.show(osdDelayTime); } return true; } if (isKeyCodePauseResume(keyCode)) { if (mediaPlayer.isPlaying()) { mediaPlayer.pause(); mediaController.show(osdDelayTime); progressReportinHandler.removeCallbacks(progressRunnable); } else { mediaPlayer.start(); mediaController.hide(); progressReportinHandler.postDelayed(progressRunnable, 5000); } return true; } if (keyCode == KeyEvent.KEYCODE_T) { final boolean showTimeOfDay = !preferences.getBoolean( "showTimeOfDay", false); timeOfDayView.setVisibility(showTimeOfDay ? View.VISIBLE : View.GONE); preferences.edit().putBoolean("showTimeOfDay", showTimeOfDay) .apply(); return true; } if (keyCode == KeyEvent.KEYCODE_MEDIA_NEXT) { if (nextPrevBehavior.equals("queue")) { mediaController.hide(); if (mediaPlayer.isPlaying()) { mediaPlayer.stop(); } videoPlayerActivity.finish(); return true; } final int skipTo; final int currentPosition = mediaPlayer.getCurrentPosition(); final int duration = mediaPlayer.getDuration(); if (nextPrevBehavior.endsWith("%")) { final Integer percent = Integer.valueOf(nextPrevBehavior .substring(0, nextPrevBehavior.length() - 1)); skipTo = currentPosition + duration * percent / 100; } else { skipTo = currentPosition + Integer.valueOf(nextPrevBehavior); } skipToOffset(skipTo); return true; } try { final int currentPosition = mediaPlayer.getCurrentPosition(); final int duration = mediaPlayer.getDuration(); if (keyCode == KeyEvent.KEYCODE_MEDIA_PREVIOUS && !nextPrevBehavior.equals("queue")) { final int skipTo; if (nextPrevBehavior.endsWith("%")) { final Integer percent = Integer.valueOf(nextPrevBehavior .substring(0, nextPrevBehavior.length() - 1)); skipTo = currentPosition - duration * percent / 100; } else { skipTo = currentPosition - Integer.valueOf(nextPrevBehavior); } skipToOffset(skipTo); return true; } if (isKeyCodeSkipForward(keyCode)) { skipToOffset(currentPosition + Integer.valueOf(preferences.getString( "skip_forward_time", "30000"))); return true; } if (isKeyCodeSkipBack(keyCode)) { skipToOffset(currentPosition - Integer.valueOf(preferences.getString( "skip_backward_time", "10000"))); return true; } if (isKeyCodeStop(keyCode)) { if (mediaPlayer.isPlaying()) { mediaPlayer.pause(); if (!mediaController.isShowing()) { mediaController.show(osdDelayTime); } } return true; } if (isSkipByPercentage(keyCode)) { return true; } } catch (IllegalStateException e) { Log.e(this.getClass().getName(), "Media Player is in an illegalstate.", e); } return false; } protected boolean isKeyCodeStop(int keyCode) { return keyCode == KeyEvent.KEYCODE_MEDIA_STOP || keyCode == KeyEvent.KEYCODE_S; } protected boolean isKeyCodeSkipBack(int keyCode) { return keyCode == KeyEvent.KEYCODE_MEDIA_REWIND || keyCode == KeyEvent.KEYCODE_R || keyCode == KeyEvent.KEYCODE_BUTTON_L1 || keyCode == KeyEvent.KEYCODE_BUTTON_L2; } protected boolean isKeyCodeSkipForward(int keyCode) { return keyCode == KeyEvent.KEYCODE_MEDIA_FAST_FORWARD || keyCode == KeyEvent.KEYCODE_F || keyCode == KeyEvent.KEYCODE_BUTTON_R1 || keyCode == KeyEvent.KEYCODE_BUTTON_R2; } protected boolean isKeyCodePauseResume(int keyCode) { return keyCode == KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE || keyCode == KeyEvent.KEYCODE_MEDIA_PAUSE || keyCode == KeyEvent.KEYCODE_P || keyCode == KeyEvent.KEYCODE_SPACE || keyCode == KeyEvent.KEYCODE_BUTTON_A || keyCode == KeyEvent.KEYCODE_MEDIA_PLAY; } protected boolean isKeyCodeInfo(int keyCode) { return keyCode == KeyEvent.KEYCODE_INFO || keyCode == KeyEvent.KEYCODE_I || keyCode == KeyEvent.KEYCODE_MENU || keyCode == KeyEvent.KEYCODE_BUTTON_Y; } protected boolean isSkipByPercentage(int keyCode) { int duration = mediaPlayer.getDuration(); if (keyCode == KeyEvent.KEYCODE_1) { skipByPercentage(duration, 0.10f); return true; } if (keyCode == KeyEvent.KEYCODE_2) { skipByPercentage(duration, 0.20f); return true; } if (keyCode == KeyEvent.KEYCODE_3) { skipByPercentage(duration, 0.30f); return true; } if (keyCode == KeyEvent.KEYCODE_4) { skipByPercentage(duration, 0.40f); return true; } if (keyCode == KeyEvent.KEYCODE_5) { skipByPercentage(duration, 0.50f); return true; } if (keyCode == KeyEvent.KEYCODE_6) { skipByPercentage(duration, 0.60f); return true; } if (keyCode == KeyEvent.KEYCODE_7) { skipByPercentage(duration, 0.70f); return true; } if (keyCode == KeyEvent.KEYCODE_8) { skipByPercentage(duration, 0.80f); return true; } if (keyCode == KeyEvent.KEYCODE_9) { skipByPercentage(duration, 0.90f); return true; } if (keyCode == KeyEvent.KEYCODE_0) { skipToPercentage(0); return true; } return false; } protected void skipByPercentage(int duration, float percentage) { int newPos = Math.round(duration * percentage); skipToPercentage(newPos); } protected void skipToPercentage(int newPos) { mediaPlayer.seekTo(newPos); if (!mediaController.isShowing()) { mediaController.show(osdDelayTime); } } protected void skipToOffset(int skipOffset) { int duration = mediaPlayer.getDuration(); if (skipOffset > duration) { skipOffset = duration - 1; } else if (skipOffset < 0) { skipOffset = 0; } if (!mediaController.isShowing()) { mediaController.show(osdDelayTime); } mediaPlayer.seekTo(skipOffset); } }