FileDocCategorySizeDatePackage
Manager.javaAPI DocJ2ME MIDP 2.012282Thu Nov 07 12:02:30 GMT 2002javax.microedition.media

Manager.java

/*
 * @(#)Manager.java	1.29 02/07/31 @(#)
 *
 * Copyright (c) 2002 Sun Microsystems, Inc.  All rights reserved.
 * PROPRIETARY/CONFIDENTIAL
 * Use is subject to license terms.
 */

package javax.microedition.media;

import java.io.IOException;
import java.io.InputStream;
import java.util.Hashtable;
import com.sun.mmedia.BasicPlayer;
import com.sun.mmedia.TonePlayer;
import com.sun.mmedia.WavPlayer;


/**
 * <code>Manager</code> is the access point for obtaining
 * system dependent resources such as <code>Players</code>
 * for multimedia processing.
 * <p>
 *
 * A <a href="Player.html"<code>Player</code></a> 
 * is an object used to
 * control and render media that
 * is specific to the 
 * <a href="#content-type">content type</a> 
 * of the data.
 * <p>
 * <code>Manager</code> provides access to an implementation specific
 * mechanism for constructing <code>Players</code>.
 * <p>
 * For convenience, <code>Manager</code> also provides a simplified 
 * method to generate simple tones.
 *
 * <h2>Simple Tone Generation</h2>
 * 
 * <blockquote>
 * The 
 * <a href="#playTone(int, int, int)">
 * <code>playTone</code></a>
 * function is defined to generate
 * tones.  Given the note and duration, the function will
 * produce the specified tone.
 * </blockquote>
 *
 * <h2>Creating Players</h2>
 * <blockquote>
 *
 * <code>Manager</code> provides two methods to create a 
 * <code>Player</code> for playing back media:
 * <ul>
 * <li> Create from a media locator.
 * <li> Create from an <code>InputStream</code>.
 * </ul>
 * The <code>Player</code> returned can be used to control the
 * presentation of the media.
 * </blockquote>
 * <p>
 *
 * <a name="content-type"></a>
 * <h2>Content Types</h2>
 * <blockquote>
 * Content types identify the type of media data.  They are 
 * defined to be the registered MIME types 
 * (<a href=
 * "http://www.iana.org/assignments/media-types/">
 * http://www.iana.org/assignments/media-types/</a>); 
 * plus
 * some user-defined types that generally follow the MIME syntax
 * (<a href="ftp://ftp.isi.edu/in-notes/rfc2045.txt">RFC 2045</a>,  
 * <a href="ftp://ftp.isi.edu/in-notes/rfc2046.txt">RFC 2046</a>).
 * <p>
 * For example, here are a few common content types:
 * <ol>
 * <li>Wave audio files: <code>audio/x-wav</code>
 * <li>AU audio files: <code>audio/basic</code>
 * <li>MP3 audio files: <code>audio/mpeg</code>
 * <li>MIDI files: <code>audio/midi</code>
 * <li>Tone sequences: <code>audio/x-tone-seq</code>
 * </ol>
 * </blockquote>
 *
 * <a name="media-locator"></a>
 * <h2>Media Locator</h2>
 * <blockquote>
 * <a name="media-protocol"></a>
 * Media locators are specified in 
 * <a href="http://www.ietf.org/rfc/rfc2396.txt">URI syntax</a> 
 * which is defined in the form:
 * <p>
 *     <scheme>:<scheme-specific-part>
 * <p>
 * The "scheme" part of the locator string identifies the name
 * of the protocol being used to deliver the data.
 * </blockquote>
 *
 * @see Player
 */

public final class Manager {

    /**
     * The locator to create a tone <code>Player</code>
     * to play back tone sequences. e.g. 
     * <pre>
     * try {
     *     Player p = Manager.createPlayer(Manager.TONE_DEVICE_LOCATOR);
     *     p.realize();
     *     ToneControl tc = (ToneControl)p.getControl("ToneControl");
     *     tc.setSequence(mySequence);
     *     p.start();
     * } catch (IOException ioe) {
     * } catch (MediaException me) {}
     * </pre>
     *
     * If a tone sequence is not set on the tone 
     * <code>Player</code> via its <code>ToneControl</code>, 
     * the <code>Player</code> does not carry any 
     * sequence.  <code>getDuration</code> returns 0 for this
     * <code>Player</code>.
     * <p>
     * The content type of the <code>Player</code> created from this
     * locator is <code>audio/x-tone-seq</code>.
     * <p>
     * A <code>Player</code> for this locator may not be supported 
     * for all implementations.
     * <p>
     * Value "device://tone" is assigned to <code>TONE_DEVICE_LOCATOR</code>.
     */
    final public static String TONE_DEVICE_LOCATOR = "device://tone";

    /**
     * The native implementation method to play a tone.
     *
     * @param note Defines the tone of the note.
     * @param dur  The duration of the tone in milli-seconds.
     * @param vol  Audio volume range from 0 to 100.
     *
     * @return the status. <= 0 means it failed to play the tone
     */
    native private static int nPlayTone(int note, int  dur, int vol);

    /**
     * This private constructor keeps anyone from actually
     * getting a <CODE>Manager</CODE>.
     */
    private Manager() {}

