/*
* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores
* CA 94065 USA or visit www.oracle.com if you need additional information or
* have any questions.
*/
package com.codename1.impl.midp;
import com.codename1.media.Media;
import com.codename1.ui.Component;
import com.codename1.ui.Image;
import java.io.IOException;
import java.io.InputStream;
import java.util.Hashtable;
import java.util.Vector;
import javax.microedition.media.Manager;
import javax.microedition.media.MediaException;
import javax.microedition.media.Player;
import javax.microedition.media.PlayerListener;
import javax.microedition.media.control.VolumeControl;
/**
* Simple abstraction to the player API in MMAPI used by the MIDP and Blackberry
* ports. This class is public only because the blackberry port relies on it and
* is in a different package, it is not meant for general use and is an
* implementation detail subject to change!
*
* this class might be changed at any moment it is an implementation detail
*
* @author Shai Almog
*/
public class MMAPIPlayer implements PlayerListener, Media {
private static int volume = -1;
private boolean deleted;
private int lastTime;
Player nativePlayer;
private InputStream sourceStream;
private Runnable onComplete;
private boolean disposeOnComplete = true;
private MMAPIPlayer(Player p) {
this.nativePlayer = p;
if (volume > -1) {
setVolume(volume);
} else {
setVolume(100);
}
}
public int getVolume() {
if (volume > -1) {
return volume;
}
try {
VolumeControl volc = (VolumeControl) nativePlayer.getControl("VolumeControl");
if (volc != null) {
return volc.getLevel();
}
} catch (Exception e) {
}
return -1;
}
public void setVolume(int v) {
volume = v;
try {
VolumeControl volc = (VolumeControl) nativePlayer.getControl("VolumeControl");
if (volc != null) {
volc.setLevel(v);
}
} catch (Exception e) {
}
}
/**
* @inheritDoc
*/
public static MMAPIPlayer createPlayer(String uri, Runnable onCompletion) throws IOException {
try {
Player p = Manager.createPlayer((String) uri);
p.realize();
MMAPIPlayer m = new MMAPIPlayer(p);
m.bindPlayerCleanupOnComplete(p, null, onCompletion);
return m;
} catch (MediaException ex) {
ex.printStackTrace();
throw new IOException(ex.toString());
}
}
public static MMAPIPlayer createPlayer(InputStream stream, String mimeType, Runnable onCompletion) throws IOException {
try {
Player p = Manager.createPlayer(stream, mimeType);
p.realize();
MMAPIPlayer m = new MMAPIPlayer(p);
m.bindPlayerCleanupOnComplete(p, stream, onCompletion);
return m;
} catch (MediaException ex) {
if ("audio/mpeg".equals(mimeType)) {
return createPlayer(stream, "audio/mp3", onCompletion);
}
ex.printStackTrace();
throw new IOException(ex.toString());
}
}
private void bindPlayerCleanupOnComplete(final Player p, final InputStream i, final Runnable onComplete) {
if (volume > -1) {
VolumeControl v = (VolumeControl) p.getControl("VolumeControl");
if (v != null) {
v.setLevel(volume);
}
}
sourceStream = i;
this.onComplete = onComplete;
p.addPlayerListener(this);
}
public void cleanup() {
if (deleted) {
return;
}
deleted = true;
try {
try {
nativePlayer.stop();
} catch (Throwable t) {
}
nativePlayer.close();
nativePlayer = null;
} catch (Throwable t) {
}
}
public void prepare() {
if (deleted) {
return;
}
try {
nativePlayer.prefetch();
} catch (MediaException ex) {
ex.printStackTrace();
throw new RuntimeException(ex.toString());
}
}
public void play() {
if (deleted) {
return;
}
try {
nativePlayer.start();
} catch (MediaException ex) {
ex.printStackTrace();
throw new RuntimeException(ex.toString());
}
}
public void pause() {
if (deleted) {
return;
}
try {
if (nativePlayer != null) {
nativePlayer.stop();
}
} catch (MediaException ex) {
ex.printStackTrace();
throw new RuntimeException(ex.toString());
}
}
public int getTime() {
try {
// this allows us to get the time even on a closed player
if (nativePlayer == null || deleted) {
return lastTime;
}
lastTime = (int) (nativePlayer.getMediaTime() / 1000);
return lastTime;
} catch (Throwable t) {
return lastTime;
}
}
public void setTime(int time) {
if (deleted) {
return;
}
try {
nativePlayer.setMediaTime(time * 1000);
} catch (MediaException ex) {
ex.printStackTrace();
}
}
public int getDuration() {
if (nativePlayer == null || deleted) {
return 1000;
}
return (int) (nativePlayer.getDuration() / 1000);
}
public void playerUpdate(Player player, String event, Object eventData) {
if (deleted) {
return;
}
if (PlayerListener.ERROR.equals(event)) {
lastTime = (int) (nativePlayer.getMediaTime() / 1000);
cleanup();
}
if (PlayerListener.END_OF_MEDIA.equals(event)) {
lastTime = (int) (nativePlayer.getMediaTime() / 1000);
if (disposeOnComplete) {
cleanup();
if (sourceStream != null) {
try {
sourceStream.close();
} catch (Throwable t) {
}
}
}
if (onComplete != null) {
onComplete.run();
}
}
}
public Component getVideoComponent() {
return null;
}
public boolean isVideo() {
return false;
}
public boolean isFullScreen() {
return false;
}
public void setFullScreen(boolean fullScreen) {
}
public void setNativePlayerMode(boolean nativePlayer) {
}
public boolean isNativePlayerMode() {
return false;
}
public boolean isPlaying() {
return nativePlayer.getState() == Player.STARTED;
}
public void setVariable(String key, Object value) {
if (key != null) {
if (key.equals("disposeOnComplete")) {
if (value != null) {
String v = value.toString();
disposeOnComplete = v.equalsIgnoreCase("true");
}
}
}
}
public Object getVariable(String key) {
if (key != null) {
if (key.equals("disposeOnComplete")) {
return "" + disposeOnComplete;
}
}
return null;
}
}