diff -r 2a9601315dfc -r 98ccebc37403 javauis/mmapi_qt/baseline/javasrc.mmf/com/nokia/microedition/media/ManagerImpl.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javauis/mmapi_qt/baseline/javasrc.mmf/com/nokia/microedition/media/ManagerImpl.java Fri May 14 15:47:24 2010 +0300 @@ -0,0 +1,675 @@ +/* +* Copyright (c) 2002 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: +* +*/ + +package com.nokia.microedition.media; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Vector; +import java.util.Enumeration; +import javax.microedition.media.protocol.DataSource; +import javax.microedition.media.TimeBase; +import javax.microedition.media.Player; +import javax.microedition.media.MediaException; + +//import com.symbian.lcdjava.lang.ObjectExtensions; +//import com.symbian.epoc.events.MIDEventServer; +//import com.symbian.midp.runtime.ToolkitInvoker; +//import com.symbian.midp.runtime.ToolkitObserver; + +import com.nokia.microedition.media.protocol.ProtocolFactory; +import com.nokia.microedition.media.tone.PlayToneImpl; +import com.nokia.microedition.volumekeys.ForegroundListener; +import com.nokia.mj.impl.rt.support.Finalizer; + +//To get the shutdown event from the midlet +import com.nokia.mj.impl.rt.support.ApplicationUtils; +import com.nokia.mj.impl.rt.support.ApplicationInfo; +import com.nokia.mj.impl.rt.support.ShutdownListener; + +/** + * ManagerImpl implements the functionality specified in + * javax.microedition.media.Manager class. + * This class is a singleton and instance can be got with getInstance method. + */ +public class ManagerImpl implements PlugIn +{ + // ManagerImpl native instance + private static int sManagerHandle; + + // CMMAEventSource + private static int iFunctionSourceHandle; + + // Static instance, can be got with getInstace method + private static ManagerImpl sManager; + + private final TimeBase iSystemTimeBase = new SystemTimeBase(); + + private final Vector iPlugIns = new Vector(); + private final ProtocolFactory iProtocolFactory = new ProtocolFactory(); + private final ForegroundListener iForegroundListener; + private Finalizer iFinalizer; + + Finalizer registerForFinalization() + { + return new Finalizer() + { + public void finalizeImpl() + { + doFinalize(); + } + }; + } + + // Play tone implementation + private PlayToneImpl iPlayToneImpl = new PlayToneImpl(); + + static + { + + try{ + com.nokia.mj.impl.rt.support.Jvm.loadSystemLibrary("javalegacyutils"); + } + catch(Exception e) + { + System.out.println("loading javalegacyutils failed....."); + } + System.out.println("inside static block of ManagerImpl.java"); + // This is called when class is loaded for the first time + sManager = new ManagerImpl(); + try + { + // Invoke external components + Setup.setup(iFunctionSourceHandle); + } + catch (OutOfMemoryError oome) + { + // External setup failed clean MMA native resources and throw oome + sManager.doFinalize(); + throw oome; + } + } + + /** + * This private constructor can be called only from staic block. + */ + private ManagerImpl() + { + // Will cause registeredFinalize() to be called when ObjectExtensions + // is finalized. + + + com.nokia.mj.impl.rt.support.Jvm.loadSystemLibrary("javamobilemedia"); + //ObjectExtensions.registerForFinalization(this); + iFinalizer = registerForFinalization(); + + // Event server contructor needs new String object, + // otherwise it don't work.. + + iFunctionSourceHandle = _createEventSource(); + if (iFunctionSourceHandle < NativeError.KErrNone) + { + throw new OutOfMemoryError("Symbian OS error: " + sEventSourceHandle); + } + + sManagerHandle = _createManager(iFunctionSourceHandle, + ApplicationInfo.getInstance().getSuiteUid().hashCode()); + if (sManagerHandle < NativeError.KErrNone) + { + throw new OutOfMemoryError(); + } + //Use ShutdownListener to get notification of exit and release the resource + //MMAPI UI 3.x work + + setShutdownListener(); + + // ManagerImpl is also a PlugIn that getAllSupportedContentTypes, + // getAllSupportedProtocols and createPlayer methods can be used + // through PlugIn interface. + iPlugIns.addElement(this); + + // support for device://tone and jts + iPlugIns.addElement( + new com.nokia.microedition.media.protocol.device.tone.Protocol()); + + // Create foreground listener which listens the state of the midlet + // This feature is a part of the media keys feature so it is flagged + System.out.println("before constructing ForegroundListener...."); + iForegroundListener = new ForegroundListener(iFunctionSourceHandle); + iForegroundListener.init(); + } + + /** + * Returns MMA event source handle + */ + public static int getEventSource() + { + return iFunctionSourceHandle; + } + /** + * Returns native handle to Manager + */ + public static int getHandle() + { + return sManagerHandle; + } + + /** + * Return ManagerImpl instance + */ + public static ManagerImpl getInstance() + { + return sManager; + } + + /** + * Adds new PlugIn to PlugIns array. + * @param aPlugIn New PlugIn. + */ + public void addPlugIn(PlugIn aPlugIn) + { + iPlugIns.addElement(aPlugIn); + } + + + + + /** + * This will be called when ObjectExtensions is finalized. + */ + synchronized final void doFinalize() + { + _dispose(iFunctionSourceHandle); + iFunctionSourceHandle = 0; + } + + /** + * This method is called in Toolkit's destroyNotify call. + * This will release convenient native resources. All native resource + * will be deleted in registeredFinalize() method. + */ + synchronized final void release() + { + _release(iFunctionSourceHandle); + } + + /** + * Create String array from Vector and remove String duplicates. + * @param aVector Vector containing String objects. + */ + private String[] createStringArray(Vector aVector) + { + // remove all duplicates from the vector + for (int i = 0; i < aVector.size(); i++) + { + String element = (String)aVector.elementAt(i); + for (int j = i + 1; j < aVector.size();) + { + if (element.equals((String)aVector.elementAt(j))) + { + aVector.removeElementAt(j); + } + else + { + j++; + } + } + } + + // Create new array for vector elements and copy elements + String[] s = new String[ aVector.size()]; + aVector.copyInto(s); + return s; + } + + /** + * Return the list of supported content types for the given protocol. + *