    /**
     * Return the list of supported content types for the given protocol.
     * <p>
     * See <a href="#content-type">content types</a> for the syntax
     * of the content types returned.
     * See <a href="#media-protocol">protocol name</a> for the syntax
     * of the protocol used. 
     * <p>
     * For example, if the given <code>protocol</code> 
     * is <code>"http"</code>,
     * then the supported content types that can be played back
     * with the <code>http</code> protocol will be returned.
     * <p>
     * If <code>null</code> is passed in as the <code>protocol</code>, 
     * all the supported content types for this implementation 
     * will be returned.  The returned array must be non-empty.
     * <p>
     * If the given <code>protocol</code> is an invalid or
     * unsupported protocol, then an empty array will be returned.
     *
     * @param protocol The input protocol for the supported content types.
     * @return The list of supported content types for the given protocol.
     */ 
    public static String [] getSupportedContentTypes(String protocol) {
	if (protocol == null)
	    return new String [] { "audio/x-wav", "audio/x-tone-seq" };
	if (protocol.equals("device"))
	    return new String [] { "audio/x-tone-seq" };
	if (protocol.equals("http"))
	    return new String [] { "audio/x-wav" };
	return new String[0];
    }

    /**
     * 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 
     * <code>Player</code>'s.
     * <p>
     * See <a href="#media-protocol">protocol name</a> for the syntax
     * of the protocols returned. 
     * See <a href="#content-type">content types</a> for the syntax
     * of the content type used.
     * <p>
     * For example, if the given <code>content_type</code>
     * is <code>"audio/x-wav"</code>, then the supported protocols
     * that can be used to play back <code>audio/x-wav</code>
     * will be returned.
     * <p>
     * If <code>null</code> is passed in as the 
     * <code>content_type</code>, 
     * all the supported protocols for this implementation 
     * will be returned.  The returned array must be non-empty.
     * <p>
     * If the given <code>content_type</code> is an invalid or
     * unsupported content type, then an empty array will be returned.
     *
     * @param content_type The content type for the supported protocols.
     * @return The list of supported protocols for the given content type.
     */
    public static String [] getSupportedProtocols(String content_type) {
	if (content_type == null)
	    return new String [] { "device", "http" };
	if (content_type.equals("audio/x-tone-seq"))
	    return new String [] { "device" };
	if (content_type.equals("audio/x-wav"))
	    return new String [] { "http" };
	return new String[0];
    }

    /**
     * Create a <code>Player</code> from an input locator.
     *
     * @param locator A locator string in URI syntax that describes
     * the media content.  
     * @return A new <code>Player</code>.
     * @exception IllegalArgumentException Thrown if <code>locator</code>
     * is <code>null</code>.
     * @exception MediaException Thrown if a <code>Player</code> cannot
     * be created for the given locator.
     * @exception IOException Thrown if there was a problem connecting
     * with the source pointed to by the <code>locator</code>.
     * @exception SecurityException Thrown if the caller does not
     * have security permission to create the <code>Player</code>.
     */
    public static Player createPlayer(String locator)
	throws IOException, MediaException {

	if (locator == null)
	    throw new IllegalArgumentException("locator: null");

	BasicPlayer p = null;
	boolean conn = true;
	if (locator.equals(TONE_DEVICE_LOCATOR)) {
	    p = new TonePlayer();
	    conn = false;
	} else {
	    if (locator.toLowerCase().endsWith(".wav") ||
		locator.startsWith("http:")) {
		p = new WavPlayer();
	    }
	}

	if (p == null)
	    throw new MediaException("Unsupported type.");
	
	p.setLocator(locator, conn);
	
	return p;
    }

    /**
     * Create a <code>Player</code> to play back media from an 
     * <code>InputStream</code>.  
     * <p>
     * The <code>type</code> argument
     * specifies the content-type of the input media.  If 
     * <code>null</code> is given, <code>Manager</code> 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
     * <code>Manager</code> may throw a <code>MediaException</code>
     * to indicate that.
     * 
     * @param stream The <code>InputStream</code> that delivers the
     * input media.
     * @param type The <code>ContentType</code> of the media.
     * @return A new <code>Player</code>.
     * @exception IllegalArgumentException Thrown if <code>stream</code>
     * is <code>null</code>.
     * @exception MediaException Thrown if a <code>Player</code> cannot
     * be created for the given stream and type.
     * @exception IOException Thrown if there was a problem reading data
     * from the <code>InputStream</code>.
     * @exception SecurityException Thrown if the caller does not
     * have security permission to create the <code>Player</code>.
     */
    public static Player createPlayer(InputStream stream, String type) 
	throws IOException, MediaException {
	if (stream == null)
	    throw new IllegalArgumentException("stream: null");

	BasicPlayer p = null;

	if (type != null) {
	    type = type.toLowerCase();
	}
	if ((type == null) || 
	    ((type != null) && (type.equals("audio/x-wav")))) {
	    p = new WavPlayer();
	}

	if ((type != null) && (type.equals("audio/x-tone-seq"))) {
	    p = new TonePlayer();
	}

	if (p != null) {
	    p.setStrm(stream);
	    p.setLocator(null, false);
	    return p;
	} 

	throw new MediaException("Unsupported type.");
    }

    /**
     * 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:
     * <pre>
     *     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.
     * </pre>
     * 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 note Defines the tone of the note as specified by the 
     * above formula.
     * @param duration The duration of the tone in milli-seconds.
     * Duration must be positive.
     * @param volume 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.
     */
    static public void playTone(int note, int duration, int volume)
	throws MediaException {
	if (note < 0 || note > 127 || duration <= 0)
	    throw new IllegalArgumentException("playTone");

	if (nPlayTone(note, duration, volume) <= 0)
	    throw new MediaException("can't play tone");
    }
}