/* * 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.blackberry; 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 */ class MMAPIPlayer implements PlayerListener, Media{ private static int volume = -1; private boolean deleted; private int lastTime; Player nativePlayer; private static Vector playing; private InputStream sourceStream; private Runnable onComplete; private boolean disposeOnComplete = true; MMAPIPlayer(Player p) { this.nativePlayer = p; if(volume > -1){ setVolume(volume); }else{ setVolume(100); } } public static int getGlobalVolume(){ if(volume > -1) { return volume; } synchronized(MMAPIPlayer.class) { if(playing != null && playing.size() > 0) { MMAPIPlayer current = (MMAPIPlayer)playing.elementAt(0); VolumeControl volc = (VolumeControl) current.nativePlayer.getControl("VolumeControl"); if(volc != null) { return volc.getLevel(); } } } return -1; } public static void setGlobalVolume(int v){ volume = v; if(playing != null) { synchronized(MMAPIPlayer.class) { for(int iter = 0 ; iter < playing.size() ; iter++) { MMAPIPlayer current = (MMAPIPlayer)playing.elementAt(iter); VolumeControl volc = (VolumeControl) current.nativePlayer.getControl("VolumeControl"); if(volc != null) { volc.setLevel(v); } } } } } public int getVolume() { synchronized (MMAPIPlayer.class) { VolumeControl volc = (VolumeControl) nativePlayer.getControl("VolumeControl"); if (volc != null) { return volc.getLevel(); } } return -1; } public void setVolume(int v) { if (playing != null) { synchronized (MMAPIPlayer.class) { VolumeControl volc = (VolumeControl) nativePlayer.getControl("VolumeControl"); if (volc != null) { volc.setLevel(v); } } } } /** * @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 { synchronized(MMAPIPlayer.class) { playing.removeElement(this); } 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 { if(playing == null) { playing = new Vector(); } synchronized(MMAPIPlayer.class) { if(!playing.contains(this)){ playing.addElement(this); } } 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 boolean isPlaying() { return nativePlayer != null && nativePlayer.getState() == Player.STARTED; } public void setNativePlayerMode(boolean nativePlayer) { } public boolean isNativePlayerMode() { return false; } 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; } }