SoundPool.java revision f992cbb9aae593c7787ac9c5f6b475e7bb0a92c5
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.media;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.AndroidRuntimeException;
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log;
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.File;
229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileDescriptor;
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.ParcelFileDescriptor;
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.lang.ref.WeakReference;
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context;
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.AssetFileDescriptor;
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException;
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
29f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparksimport android.os.Handler;
30f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparksimport android.os.Looper;
31f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparksimport android.os.Message;
32f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks
33cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks/**
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * The SoundPool class manages and plays audio resources for applications.
35cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks *
36cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * <p>A SoundPool is a collection of samples that can be loaded into memory
37cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * from a resource inside the APK or from a file in the file system. The
38cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * SoundPool library uses the MediaPlayer service to decode the audio
39cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * into a raw 16-bit PCM mono or stereo stream. This allows applications
40cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * to ship with compressed streams without having to suffer the CPU load
41cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * and latency of decompressing during playback.</p>
42cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks *
43cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * <p>In addition to low-latency playback, SoundPool can also manage the number
44cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * of audio streams being rendered at once. When the SoundPool object is
45cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * constructed, the maxStreams parameter sets the maximum number of streams
46cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * that can be played at a time from this single SoundPool. SoundPool tracks
47cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * the number of active streams. If the maximum number of streams is exceeded,
48cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * SoundPool will automatically stop a previously playing stream based first
49cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * on priority and then by age within that priority. Limiting the maximum
50cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * number of streams helps to cap CPU loading and reducing the likelihood that
51cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * audio mixing will impact visuals or UI performance.</p>
52cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks *
536cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks * <p>Sounds can be looped by setting a non-zero loop value. A value of -1
546cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks * causes the sound to loop forever. In this case, the application must
556cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks * explicitly call the stop() function to stop the sound. Any other non-zero
566cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks * value will cause the sound to repeat the specified number of times, e.g.
576cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks * a value of 3 causes the sound to play a total of 4 times.</p>
586cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks *
596cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks * <p>The playback rate can also be changed. A playback rate of 1.0 causes
606cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks * the sound to play at its original frequency (resampled, if necessary,
616cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks * to the hardware output frequency). A playback rate of 2.0 causes the
626cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks * sound to play at twice its original frequency, and a playback rate of
636cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks * 0.5 causes it to play at half its original frequency. The playback
646cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks * rate range is 0.5 to 2.0.</p>
656cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks *
66cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * <p>Priority runs low to high, i.e. higher numbers are higher priority.
67cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * Priority is used when a call to play() would cause the number of active
68cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * streams to exceed the value established by the maxStreams parameter when
69cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * the SoundPool was created. In this case, the stream allocator will stop
70cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * the lowest priority stream. If there are multiple streams with the same
71cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * low priority, it will choose the oldest stream to stop. In the case
72cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * where the priority of the new stream is lower than all the active
73cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * streams, the new sound will not play and the play() function will return
74cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * a streamID of zero.</p>
75cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks *
76cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * <p>Let's examine a typical use case: A game consists of several levels of
77cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * play. For each level, there is a set of unique sounds that are used only
78cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * by that level. In this case, the game logic should create a new SoundPool
79cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * object when the first level is loaded. The level data itself might contain
80cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * the list of sounds to be used by this level. The loading logic iterates
81cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * through the list of sounds calling the appropriate SoundPool.load()
82cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * function. This should typically be done early in the process to allow time
83cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * for decompressing the audio to raw PCM format before they are needed for
84cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * playback.</p>
85cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks *
86cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * <p>Once the sounds are loaded and play has started, the application can
87cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * trigger sounds by calling SoundPool.play(). Playing streams can be
88cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * paused or resumed, and the application can also alter the pitch by
89cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * adjusting the playback rate in real-time for doppler or synthesis
90cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * effects.</p>
91cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks *
926cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks * <p>Note that since streams can be stopped due to resource constraints, the
936cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks * streamID is a reference to a particular instance of a stream. If the stream
946cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks * is stopped to allow a higher priority stream to play, the stream is no
956cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks * longer be valid. However, the application is allowed to call methods on
966cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks * the streamID without error. This may help simplify program logic since
976cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks * the application need not concern itself with the stream lifecycle.</p>
986cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks *
99cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * <p>In our example, when the player has completed the level, the game
100cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * logic should call SoundPool.release() to release all the native resources
101cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * in use and then set the SoundPool reference to null. If the player starts
102cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * another level, a new SoundPool is created, sounds are loaded, and play
103cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks * resumes.</p>
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class SoundPool
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static { System.loadLibrary("soundpool"); }
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final static String TAG = "SoundPool";
110f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks    private final static boolean DEBUG = false;
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int mNativeContext; // accessed by native methods
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
114f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks    private EventHandler mEventHandler;
115f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks    private OnLoadCompleteListener mOnLoadCompleteListener;
116f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks
117f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks    private final Object mLock;
118f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks
119f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks    // SoundPool messages
120f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks    //
121f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks    // must match SoundPool.h
122f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks    private static final int SAMPLE_LOADED = 1;
123f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks
124cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks    /**
125cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * Constructor. Constructs a SoundPool object with the following
126cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * characteristics:
127cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *
128cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @param maxStreams the maximum number of simultaneous streams for this
129cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *                   SoundPool object
130cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @param streamType the audio stream type as described in AudioManager
131cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *                   For example, game applications will normally use
132cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *                   {@link AudioManager#STREAM_MUSIC}.
133cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @param srcQuality the sample-rate converter quality. Currently has no
134cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *                   effect. Use 0 for the default.
135cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @return a SoundPool object, or null if creation failed
136cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     */
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public SoundPool(int maxStreams, int streamType, int srcQuality) {
138f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks
139f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks        // do native setup
140f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks        if (native_setup(new WeakReference(this), maxStreams, streamType, srcQuality) != 0) {
141f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks            throw new RuntimeException("Native setup failed");
142f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks        }
143f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks        mLock = new Object();
144f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks
145f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks        // setup message handler
146f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks        Looper looper;
147f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks        if ((looper = Looper.myLooper()) != null) {
148f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks            mEventHandler = new EventHandler(this, looper);
149f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks        } else if ((looper = Looper.getMainLooper()) != null) {
150f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks            mEventHandler = new EventHandler(this, looper);
151f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks        } else {
152f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks            mEventHandler = null;
153f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks        }
154f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
157cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks    /**
1586cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * Load the sound from the specified path.
1596cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     *
160cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @param path the path to the audio file
1616cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * @param priority the priority of the sound. Currently has no effect. Use
1626cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     *                 a value of 1 for future compatibility.
163cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @return a sound ID. This value can be used to play or unload the sound.
164cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     */
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int load(String path, int priority)
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    {
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // pass network streams to player
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (path.startsWith("http:"))
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return _load(path, priority);
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // try local path
1729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int id = 0;
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            File f = new File(path);
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (f != null) {
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ParcelFileDescriptor fd = ParcelFileDescriptor.open(f, ParcelFileDescriptor.MODE_READ_ONLY);
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (fd != null) {
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    id = _load(fd.getFileDescriptor(), 0, f.length(), priority);
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    fd.close();
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
182d282ac8610f72d964105efefe41120a5340f1ce0Marco Nelissen        } catch (java.io.IOException e) {
183f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks            Log.e(TAG, "error loading " + path);
184d282ac8610f72d964105efefe41120a5340f1ce0Marco Nelissen        }
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return id;
1869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
188cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks    /**
1896cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * Load the sound from the specified APK resource.
190cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *
1916cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * Note that the extension is dropped. For example, if you want to load
192cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * a sound from the raw resource file "explosion.mp3", you would specify
193cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * "R.raw.explosion" as the resource ID. Note that this means you cannot
194cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * have both an "explosion.wav" and an "explosion.mp3" in the res/raw
1956cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * directory.
196cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *
197cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @param context the application context
198cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @param resId the resource ID
1996cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * @param priority the priority of the sound. Currently has no effect. Use
2006cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     *                 a value of 1 for future compatibility.
201cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @return a sound ID. This value can be used to play or unload the sound.
202cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     */
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int load(Context context, int resId, int priority) {
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        AssetFileDescriptor afd = context.getResources().openRawResourceFd(resId);
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int id = 0;
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (afd != null) {
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            id = _load(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength(), priority);
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                afd.close();
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (java.io.IOException ex) {
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                //Log.d(TAG, "close failed:", ex);
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return id;
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
217cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks    /**
2186cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * Load the sound from an asset file descriptor.
219cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *
220cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @param afd an asset file descriptor
2216cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * @param priority the priority of the sound. Currently has no effect. Use
2226cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     *                 a value of 1 for future compatibility.
223cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @return a sound ID. This value can be used to play or unload the sound.
224cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     */
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int load(AssetFileDescriptor afd, int priority) {
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (afd != null) {
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            long len = afd.getLength();
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (len < 0) {
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new AndroidRuntimeException("no length for fd");
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return _load(afd.getFileDescriptor(), afd.getStartOffset(), len, priority);
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return 0;
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
237cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks    /**
2386cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * Load the sound from a FileDescriptor.
239cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *
2406cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * This version is useful if you store multiple sounds in a single
241cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * binary. The offset specifies the offset from the start of the file
2426cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * and the length specifies the length of the sound within the file.
243cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *
244cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @param fd a FileDescriptor object
245cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @param offset offset to the start of the sound
246cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @param length length of the sound
2476cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * @param priority the priority of the sound. Currently has no effect. Use
2486cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     *                 a value of 1 for future compatibility.
249cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @return a sound ID. This value can be used to play or unload the sound.
250cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     */
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public int load(FileDescriptor fd, long offset, long length, int priority) {
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return _load(fd, offset, length, priority);
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native final int _load(String uri, int priority);
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private native final int _load(FileDescriptor fd, long offset, long length, int priority);
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
259cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks    /**
2606cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * Unload a sound from a sound ID.
261cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *
2626cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * Unloads the sound specified by the soundID. This is the value
263cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * returned by the load() function. Returns true if the sound is
2646cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * successfully unloaded, false if the sound was already unloaded.
265cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *
266cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @param soundID a soundID returned by the load() function
267cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @return true if just unloaded, false if previously unloaded
268cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     */
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public native final boolean unload(int soundID);
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
271cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks    /**
2726cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * Play a sound from a sound ID.
273cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *
2746cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * Play the sound specified by the soundID. This is the value
275cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * returned by the load() function. Returns a non-zero streamID
276cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * if successful, zero if it fails. The streamID can be used to
277cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * further control playback. Note that calling play() may cause
278cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * another sound to stop playing if the maximum number of active
2796cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * streams is exceeded. A loop value of -1 means loop forever,
2806cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * a value of 0 means don't loop, other values indicate the
2816cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * number of repeats, e.g. a value of 1 plays the audio twice.
2826cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * The playback rate allows the application to vary the playback
2836cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * rate (pitch) of the sound. A value of 1.0 means play back at
2846cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * the original frequency. A value of 2.0 means play back twice
2856cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * as fast, and a value of 0.5 means playback at half speed.
286cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *
287cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @param soundID a soundID returned by the load() function
2886cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * @param leftVolume left volume value (range = 0.0 to 1.0)
2896cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * @param rightVolume right volume value (range = 0.0 to 1.0)
2906cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * @param priority stream priority (0 = lowest priority)
2916cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * @param loop loop mode (0 = no loop, -1 = loop forever)
2926cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * @param rate playback rate (1.0 = normal playback, range 0.5 to 2.0)
293cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @return non-zero streamID if successful, zero if failed
294cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     */
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public native final int play(int soundID, float leftVolume, float rightVolume,
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int priority, int loop, float rate);
2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
298cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks    /**
2996cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * Pause a playback stream.
300cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *
3016cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * Pause the stream specified by the streamID. This is the
302cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * value returned by the play() function. If the stream is
303cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * playing, it will be paused. If the stream is not playing
304cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * (e.g. is stopped or was previously paused), calling this
3056cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * function will have no effect.
306cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *
307cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @param streamID a streamID returned by the play() function
308cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     */
3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public native final void pause(int streamID);
3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
311cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks    /**
3126cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * Resume a playback stream.
313cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *
3146cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * Resume the stream specified by the streamID. This
315cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * is the value returned by the play() function. If the stream
316cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * is paused, this will resume playback. If the stream was not
3176cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * previously paused, calling this function will have no effect.
318cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *
319cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @param streamID a streamID returned by the play() function
320cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     */
3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public native final void resume(int streamID);
3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
323cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks    /**
324f992cbb9aae593c7787ac9c5f6b475e7bb0a92c5Dave Sparks     * Pause all active streams.
325f992cbb9aae593c7787ac9c5f6b475e7bb0a92c5Dave Sparks     *
326f992cbb9aae593c7787ac9c5f6b475e7bb0a92c5Dave Sparks     * Pause all streams that are currently playing. This function
327f992cbb9aae593c7787ac9c5f6b475e7bb0a92c5Dave Sparks     * iterates through all the active streams and pauses any that
328f992cbb9aae593c7787ac9c5f6b475e7bb0a92c5Dave Sparks     * are playing. It also sets a flag so that any streams that
329f992cbb9aae593c7787ac9c5f6b475e7bb0a92c5Dave Sparks     * are playing can be resumed by calling autoResume().
330f992cbb9aae593c7787ac9c5f6b475e7bb0a92c5Dave Sparks     *
331f992cbb9aae593c7787ac9c5f6b475e7bb0a92c5Dave Sparks     * @hide
332f992cbb9aae593c7787ac9c5f6b475e7bb0a92c5Dave Sparks     */
333f992cbb9aae593c7787ac9c5f6b475e7bb0a92c5Dave Sparks    public native final void autoPause();
334f992cbb9aae593c7787ac9c5f6b475e7bb0a92c5Dave Sparks
335f992cbb9aae593c7787ac9c5f6b475e7bb0a92c5Dave Sparks    /**
336f992cbb9aae593c7787ac9c5f6b475e7bb0a92c5Dave Sparks     * Resume all previously active streams.
337f992cbb9aae593c7787ac9c5f6b475e7bb0a92c5Dave Sparks     *
338f992cbb9aae593c7787ac9c5f6b475e7bb0a92c5Dave Sparks     * Automatically resumes all streams that were paused in previous
339f992cbb9aae593c7787ac9c5f6b475e7bb0a92c5Dave Sparks     * calls to autoPause().
340f992cbb9aae593c7787ac9c5f6b475e7bb0a92c5Dave Sparks     *
341f992cbb9aae593c7787ac9c5f6b475e7bb0a92c5Dave Sparks     * @hide
342f992cbb9aae593c7787ac9c5f6b475e7bb0a92c5Dave Sparks     */
343f992cbb9aae593c7787ac9c5f6b475e7bb0a92c5Dave Sparks    public native final void autoResume();
344f992cbb9aae593c7787ac9c5f6b475e7bb0a92c5Dave Sparks
345f992cbb9aae593c7787ac9c5f6b475e7bb0a92c5Dave Sparks    /**
3466cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * Stop a playback stream.
347cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *
3486cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * Stop the stream specified by the streamID. This
349cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * is the value returned by the play() function. If the stream
350cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * is playing, it will be stopped. It also releases any native
351cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * resources associated with this stream. If the stream is not
3526cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * playing, it will have no effect.
353cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *
354cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @param streamID a streamID returned by the play() function
355cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     */
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public native final void stop(int streamID);
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
358cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks    /**
3596cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * Set stream volume.
360cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *
3616cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * Sets the volume on the stream specified by the streamID.
362cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * This is the value returned by the play() function. The
363cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * value must be in the range of 0.0 to 1.0. If the stream does
3646cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * not exist, it will have no effect.
365cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *
366cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @param streamID a streamID returned by the play() function
367cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @param leftVolume left volume value (range = 0.0 to 1.0)
368cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @param rightVolume right volume value (range = 0.0 to 1.0)
369cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     */
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public native final void setVolume(int streamID,
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            float leftVolume, float rightVolume);
3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
373cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks    /**
3746cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * Change stream priority.
375cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *
3766cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * Change the priority of the stream specified by the streamID.
377cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * This is the value returned by the play() function. Affects the
3786cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * order in which streams are re-used to play new sounds. If the
3796cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * stream does not exist, it will have no effect.
380cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *
381cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @param streamID a streamID returned by the play() function
382cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     */
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public native final void setPriority(int streamID, int priority);
3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
385cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks    /**
3866cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * Set loop mode.
387cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *
3886cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * Change the loop mode. A loop value of -1 means loop forever,
3896cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * a value of 0 means don't loop, other values indicate the
3906cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * number of repeats, e.g. a value of 1 plays the audio twice.
3916cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * If the stream does not exist, it will have no effect.
392cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     *
393cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     * @param streamID a streamID returned by the play() function
3946cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * @param loop loop mode (0 = no loop, -1 = loop forever)
395cef302d0950a02fdc6920475d0c357d3949e85c3Dave Sparks     */
3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public native final void setLoop(int streamID, int loop);
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3986cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks    /**
3996cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * Change playback rate.
4006cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     *
4016cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * The playback rate allows the application to vary the playback
4026cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * rate (pitch) of the sound. A value of 1.0 means playback at
4036cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * the original frequency. A value of 2.0 means playback twice
4046cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * as fast, and a value of 0.5 means playback at half speed.
4056cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * If the stream does not exist, it will have no effect.
4066cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     *
4076cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * @param streamID a streamID returned by the play() function
4086cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * @param rate playback rate (1.0 = normal playback, range 0.5 to 2.0)
4096cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     */
4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public native final void setRate(int streamID, float rate);
4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4126cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks    /**
413f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks     * Interface definition for a callback to be invoked when all the
414f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks     * sounds are loaded.
415f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks     *
416f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks     * @hide
417f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks     */
418f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks    public interface OnLoadCompleteListener
419f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks    {
420f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks        /**
421f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks         * Called when a sound has completed loading.
422f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks         *
423f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks         * @param soundPool SoundPool object from the load() method
424f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks         * @param soundPool the sample ID of the sound loaded.
425f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks         * @param status the status of the load operation (0 = success)
426f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks         */
427f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks        public void onLoadComplete(SoundPool soundPool, int sampleId, int status);
428f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks    }
429f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks
430f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks    /**
431f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks     * Sets the callback hook for the OnLoadCompleteListener.
432f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks     *
433f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks     * @hide
434f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks     */
435f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks    public void setOnLoadCompleteListener(OnLoadCompleteListener listener)
436f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks    {
437f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks        synchronized(mLock) {
438f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks            mOnLoadCompleteListener = listener;
439f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks        }
440f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks    }
441f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks
442f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks    private class EventHandler extends Handler
443f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks    {
444f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks        private SoundPool mSoundPool;
445f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks
446f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks        public EventHandler(SoundPool soundPool, Looper looper) {
447f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks            super(looper);
448f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks            mSoundPool = soundPool;
449f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks        }
450f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks
451f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks        @Override
452f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks        public void handleMessage(Message msg) {
453f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks            switch(msg.what) {
454f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks            case SAMPLE_LOADED:
455f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks                if (DEBUG) Log.d(TAG, "Sample " + msg.arg1 + " loaded");
456f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks                synchronized(mLock) {
457f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks                    if (mOnLoadCompleteListener != null) {
458f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks                        mOnLoadCompleteListener.onLoadComplete(mSoundPool, msg.arg1, msg.arg2);
459f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks                    }
460f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks                }
461f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks                break;
462f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks            default:
463f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks                Log.e(TAG, "Unknown message type " + msg.what);
464f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks                return;
465f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks            }
466f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks        }
467f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks    }
468f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks
469f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks    // post event from native code to message handler
470f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks    private static void postEventFromNative(Object weakRef, int msg, int arg1, int arg2, Object obj)
471f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks    {
472f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks        SoundPool soundPool = (SoundPool)((WeakReference)weakRef).get();
473f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks        if (soundPool == null)
474f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks            return;
475f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks
476f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks        if (soundPool.mEventHandler != null) {
477f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks            Message m = soundPool.mEventHandler.obtainMessage(msg, arg1, arg2, obj);
478f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks            soundPool.mEventHandler.sendMessage(m);
479f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks        }
480f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks    }
481f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks
482f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks    /**
4836cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * Release the SoundPool resources.
4846cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     *
4856cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * Release all memory and native resources used by the SoundPool
4866cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * object. The SoundPool can no longer be used and the reference
4876cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     * should be set to null.
4886cb9900e6f884adb6c9aa0243f2bf88985f671f8Dave Sparks     */
4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public native final void release();
4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
491f6e43bf29084760b39257b2273e0f04c2815fdc5Dave Sparks    private native final int native_setup(Object weakRef, int maxStreams, int streamType, int srcQuality);
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void finalize() { release(); }
4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
495