• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2008 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <stdio.h>
18 
19 //#define LOG_NDEBUG 0
20 #define LOG_TAG "SoundPool"
21 
22 #include <utils/Log.h>
23 #include <nativehelper/jni.h>
24 #include <nativehelper/JNIHelp.h>
25 #include <android_runtime/AndroidRuntime.h>
26 #include "SoundPool.h"
27 
28 using namespace android;
29 
30 static struct fields_t {
31     jfieldID    mNativeContext;
32     jclass      mSoundPoolClass;
33 } fields;
34 
MusterSoundPool(JNIEnv * env,jobject thiz)35 static inline SoundPool* MusterSoundPool(JNIEnv *env, jobject thiz) {
36     return (SoundPool*)env->GetIntField(thiz, fields.mNativeContext);
37 }
38 
39 // ----------------------------------------------------------------------------
40 static int
android_media_SoundPool_load_URL(JNIEnv * env,jobject thiz,jstring path,jint priority)41 android_media_SoundPool_load_URL(JNIEnv *env, jobject thiz, jstring path, jint priority)
42 {
43     LOGV("android_media_SoundPool_load_URL");
44     SoundPool *ap = MusterSoundPool(env, thiz);
45     if (path == NULL) {
46         jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
47         return 0;
48     }
49     const char* s = env->GetStringUTFChars(path, NULL);
50     int id = ap->load(s, priority);
51     env->ReleaseStringUTFChars(path, s);
52     return id;
53 }
54 
55 static int
android_media_SoundPool_load_FD(JNIEnv * env,jobject thiz,jobject fileDescriptor,jlong offset,jlong length,jint priority)56 android_media_SoundPool_load_FD(JNIEnv *env, jobject thiz, jobject fileDescriptor,
57         jlong offset, jlong length, jint priority)
58 {
59     LOGV("android_media_SoundPool_load_FD");
60     SoundPool *ap = MusterSoundPool(env, thiz);
61     if (ap == NULL) return 0;
62     return ap->load(getParcelFileDescriptorFD(env, fileDescriptor),
63             int64_t(offset), int64_t(length), int(priority));
64 }
65 
66 static bool
android_media_SoundPool_unload(JNIEnv * env,jobject thiz,jint sampleID)67 android_media_SoundPool_unload(JNIEnv *env, jobject thiz, jint sampleID) {
68     LOGV("android_media_SoundPool_unload\n");
69     SoundPool *ap = MusterSoundPool(env, thiz);
70     if (ap == NULL) return 0;
71     return ap->unload(sampleID);
72 }
73 
74 static int
android_media_SoundPool_play(JNIEnv * env,jobject thiz,jint sampleID,jfloat leftVolume,jfloat rightVolume,jint priority,jint loop,jfloat rate)75 android_media_SoundPool_play(JNIEnv *env, jobject thiz, jint sampleID,
76         jfloat leftVolume, jfloat rightVolume, jint priority, jint loop,
77         jfloat rate)
78 {
79     LOGV("android_media_SoundPool_play\n");
80     SoundPool *ap = MusterSoundPool(env, thiz);
81     if (ap == NULL) return 0;
82     return ap->play(sampleID, leftVolume, rightVolume, priority, loop, rate);
83 }
84 
85 static void
android_media_SoundPool_pause(JNIEnv * env,jobject thiz,jint channelID)86 android_media_SoundPool_pause(JNIEnv *env, jobject thiz, jint channelID)
87 {
88     LOGV("android_media_SoundPool_pause");
89     SoundPool *ap = MusterSoundPool(env, thiz);
90     if (ap == NULL) return;
91     ap->pause(channelID);
92 }
93 
94 static void
android_media_SoundPool_resume(JNIEnv * env,jobject thiz,jint channelID)95 android_media_SoundPool_resume(JNIEnv *env, jobject thiz, jint channelID)
96 {
97     LOGV("android_media_SoundPool_resume");
98     SoundPool *ap = MusterSoundPool(env, thiz);
99     if (ap == NULL) return;
100     ap->resume(channelID);
101 }
102 
103 static void
android_media_SoundPool_stop(JNIEnv * env,jobject thiz,jint channelID)104 android_media_SoundPool_stop(JNIEnv *env, jobject thiz, jint channelID)
105 {
106     LOGV("android_media_SoundPool_stop");
107     SoundPool *ap = MusterSoundPool(env, thiz);
108     if (ap == NULL) return;
109     ap->stop(channelID);
110 }
111 
112 static void
android_media_SoundPool_setVolume(JNIEnv * env,jobject thiz,jint channelID,float leftVolume,float rightVolume)113 android_media_SoundPool_setVolume(JNIEnv *env, jobject thiz, jint channelID,
114         float leftVolume, float rightVolume)
115 {
116     LOGV("android_media_SoundPool_setVolume");
117     SoundPool *ap = MusterSoundPool(env, thiz);
118     if (ap == NULL) return;
119     ap->setVolume(channelID, leftVolume, rightVolume);
120 }
121 
122 static void
android_media_SoundPool_setPriority(JNIEnv * env,jobject thiz,jint channelID,int priority)123 android_media_SoundPool_setPriority(JNIEnv *env, jobject thiz, jint channelID,
124         int priority)
125 {
126     LOGV("android_media_SoundPool_setPriority");
127     SoundPool *ap = MusterSoundPool(env, thiz);
128     if (ap == NULL) return;
129     ap->setPriority(channelID, priority);
130 }
131 
132 static void
android_media_SoundPool_setLoop(JNIEnv * env,jobject thiz,jint channelID,int loop)133 android_media_SoundPool_setLoop(JNIEnv *env, jobject thiz, jint channelID,
134         int loop)
135 {
136     LOGV("android_media_SoundPool_setLoop");
137     SoundPool *ap = MusterSoundPool(env, thiz);
138     if (ap == NULL) return;
139     ap->setLoop(channelID, loop);
140 }
141 
142 static void
android_media_SoundPool_setRate(JNIEnv * env,jobject thiz,jint channelID,float rate)143 android_media_SoundPool_setRate(JNIEnv *env, jobject thiz, jint channelID,
144         float rate)
145 {
146     LOGV("android_media_SoundPool_setRate");
147     SoundPool *ap = MusterSoundPool(env, thiz);
148     if (ap == NULL) return;
149     ap->setRate(channelID, rate);
150 }
151 
152 static void
android_media_SoundPool_native_setup(JNIEnv * env,jobject thiz,jobject weak_this,jint maxChannels,jint streamType,jint srcQuality)153 android_media_SoundPool_native_setup(JNIEnv *env, jobject thiz,
154         jobject weak_this, jint maxChannels, jint streamType, jint srcQuality)
155 {
156     LOGV("android_media_SoundPool_native_setup");
157     SoundPool *ap = new SoundPool(weak_this, maxChannels, streamType, srcQuality);
158     if (ap == NULL) {
159         jniThrowException(env, "java/lang/RuntimeException", "Out of memory");
160         return;
161     }
162 
163     // save pointer to SoundPool C++ object in opaque field in Java object
164     env->SetIntField(thiz, fields.mNativeContext, (int)ap);
165 }
166 
167 static void
android_media_SoundPool_release(JNIEnv * env,jobject thiz)168 android_media_SoundPool_release(JNIEnv *env, jobject thiz)
169 {
170     LOGV("android_media_SoundPool_release");
171     SoundPool *ap = MusterSoundPool(env, thiz);
172     if (ap != NULL) {
173         env->SetIntField(thiz, fields.mNativeContext, 0);
174         delete ap;
175     }
176 }
177 
178 // ----------------------------------------------------------------------------
179 
180 // Dalvik VM type signatures
181 static JNINativeMethod gMethods[] = {
182     {   "_load",
183         "(Ljava/lang/String;I)I",
184         (void *)android_media_SoundPool_load_URL
185     },
186     {   "_load",
187         "(Ljava/io/FileDescriptor;JJI)I",
188         (void *)android_media_SoundPool_load_FD
189     },
190     {   "unload",
191         "(I)Z",
192         (void *)android_media_SoundPool_unload
193     },
194     {   "play",
195         "(IFFIIF)I",
196         (void *)android_media_SoundPool_play
197     },
198     {   "pause",
199         "(I)V",
200         (void *)android_media_SoundPool_pause
201     },
202     {   "resume",
203         "(I)V",
204         (void *)android_media_SoundPool_resume
205     },
206     {   "stop",
207         "(I)V",
208         (void *)android_media_SoundPool_stop
209     },
210     {   "setVolume",
211         "(IFF)V",
212         (void *)android_media_SoundPool_setVolume
213     },
214     {   "setPriority",
215         "(II)V",
216         (void *)android_media_SoundPool_setPriority
217     },
218     {   "setLoop",
219         "(II)V",
220         (void *)android_media_SoundPool_setLoop
221     },
222     {   "setRate",
223         "(IF)V",
224         (void *)android_media_SoundPool_setRate
225     },
226     {   "native_setup",
227         "(Ljava/lang/Object;III)V",
228         (void*)android_media_SoundPool_native_setup
229     },
230     {   "release",
231         "()V",
232         (void*)android_media_SoundPool_release
233     }
234 };
235 
236 static const char* const kClassPathName = "android/media/SoundPool";
237 
JNI_OnLoad(JavaVM * vm,void * reserved)238 jint JNI_OnLoad(JavaVM* vm, void* reserved)
239 {
240     JNIEnv* env = NULL;
241     jint result = -1;
242     jclass clazz;
243 
244     if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
245         LOGE("ERROR: GetEnv failed\n");
246         goto bail;
247     }
248     assert(env != NULL);
249 
250     clazz = env->FindClass(kClassPathName);
251     if (clazz == NULL) {
252         LOGE("Can't find %s", kClassPathName);
253         goto bail;
254     }
255 
256     fields.mNativeContext = env->GetFieldID(clazz, "mNativeContext", "I");
257     if (fields.mNativeContext == NULL) {
258         LOGE("Can't find SoundPool.mNativeContext");
259         goto bail;
260     }
261 
262     if (AndroidRuntime::registerNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods)) < 0)
263         goto bail;
264 
265     /* success -- return valid version number */
266     result = JNI_VERSION_1_4;
267 
268 bail:
269     return result;
270 }
271