--- a/javauis/nokiasound/javasrc/com/nokia/mid/sound/Sound.java Wed Sep 15 12:05:25 2010 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,698 +0,0 @@
-/*
-* Copyright (c) 2006 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: Provides Sound API for playing tones and digitized audio.
-*
-*/
-
-
-package com.nokia.mid.sound;
-
-import com.nokia.mj.impl.rt.support.Finalizer;
-import java.util.Vector;
-import com.nokia.mj.impl.utils.Logger;
-import java.lang.Thread;
-
-/**
- * <p>
- * Provides simple Sound API for playing tones and digitized audio.
- * </p><p>
- * Since MIDP doesn't have any Sound API for games there is a need
- * for proprietary sound extension to support devices audio
- * capabilities. Every implementation has capability to produce tone
- * sounds (e.g. ringing tones), this is the minimum support. Currently
- * some products support or will support also digitized audio formats.
- * The Game sound API will support both buzzer and digitized audio.
- * Buzzer must be supported by all implementations. If implementation
- * doesn't have buzzer the buzzer tones are emulated.
- * </p>
- * Since implementations have different audio capabilities,
- * application can query which audio formats are supported by
- * implementation by calling {@link #getSupportedFormats()}.
- * <p>
- * All implementations need to support at least tone based sounds
- * (type FORMAT_TONE) via {@link #Sound(int freq, long duration)} and
- * {@link #init(int freq, long duration)}. In addition all implementations
- * must support Smart messaging ringingtone format (type FORMAT_TONE)
- * via {@link #Sound(byte[] data, int type)} and
- * {@link #init(byte[] data, int type) }.
- * <p>
- * Note that there is also work going on with Multimedia API that
- * is done in JCP as
- * <a href="http://www.jcp.org/jsr/detail/135.jsp">JSR 135</a>.
- * The standard Multimedia API
- * will replace the proprietary Game Sound API when it is ready. However
- * Sound API will be supported also later on but probably it will be
- * stated as deprecated.
- * </p>
- * @version 1.1
- * @see com.nokia.mid.ui.DeviceControl
- * @since 1.0
- */
-
-public class Sound
-{
-
- /**
- * Tone based format is used.
- *
- * init(int freq, int duration) puts sound into this format.
- * @since 1.0
- *
- */
- public static final int FORMAT_TONE = 1;
-
- /**
- * Content is in WAV format.
- * @since 1.0
- *
- */
- public static final int FORMAT_WAV = 5;
-
- /**
- * Sound is playing.
- * @since 1.0
- *
- */
- public static final int SOUND_PLAYING = 0;
-
- /**
- * Sound is stopped.
- * @since 1.0
- *
- */
- public static final int SOUND_STOPPED = 1;
-
- /**
- * Sound is uninitialized (released).
- * @since 1.0
- */
- public static final int SOUND_UNINITIALIZED = 3;
-
- /**
- * Sound is reinitialising
- */
- private static final int SOUND_REINITIALISING = 4;
-
- private static final int FORMAT_BEEP = 2;
- private static final int NOT_SUPPORTED_ERROR = 3;
-
- private static final int ERR_NOT_READY = -18;
- private static final int ERR_ARGUMENT = -6;
-
- private int iHandle;
-
- private Finalizer iFinalizer;
- private int iCurrentType;
- private int iState;
- private int iGain = -1;
-
- Vector iSoundListeners = new Vector();
-
- private static Sound iPlayingSound;
-
- static
- {
- com.nokia.mj.impl.rt.support.Jvm.loadSystemLibrary("javanokiasound");
- }
-
- /**
- * Constructors initialize the Sound object so that it is ready for
- * playback. This constructor is used for initializing Sound
- * object based on byte array data. The data should contain the data
- * presented in the data format specified by type parameter. The Sound
- * class defines also generally supported types as constants.
- * <p>
- * All implementations need to support at least Nokia
- * Smart Messaging, Over the Air (OTA) ringingtone format.
- * The type of this format is FORMAT_TONE.
- * <p>
- * Note: some implementations can't throw exceptions about
- * sound data being corrupted or illegal during construction.
- * This will result that IllagalArgumentException is delayed until
- * play(int loop) method is called. Applications thus need to except
- * that IllegalArgumentException is thrown in this method or during
- * play method call.
- * <p>
- * @throws java.lang.IllegalArgumentException if the data can not be
- recognized to
- * given type or the type is unsupported or unknown
- * @throws java.lang.NullPointerException if the data is null
- * @since 1.0
- *
- */
- public Sound(byte[] data, int type)
- {
- Logger.LOG(Logger.EJavaUI, Logger.EInfo, "Sound Constructor");
- iFinalizer = registerForFinalization();
-
- iHandle = _create();
-
- iState = SOUND_UNINITIALIZED;
-
- init(data, type);
- }
-
- /**
- * Constructors initialize the Sound object so that it is ready for
- * playback. Sound is initialized as a simple tone based sound.
- * <p>
- * See method {@link #init(int freq, long duration)} for
- * freq value descriptions. See also a note on exceptions semantics in
- * {@link #init(int freq, long duration)}.
- *
- * @param freq a frequency value
- * @param duration the duration of the tone in milliseconds
- * @throws java.lang.IllegalArgumentException if parameter values are
- * illegal, freq is not in given range or duration is negative or zero
- * @since 1.0
- */
- public Sound(int freq, long duration)
- {
-
- iFinalizer = registerForFinalization();
- iHandle = _create();
-
- iState = SOUND_UNINITIALIZED;
-
- init(freq, duration);
- }
-
- /**
- * Called when this object is finalized, frees native resources
- */
-
- public Finalizer registerForFinalization()
- {
-
- return new Finalizer()
- {
- public void finalizeImpl()
- {
- doFinalize();
- }
- };
- }
-
- void doFinalize()
- {
-
- if (iFinalizer == null)
- {
- return;
- }
- iFinalizer = null;
-
- if (iHandle > 0)
- {
- _dispose(iHandle);
- }
- }
-
- /**
- * Releases audio resources reserved by this object. After object
- * is released it goes to uninitialized state. This method should
- * be called when Sound object is not needed anymore.
- * @since 1.0
- */
- public void release()
- {
- if ((iState != SOUND_UNINITIALIZED) &&
- (iState != SOUND_REINITIALISING))
- {
- iState = SOUND_REINITIALISING;
- soundStateChanged(SOUND_UNINITIALIZED);
- }
-
- _release(iHandle);
-
- iState = SOUND_UNINITIALIZED;
-
- }
-
- /**
- * Initializes Sound to play a simple beep.
- * <p>
- * Note: some implementations may not support the full frequency
- * scale defined in table below. They will throw
- * IllegalArgumentException instead for unsupported values. The
- * exception may also be delayed
- * until the play(int loop) method is called.
- * <p>
- * Following table describes some freq argument
- * values:
- * <pre>
- * Description Frequency
- * Freq off 0
- * Ring freq A0 220
- * Ring freq B0b 233
- * Ring freq B0 247
- * Ring freq C0 262
- * Ring freq D0b 277
- * Ring freq D0 294
- * Ring freq E0b 311
- * Ring freq E0 330
- * Ring freq F0 349
- * Ring freq G0b 370
- * Ring freq G0 392
- * Ring freq A1b 416
- * Ring freq A1 440
- * Ring freq B1b 466
- * Ring freq B1 494
- * Ring freq C1 523
- * Ring freq D1b 554
- * Ring freq D1 587
- * Ring freq E1b 622
- * Ring freq E1 659
- * Ring freq F1 698
- * Ring freq G1b 740
- * Ring freq G1 784
- * Ring freq A2b 831
- * Ring freq A2 880
- * Ring freq B2b 932
- * Ring freq B2 988
- * Ring freq C2 1047
- * Ring freq D2b 1109
- * Ring freq D2 1175
- * Ring freq E2b 1245
- * Ring freq E2 1319
- * Ring freq F2 1397
- * Ring freq G2b 1480
- * Ring freq G2 1568
- * Ring freq A3b 1661
- * Ring freq A3 1760
- * Ring freq B3b 1865
- * Ring freq B3 1976
- * Ring freq C3 2093
- * Ring freq D3b 2217
- * Ring freq D3 2349
- * Ring freq E3b 2489
- * Ring freq E3 2637
- * Ring freq F3 2794
- * Ring freq G3b 2960
- * Ring freq G3 3136
- * Ring freq A4b 3322
- * Ring freq A4 3520
- * Ring freq B4b 3729
- * Ring freq B4 3951
- * Ring freq C4 4186
- * Ring freq D4b 4434
- * Ring freq D4 4698
- * Ring freq E4b 4978
- * Ring freq E4 5274
- * Ring freq F4 5588
- * Ring freq G4b 5920
- * Ring freq G4 6272
- * Ring freq A5b 6644
- * Ring freq A5 7040
- * Ring freq B5b 7458
- * Ring freq B5 7902
- * Ring freq C5 8372
- * Ring freq D5b 8870
- * Ring freq D5 9396
- * Ring freq E5b 9956
- * Ring freq E5 10548
- * Ring freq F5 11176
- * Ring freq G5b 11840
- * Ring freq G5 12544
- * Ring freq A6b 13288
- *
- * </pre>
- *
- * @param duration length of the beep in milliseconds
- * @param freq frequency to be played
- * @throws java.lang.IllegalArgumentException if parameter values are
- * illegal, freq is not in given range or duration is negative or zero
- * @since 1.0
- */
- public void init(int freq, long duration)
- {
- if (duration < 1 || duration > 10000000)
- {
- throw(new IllegalArgumentException(
- "Bad duration value, must be 1-10000000"));
- }
- if (freq < 0 || freq > 15000)
- {
- throw(new IllegalArgumentException(
- "Bad frequency value, must be 0-15000"));
- }
- // if the uninitialised event is sent from native side, it reaches
- // listener too late in TCK test sound8004, thus we send the event
- // already here
- if ((iState != SOUND_UNINITIALIZED) &&
- (iState != SOUND_REINITIALISING))
- {
- iState = SOUND_REINITIALISING;
- soundStateChanged(SOUND_UNINITIALIZED);
- } // end of if (iState != SOUND_UNINITIALIZED)
-
- iCurrentType = FORMAT_BEEP;
- int err = _init(iHandle, iCurrentType, null, freq, duration);
- if (err == ERR_NOT_READY)
- {
- throw new RuntimeException(Integer.toString(err));
- }
- else if (err == ERR_ARGUMENT)
- {
- throw new IllegalArgumentException("Data is invalid");
- }
- iState = SOUND_STOPPED;
- }
-
- /**
- * Initializes Sound object based on byte
- * array data. The data should contain the data presented in the data
- * format specified by type parameter. The Sound class defines also
- * generally supported types as constants.
- * <p>
- * All implementations need to support at least Nokia
- * Smart Messaging, Over the Air (OTA) ringingtone format.
- * The type of this format is FORMAT_TONE.
- * <p>
- * Note: some implementations can't throw exceptions about
- * sound data being corrupted or illegal during this method call.
- * This will result that IllagalArgumentException is delayed until
- * play(int loop) method is called. Applications thus need to except
- * that IllegalArgumentException is thrown in this method or during
- * play method call.
- * <p>
- * @param data a byte array containing the data to be played
- * @param type type of the audio
- * @throws java.lang.IllegalArgumentException if the data can not be
- recognized to
- * given type or the type is unsupported or unknown
- * @throws java.lang.NullPointerException if the data is null
- * @since 1.0
- */
- public void init(byte[] data, int type)
- {
- if (!(type == FORMAT_WAV || type == FORMAT_TONE))
- {
- throw(new IllegalArgumentException("Type is not supported"));
- }
- if (data == null)
- {
- throw(new NullPointerException("Data is null"));
- }
-
- if ((iState != SOUND_UNINITIALIZED) &&
- (iState != SOUND_REINITIALISING))
- {
- iState = SOUND_REINITIALISING;
- soundStateChanged(SOUND_UNINITIALIZED);
- } // end of if (iState != SOUND_UNINITIALIZED)
-
- iCurrentType = type;
- int err = _init(iHandle, iCurrentType, data, 0, 0);
- if (err == ERR_NOT_READY || err == ERR_ARGUMENT )
- {
- throw new IllegalArgumentException("Data is invalid");
- }
-
- iState = SOUND_STOPPED;
- }
-
-
- /**
- * Get the current state of the Sound object.
- *
- * @return current state, SOUND_PLAYING, SOUND_STOPPED or
- SOUND_UNINITIALIZED
- * @since 1.0
- *
- */
- public int getState()
- {
- if (iState == SOUND_REINITIALISING)
- {
- return SOUND_UNINITIALIZED;
- }
-
- iState = _getState(iHandle);
- switch (iState)
- {
- case(0): // ENotReady
- case(4): // EInitialising
- iState = SOUND_UNINITIALIZED;
- break;
- case(1): // EReadyToPlay
- iState = SOUND_STOPPED;
- break;
- case(2): // EPlaying
- iState = SOUND_PLAYING;
- break;
- default:
- }
- return iState;
- }
-
- /**
- * This method is used for starting the playback from the beginning of a
- * sound object. The loop parameter defined the loop count for playback.
- * Argument zero (0) means continuos looping. For uninitialized sound the
- * play method doesn't do anything and silently returns. For stopped and
- * playing sounds the playback starts from beginning of the sound with new
- * looping information.
- * <p>
- * This method will throw IllegalStateException if playback cannot be
- * started since all channels are in use, or playback is not possible
- * because there is more higher priority system sounds being played.
- * <p>
- * If Sound playback is possible this method will return immediately and
- * thus will not block the calling thread during the playback. If any error
- * that prevents the playback is encountered during the playback, the
- * playback is silently stopped as if called to the stop method.
- *
- * @param number number of times audio is played. Value 0 plays audio in
- * continous loop.
- * @throws java.lang.IllegalStateException if the sound object cannot be
- * played because all the channels are already in use.
- * @throws java.lang.IllegalArgumentException if the loop value is negative,
- * or if sound values/date is illegal or corrupted.
- * @since 1.0
- *
- */
- public void play(int loop) throws IllegalArgumentException
- {
- if (loop < 0)
- {
- throw(new IllegalArgumentException("Negative loop value"));
- }
- if (iState == SOUND_REINITIALISING)
- {
- return;
- } // end of if (iState == SOUND_REINITIALISING)
-
- if (iPlayingSound != null)
- {
- if (iPlayingSound.getState() == SOUND_PLAYING)
- {
- iPlayingSound.stop();
- }
- } // end of if (iPlayingSound != null)
-
- int error = _play(iHandle, loop);
- if ((error == NOT_SUPPORTED_ERROR))
- {
- throw(new IllegalArgumentException("Sound is not supported"));
- }
- iPlayingSound = this;
- }
-
- /**
- * The method will stop the sound playback, storing the current position.
- * For sound that has never been started (may be uninitialized), or is
- * currently being stopped the method call doesn't do anything and returns
- * silently.
- *
- * Note that for tone based sounds it is not possible to resume from
- * position the sound was stopped at, to be specific, stop will reset
- * the position to the beginning of the sound.
- * @since 1.0
- */
- public void stop()
- {
- if (iState == SOUND_REINITIALISING)
- {
- return;
- } // end of if (iState == SOUND_REINITIALISING)
- _stop(iHandle);
- }
-
- /**
- * The method will continue the stopped sound object from the position it
- * was stopped to. For sound that has never been started (may be
- * uninitialized), or is currently being played the method call doesn't
- * do anything.
- * <p>
- * Note: For tone based sounds the resume starts the sound from the
- * beginning of the sound clip.
- * @since 1.0
- *
- */
- public void resume()
- {
- if (iState == SOUND_REINITIALISING)
- {
- return;
- } // end of if (iState == SOUND_REINITIALISING)
- _resume(iHandle);
- }
-
- /**
- * Sets the gain for the sound object. The gain is a value between
- * 0 and 255. Implementation scales the gain value to the limits it
- * supports. Notice that any gain value > 0 should result a gain
- * value > 0. If the gain is smaller than this minimum value then
- * gain is set to 0, if the gain greater than this maximum value
- * then the gain is set to maximum value (255).
- *
- * @param gain gain value: 0 - 255
- * @throws java.lang.IllegalArgumentException if the gain not 0 - 255
- * @since 1.0
- */
- public void setGain(int gain)
- {
- if (iState == SOUND_REINITIALISING)
- {
- return;
- } // end of if (iState == SOUND_REINITIALISING)
- if (gain < 0)
- {
- gain = 0;
- }
- else if (gain > 255)
- {
- gain = 255;
- }
- iGain = gain;
- _setVolume(iHandle, iGain);
- }
-
- /**
- * Get the gain (or volume) of Sound object. The gain is a value
- * between 0 and 255. System returns a scaled value based on the
- * limits it supports. Notice that any system gain value > 0 should
- * return a gain value > 0.
- *
- * @return gain value 0 - 255
- * @since 1.0
- *
- */
- public int getGain()
- {
- if (iGain == -1)
- {
- return _volume(iHandle);
- }
- // we have previously set gain
- return iGain;
- }
-
- /**
- * Returns number of concurrent sounds the device can play for
- * specific audio type. Returns 1 if only one sound can be played
- * at a time. Notice that most types use same channel resources.
- * @return total number of available channels.
- * @param type the media type
- * @throws java.lang.IllegalArgumentException if the type is unsupported
- * or unknown
- * @since 1.0
- */
- public static int getConcurrentSoundCount(int type)
- {
- if ((type != FORMAT_TONE) && (type != FORMAT_WAV))
- {
- throw(new IllegalArgumentException("Type is not supported"));
- }
-
- return 1;
- }
-
- /**
- * Returns the supported audio formats as an int array.
- *
- * @return an array containing supported audio formats as
- * int values (e.g. FORMAT_TONE, FORMAT_WAV),
- * or an empty array if no audio formats are supported.
- * @since 1.0
- */
- static public int[] getSupportedFormats()
- {
- return(new int[] { FORMAT_TONE, FORMAT_WAV });
- }
-
- /**
- * Registeres a listener for playback state notifications.
- * @see com.nokia.mid.sound.SoundListener
- * @param listener a listener that is notified when state
- * changes occur or null if listener is to be
- * removed.
- * @since 1.0
- *
- */
- public void setSoundListener(SoundListener listener)
- {
- iSoundListeners.addElement(listener);
- }
-
- /**
- * Callback method when sound state changes
- *
- */
- public void soundStateChanged(final int event)
- {
- /*
- for(int i = 0; i < iSoundListeners.size(); i++)
- {
- ((SoundListener)iSoundListeners.elementAt(i)).soundStateChanged(this, event);
- }
- */
- //Notify SoundState Listeners in a separate thread, so that application doesn't
- //block main thread
- new Thread(new Runnable()
- {
- public void run()
- {
- notifySoundStateListeners(event);
- }
- }).start();
- }
-
- /**
- * Notify Sound State Listeners
- */
- public synchronized void notifySoundStateListeners(int event)
- {
- for (int i = 0; i < iSoundListeners.size(); i++)
- {
- ((SoundListener)iSoundListeners.elementAt(i)).soundStateChanged(this, event);
- }
- }
-
- private native void _dispose(int aHandle);
- private native int _create();
- private native int _init(int aHandle, int aType,
- byte[] aData,
- int aFrequency, long aDuration);
- private native void _release(int aHandle);
- private native int _play(int aHandle, int aLoop);
- private native void _stop(int aHandle);
- private native void _resume(int aHandle);
- private native void _setVolume(int aHandle, int aVolume);
- private native int _volume(int aHandle);
- private native int _getState(int aHandle);
-
-} //End of Sound class
-