+ * See content types for the syntax + * of the content types returned. + * See protocol name for the syntax + * of the protocol used. + *

+ * For example, if the given protocol + * is "http", + * then the supported content types that can be played back + * with the http protocol will be returned. + *

+ * If null is passed in as the protocol, + * all the supported content types for this implementation + * will be returned. The returned array must be non-empty. + *

+ * If the given protocol is an invalid or + * unsupported protocol, then an empty array will be returned. + * + * @param aProtocol The input protocol for the supported content types. + * @return The list of supported content types for the given protocol. + */ + public String[] getAllSupportedContentTypes(String aProtocol) + { + if ((aProtocol != null) && (aProtocol.length() == 0)) + { + // No supported types for 0 length string. + return new String[ 0 ]; + } + Vector contentTypes = new Vector(); + + Enumeration plugIns = iPlugIns.elements(); + + // go through all plugins and get content types + while (plugIns.hasMoreElements()) + { + PlugIn plugIn = (PlugIn)plugIns.nextElement(); + String[] types = plugIn.getSupportedContentTypes(aProtocol); + + // Add all types to vector + for (int i = 0; i < types.length; i++) + { + contentTypes.addElement(types[ i ]); + } + } + return createStringArray(contentTypes); + } + + /** + * Return the list of supported protocols given the content + * type. The protocols are returned + * as strings which identify what locators can be used for creating + * Player's. + *

+ * See protocol name for the syntax + * of the protocols returned. + * See content types for the syntax + * of the content type used. + *

+ * For example, if the given content_type + * is "audio/x-wav", then the supported protocols + * that can be used to play back audio/x-wav + * will be returned. + *

+ * If null is passed in as the + * content_type, + * all the supported protocols for this implementation + * will be returned. The returned array must be non-empty. + *

+ * If the given content_type is an invalid or + * unsupported content type, then an empty array will be returned. + * + * @param aContentType The content type for the supported protocols. + * @return The list of supported protocols for the given content type. + */ + public String[] getAllSupportedProtocols(String aContentType) + { + String contentType = aContentType; + if ((contentType != null) && contentType.equals("")) + { + return new String[ 0 ]; + } + + Vector protocols = new Vector(); + Enumeration plugIns = iPlugIns.elements(); + while (plugIns.hasMoreElements()) + { + PlugIn plugIn = (PlugIn)plugIns.nextElement(); + String[] types = plugIn.getSupportedProtocols(aContentType); + for (int i = 0; i < types.length; i++) + { + protocols.addElement(types[ i ]); + } + } + return createStringArray(protocols); + } + + /** + * From PlugIn. Get MMA supported protocols. + */ + public String[] getSupportedProtocols(String aContentType) + { + String[] protocols = _getSupportedProtocols(iFunctionSourceHandle, + sManagerHandle, + aContentType); + NativeError.checkOOM(protocols); + return protocols; + } + + /** + * From PlugIn. Get MMA supported types. + */ + public String[] getSupportedContentTypes(String aProtocol) + { + String[] types = _getSupportedContentTypes(iFunctionSourceHandle, + sManagerHandle, + aProtocol); + NativeError.checkOOM(types); + return types; + } + + /** + * From PlugIn. + */ + public InternalPlayer createPlayer(DataSource aSource) + throws MediaException, IOException + { + InternalPlayer player = null; + if (aSource.getContentType() != null) + { + // Create player from content type + if (isValidContentType(aSource.getContentType())) + { + player = NativePlayerFactory.createPlayer(aSource.getContentType(), + aSource); + } + else + { + throw new MediaException( + "Content type not supported: " + aSource.getContentType()); + } + } + + if ((player == null) && + (aSource.getLocator() != null)) + { + // Create player from locator + player = NativePlayerFactory.createPlayer( + new Locator(aSource.getLocator()), + aSource); + } + + if (player == null) + { + // Could not create player from content-type or locator, + // try to create player from header data + player = NativePlayerFactory.createPlayer( + ((BufferDataSource)aSource).getHeader(), + aSource); + } + + return player; + } + + /** + * From PlugIn. Empty implemation. + */ + public void preparePlayer(InternalPlayer aPlayer) throws MediaException + { + + } + + /** + * This method calls preparePlayer to all PlugIns. + */ + private void pluginsPreparePlayer(InternalPlayer aPlayer) + throws MediaException + { + // Call preparePlayer to all plugins + Enumeration plugins = iPlugIns.elements(); + while (plugins.hasMoreElements()) + { + ((PlugIn)plugins.nextElement()).preparePlayer(aPlayer); + } + } + + /** + * Create a Player from an input locator. + * + * @param aLocator A locator string in URI syntax that describes + * the media content. + * @return A new Player. + * @exception IllegalArgumentException Thrown if locator + * is null. + * @exception MediaException Thrown if a Player cannot + * be created for the given locator. + * @exception IOException Thrown if there was a problem connecting + * with the source pointed to by the locator. + * @exception SecurityException Thrown if the caller does not + * have security permission to create the Player. + */ + public Player createPlayer(String aLocator) + throws IOException, MediaException + { + if (aLocator == null) + { + throw new IllegalArgumentException("Locator is null."); + } + InternalPlayer player = iProtocolFactory.createPlayer( + new Locator(aLocator)); + if (player == null) + { + throw new MediaException("Locator not supported: " + + aLocator); + } + pluginsPreparePlayer(player); + return player; + } + + /** + * Create a InternalPlayer for a DataSource. + */ + public InternalPlayer createInternalPlayer(DataSource aSource) + throws IOException, MediaException + { + // Throw IllegalArgumentException if source is null. + if (aSource == null) + { + throw new IllegalArgumentException("DataSource is null."); + } + aSource.connect(); // Ensure that external source is connected. + if (aSource.getStreams() == null || + aSource.getStreams().length == 0) + { + // There must be atleast one stream in the DataSource + throw new MediaException( + "There must be at least one stream in datasource"); + } + + BufferDataSource bdc = new BufferDataSource(aSource); + + InternalPlayer player = null; + Enumeration plugins = iPlugIns.elements(); + // Loop through all plugins, stop if player was created + while (plugins.hasMoreElements() && + (player == null)) + { + PlugIn tmp = (PlugIn)plugins.nextElement(); + player = tmp.createPlayer(bdc); + } + + if (player == null) + { + // MMA or plugins could not create player + bdc.disconnect(); + + throw new MediaException("Could not create player."); + } + + return player; + } + + /** + * Create a Player to play back media from an + * InputStream. + *

+ * The type argument + * specifies the content-type of the input media. If + * null is given, Manager will + * attempt to determine the type. However, since determining + * the media type is non-trivial for some media types, it + * may not be feasible in some cases. The + * Manager may throw a MediaException + * to indicate that. + * + * @param aStream The InputStream that delivers the + * input media. + * @param aType The ContentType of the media. + * @return A new Player. + * @exception IllegalArgumentException Thrown if stream + * is null. + * @exception MediaException Thrown if a Player cannot + * be created for the given stream and type. + * @exception IOException Thrown if there was a problem reading data + * from the InputStream. + * @exception SecurityException Thrown if the caller does not + * have security permission to create the Player. + */ + public Player createPlayer(InputStream aStream, String aType) + throws IOException, MediaException + { + if (aStream == null) + { + throw new IllegalArgumentException("InputStream is null."); + } + + InputStreamSourceStream sourceStream = + new InputStreamSourceStream(aStream); + + // Create data source without locator. + DataSource dataSource = new InputStreamDataSource(sourceStream, + aType); + InternalPlayer player = createInternalPlayer(dataSource); + + if (player != null) + { + // Call preparePlayer to all plugins + pluginsPreparePlayer(player); + } + + return player; + } + + /** + * Play back a tone as specified by a note and its duration. + * A note is given in the range of 0 to 127 inclusive. The frequency + * of the note can be calculated from the following formula: + *

+     *     SEMITONE_CONST = 17.31234049066755 = 1/(ln(2^(1/12)))
+     *     note = ln(freq/8.176)*SEMITONE_CONST
+     *     The musical note A = MIDI note 69 (0x45) = 440 Hz.
+     * 
+ * This call is a non-blocking call. Notice that this method may + * utilize CPU resources significantly on devices that don't + * have hardware support for tone generation. + * + * @param aNote Defines the tone of the note as specified by the + * above formula. + * @param aDuration The duration of the tone in milli-seconds. + * Duration must be positive. + * @param aVolume Audio volume range from 0 to 100. 100 represents + * the maximum + * volume at the current hardware level. Setting the volume to a + * value less + * than 0 will set the volume to 0. Setting the volume to greater than + * 100 will set the volume to 100. + * + * @exception IllegalArgumentException Thrown if the given note or + * duration is out of range. + * @exception MediaException Thrown if the tone cannot be played + * due to a device-related problem. + */ + public void playTone(int aNote, int aDuration, int aVolume) + throws MediaException + { + iPlayToneImpl.playTone(aNote, aDuration, aVolume); + } + + /** + * Get the time-base object for the system. + * @return The system time base. + */ + public TimeBase getSystemTimeBase() + { + return iSystemTimeBase; + } + + public boolean isValidContentType(String contentType) + { + for (int i=0; i < contentType.length(); i++) + { + if ((contentType.charAt(i) >= 0 && contentType.charAt(i) <= 31) || contentType.charAt(i) == 127) + return false; + } + return true; + } + + + +/** + * Registers for shutdown listener + */ + private void setShutdownListener() + { + // Get the instance of ApplicationUtils. + ApplicationUtils appUtils = ApplicationUtils.getInstance(); + + // add the listener + appUtils.addShutdownListener(new ShutdownListener() + { + public void shuttingDown() + { + try + { + System.out.println("Shutting down.........."); + // Do cleaning... + release(); + } + catch (Exception ex) + { + // catch the exception and call dispose + } + + if (iFunctionSourceHandle != 0) + { + _dispose(iFunctionSourceHandle); + iFunctionSourceHandle = 0; + } + } + + }); + } // end setShutdownListener() + + +// MMAPI UI 3.x req +/** + * get midlet state + */ + + public boolean isForground() + { + return iForegroundListener.isForeground(); + } + + + private native int _createManager(int aEventSourceHandle, + int aMIDletSuiteID); + private native int _createEventSource(); + private native void _dispose(int aEventSourceHandle); + + /** + * Releases native resources. + * @param aEventSourceHandle Handle to native CMMAEventSource instance. + */ + private native void _release(int aFunctionSourceHandle); + + private static native String[] _getSupportedContentTypes(int aFunctionSourceHandle, + int aManagerHandle, + String aContentType); + + private static native String[] _getSupportedProtocols(int aFunctionSourceHandle, + int aManagerHandle, + String aProtocol); +} + +// End of File