/* * Copyright 2008-2013, ETH Zürich, Samuel Welten, Michael Kuhn, Tobias Langner, * Sandro Affentranger, Lukas Bossard, Michael Grob, Rahul Jain, * Dominic Langenegger, Sonia Mayor Alonso, Roger Odermatt, Tobias Schlueter, * Yannick Stucki, Sebastian Wendland, Samuel Zehnder, Samuel Zihlmann, * Samuel Zweifel * * This file is part of Jukefox. * * Jukefox is free software: you can redistribute it and/or modify it under the * terms of the GNU General Public License as published by the Free Software * Foundation, either version 3 of the License, or any later version. Jukefox is * distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A * PARTICULAR PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along with * Jukefox. If not, see <http://www.gnu.org/licenses/>. */ package ch.ethz.dcg.jukefox.controller.player.mediaplayer; import java.io.IOException; import android.media.MediaPlayer; import android.media.MediaPlayer.OnCompletionListener; import android.media.MediaPlayer.OnErrorListener; import android.media.MediaPlayer.OnInfoListener; import ch.ethz.dcg.jukefox.commons.utils.AndroidUtils; import ch.ethz.dcg.jukefox.commons.utils.Log; import ch.ethz.dcg.jukefox.model.collection.BaseAlbum; import ch.ethz.dcg.jukefox.model.collection.BaseArtist; import ch.ethz.dcg.jukefox.model.collection.PlaylistSong; public class AndroidMediaPlayerWrapper implements IMediaPlayerWrapper, OnCompletionListener, OnErrorListener, OnInfoListener { public static final String TAG = AndroidMediaPlayerWrapper.class.getSimpleName(); private MediaPlayer mediaPlayer; private OnMediaPlayerEventListener listener; protected int seekTo = -1; protected boolean isPlaying; protected boolean isPaused; protected boolean isSongPrepared = false; protected PlaylistSong<BaseArtist, BaseAlbum> currentSong = null; public AndroidMediaPlayerWrapper() { mediaPlayer = new MediaPlayer(); isPlaying = false; isPaused = false; } public int getCurrentPosition() { if (!isPlaying && !isPaused || !isSongPrepared) { if (seekTo > 0) { return seekTo; } return 0; } try { int position = mediaPlayer.getCurrentPosition(); if (position < 0) { position = 0; } return position; } catch (Exception e) { Log.w(TAG, e); return 0; } } public int getDuration() { if (!isSongPrepared) { return 1000000; } return mediaPlayer.getDuration(); } public boolean isPlaying() { return mediaPlayer.isPlaying(); } public void onDestroy() { isPlaying = false; isPaused = false; mediaPlayer.release(); } public void pause() { mediaPlayer.pause(); isPlaying = false; isPaused = true; } public void play() { mediaPlayer.start(); if (mediaPlayer.isPlaying()) { isPlaying = true; isPaused = false; recallSeekToPosition(); } // Log.v(TAG, "Time after play: " + System.currentTimeMillis() + " " // + mp.isPlaying()); } public void reset() { mediaPlayer.reset(); isPlaying = false; isPaused = false; isSongPrepared = false; } public void seekTo(int position) { seekTo(mediaPlayer, position); } public void setSong(PlaylistSong<BaseArtist, BaseAlbum> song, String path) throws InvalidPathException { if (!AndroidUtils.isSdCardOk()) { throw new InvalidPathException(); } resetSeekToPosition(); mediaPlayer.reset(); try { mediaPlayer.setDataSource(path); } catch (IllegalArgumentException e) { Log.w(TAG, e); throw new InvalidPathException(); } catch (IllegalStateException e) { Log.w(TAG, e); throw new InvalidPathException(); } catch (IOException e) { Log.w(TAG, e); throw new InvalidPathException(); } try { // kuhnmi 8.8.2011: replaced "MPService" with TAG Log.i(TAG, "Preparing to play song at path: " + path); mediaPlayer.prepare(); } catch (Exception e) { Log.w("IOException during prepare.", e); listener.onError(this, 0, 0); return; } currentSong = song; isPlaying = false; isPaused = false; isSongPrepared = true; } public void stop() { mediaPlayer.stop(); isPlaying = false; isPaused = false; isSongPrepared = false; } public void setVolume(float left, float right) { mediaPlayer.setVolume(left, right); } public void setOnMediaPlayerEventListener(OnMediaPlayerEventListener listener) { this.listener = listener; mediaPlayer.setOnCompletionListener(this); mediaPlayer.setOnErrorListener(this); mediaPlayer.setOnInfoListener(this); } @Override public void onCompletion(MediaPlayer mp) { listener.onSongCompleted(this); } @Override public boolean onError(MediaPlayer mp, int what, int extra) { isSongPrepared = false; return listener.onError(this, what, extra); } @Override public boolean onInfo(MediaPlayer mp, int what, int extra) { return listener.onInfo(this, what, extra); } private void recallSeekToPosition() { Log.v(TAG, "recall seekto: " + seekTo); if (seekTo >= 0) { seekTo(seekTo); } resetSeekToPosition(); } private void resetSeekToPosition() { seekTo = -1; } protected void seekTo(MediaPlayer mp, int position) { if (!isPlaying && !isPaused || !isSongPrepared) { rememberSeekToPosition(position); return; } Log.v(TAG, "seekto 2 " + position); try { int duration = getDuration(); position = Math.min(duration, position); position = Math.max(0, position); mp.seekTo(position); } catch (Exception e) { Log.w(TAG, e); } } protected void rememberSeekToPosition(int position) { Log.v(TAG, "Remembering position: " + position); seekTo = position; } @Override public PlaylistSong<BaseArtist, BaseAlbum> getCurrentSong() { return currentSong; } @Override public boolean isSongReadyToPlay() { return isSongPrepared; } }