PageRenderTime 619ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/media/jni/soundpool/android_media_SoundPool.cpp

https://gitlab.com/drgroovestarr/frameworks_base
C++ | 371 lines | 299 code | 42 blank | 30 comment | 55 complexity | c5150c02174d8d767709825546e266e8 MD5 | raw file
  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. #include <stdio.h>
  17. //#define LOG_NDEBUG 0
  18. #define LOG_TAG "SoundPool-JNI"
  19. #include <utils/Log.h>
  20. #include <jni.h>
  21. #include <nativehelper/JNIHelp.h>
  22. #include <android_runtime/AndroidRuntime.h>
  23. #include "SoundPool.h"
  24. using namespace android;
  25. static struct fields_t {
  26. jfieldID mNativeContext;
  27. jmethodID mPostEvent;
  28. jclass mSoundPoolClass;
  29. } fields;
  30. static inline SoundPool* MusterSoundPool(JNIEnv *env, jobject thiz) {
  31. return (SoundPool*)env->GetLongField(thiz, fields.mNativeContext);
  32. }
  33. static const char* const kAudioAttributesClassPathName = "android/media/AudioAttributes";
  34. struct audio_attributes_fields_t {
  35. jfieldID fieldUsage; // AudioAttributes.mUsage
  36. jfieldID fieldContentType; // AudioAttributes.mContentType
  37. jfieldID fieldFlags; // AudioAttributes.mFlags
  38. jfieldID fieldFormattedTags;// AudioAttributes.mFormattedTags
  39. };
  40. static audio_attributes_fields_t javaAudioAttrFields;
  41. // ----------------------------------------------------------------------------
  42. static jint
  43. android_media_SoundPool_load_FD(JNIEnv *env, jobject thiz, jobject fileDescriptor,
  44. jlong offset, jlong length, jint priority)
  45. {
  46. ALOGV("android_media_SoundPool_load_FD");
  47. SoundPool *ap = MusterSoundPool(env, thiz);
  48. if (ap == NULL) return 0;
  49. return (jint) ap->load(jniGetFDFromFileDescriptor(env, fileDescriptor),
  50. int64_t(offset), int64_t(length), int(priority));
  51. }
  52. static jboolean
  53. android_media_SoundPool_unload(JNIEnv *env, jobject thiz, jint sampleID) {
  54. ALOGV("android_media_SoundPool_unload\n");
  55. SoundPool *ap = MusterSoundPool(env, thiz);
  56. if (ap == NULL) return JNI_FALSE;
  57. return ap->unload(sampleID) ? JNI_TRUE : JNI_FALSE;
  58. }
  59. static jint
  60. android_media_SoundPool_play(JNIEnv *env, jobject thiz, jint sampleID,
  61. jfloat leftVolume, jfloat rightVolume, jint priority, jint loop,
  62. jfloat rate)
  63. {
  64. ALOGV("android_media_SoundPool_play\n");
  65. SoundPool *ap = MusterSoundPool(env, thiz);
  66. if (ap == NULL) return 0;
  67. return (jint) ap->play(sampleID, leftVolume, rightVolume, priority, loop, rate);
  68. }
  69. static void
  70. android_media_SoundPool_pause(JNIEnv *env, jobject thiz, jint channelID)
  71. {
  72. ALOGV("android_media_SoundPool_pause");
  73. SoundPool *ap = MusterSoundPool(env, thiz);
  74. if (ap == NULL) return;
  75. ap->pause(channelID);
  76. }
  77. static void
  78. android_media_SoundPool_resume(JNIEnv *env, jobject thiz, jint channelID)
  79. {
  80. ALOGV("android_media_SoundPool_resume");
  81. SoundPool *ap = MusterSoundPool(env, thiz);
  82. if (ap == NULL) return;
  83. ap->resume(channelID);
  84. }
  85. static void
  86. android_media_SoundPool_autoPause(JNIEnv *env, jobject thiz)
  87. {
  88. ALOGV("android_media_SoundPool_autoPause");
  89. SoundPool *ap = MusterSoundPool(env, thiz);
  90. if (ap == NULL) return;
  91. ap->autoPause();
  92. }
  93. static void
  94. android_media_SoundPool_autoResume(JNIEnv *env, jobject thiz)
  95. {
  96. ALOGV("android_media_SoundPool_autoResume");
  97. SoundPool *ap = MusterSoundPool(env, thiz);
  98. if (ap == NULL) return;
  99. ap->autoResume();
  100. }
  101. static void
  102. android_media_SoundPool_stop(JNIEnv *env, jobject thiz, jint channelID)
  103. {
  104. ALOGV("android_media_SoundPool_stop");
  105. SoundPool *ap = MusterSoundPool(env, thiz);
  106. if (ap == NULL) return;
  107. ap->stop(channelID);
  108. }
  109. static void
  110. android_media_SoundPool_setVolume(JNIEnv *env, jobject thiz, jint channelID,
  111. jfloat leftVolume, jfloat rightVolume)
  112. {
  113. ALOGV("android_media_SoundPool_setVolume");
  114. SoundPool *ap = MusterSoundPool(env, thiz);
  115. if (ap == NULL) return;
  116. ap->setVolume(channelID, (float) leftVolume, (float) rightVolume);
  117. }
  118. static void
  119. android_media_SoundPool_mute(JNIEnv *env, jobject thiz, jboolean muting)
  120. {
  121. ALOGV("android_media_SoundPool_mute(%d)", muting);
  122. SoundPool *ap = MusterSoundPool(env, thiz);
  123. if (ap == NULL) return;
  124. ap->mute(muting == JNI_TRUE);
  125. }
  126. static void
  127. android_media_SoundPool_setPriority(JNIEnv *env, jobject thiz, jint channelID,
  128. jint priority)
  129. {
  130. ALOGV("android_media_SoundPool_setPriority");
  131. SoundPool *ap = MusterSoundPool(env, thiz);
  132. if (ap == NULL) return;
  133. ap->setPriority(channelID, (int) priority);
  134. }
  135. static void
  136. android_media_SoundPool_setLoop(JNIEnv *env, jobject thiz, jint channelID,
  137. int loop)
  138. {
  139. ALOGV("android_media_SoundPool_setLoop");
  140. SoundPool *ap = MusterSoundPool(env, thiz);
  141. if (ap == NULL) return;
  142. ap->setLoop(channelID, loop);
  143. }
  144. static void
  145. android_media_SoundPool_setRate(JNIEnv *env, jobject thiz, jint channelID,
  146. jfloat rate)
  147. {
  148. ALOGV("android_media_SoundPool_setRate");
  149. SoundPool *ap = MusterSoundPool(env, thiz);
  150. if (ap == NULL) return;
  151. ap->setRate(channelID, (float) rate);
  152. }
  153. static void android_media_callback(SoundPoolEvent event, SoundPool* soundPool, void* user)
  154. {
  155. ALOGV("callback: (%d, %d, %d, %p, %p)", event.mMsg, event.mArg1, event.mArg2, soundPool, user);
  156. JNIEnv *env = AndroidRuntime::getJNIEnv();
  157. env->CallStaticVoidMethod(fields.mSoundPoolClass, fields.mPostEvent, user, event.mMsg, event.mArg1, event.mArg2, NULL);
  158. }
  159. static jint
  160. android_media_SoundPool_native_setup(JNIEnv *env, jobject thiz, jobject weakRef,
  161. jint maxChannels, jobject jaa)
  162. {
  163. if (jaa == 0) {
  164. ALOGE("Error creating SoundPool: invalid audio attributes");
  165. return -1;
  166. }
  167. audio_attributes_t *paa = NULL;
  168. // read the AudioAttributes values
  169. paa = (audio_attributes_t *) calloc(1, sizeof(audio_attributes_t));
  170. const jstring jtags =
  171. (jstring) env->GetObjectField(jaa, javaAudioAttrFields.fieldFormattedTags);
  172. const char* tags = env->GetStringUTFChars(jtags, NULL);
  173. // copying array size -1, char array for tags was calloc'd, no need to NULL-terminate it
  174. strncpy(paa->tags, tags, AUDIO_ATTRIBUTES_TAGS_MAX_SIZE - 1);
  175. env->ReleaseStringUTFChars(jtags, tags);
  176. paa->usage = (audio_usage_t) env->GetIntField(jaa, javaAudioAttrFields.fieldUsage);
  177. paa->content_type =
  178. (audio_content_type_t) env->GetIntField(jaa, javaAudioAttrFields.fieldContentType);
  179. paa->flags = env->GetIntField(jaa, javaAudioAttrFields.fieldFlags);
  180. ALOGV("android_media_SoundPool_native_setup");
  181. SoundPool *ap = new SoundPool(maxChannels, paa);
  182. if (ap == NULL) {
  183. return -1;
  184. }
  185. // save pointer to SoundPool C++ object in opaque field in Java object
  186. env->SetLongField(thiz, fields.mNativeContext, (jlong) ap);
  187. // set callback with weak reference
  188. jobject globalWeakRef = env->NewGlobalRef(weakRef);
  189. ap->setCallback(android_media_callback, globalWeakRef);
  190. // audio attributes were copied in SoundPool creation
  191. free(paa);
  192. return 0;
  193. }
  194. static void
  195. android_media_SoundPool_release(JNIEnv *env, jobject thiz)
  196. {
  197. ALOGV("android_media_SoundPool_release");
  198. SoundPool *ap = MusterSoundPool(env, thiz);
  199. if (ap != NULL) {
  200. // release weak reference and clear callback
  201. jobject weakRef = (jobject) ap->getUserData();
  202. ap->setCallback(NULL, NULL);
  203. if (weakRef != NULL) {
  204. env->DeleteGlobalRef(weakRef);
  205. }
  206. // clear native context
  207. env->SetLongField(thiz, fields.mNativeContext, 0);
  208. delete ap;
  209. }
  210. }
  211. // ----------------------------------------------------------------------------
  212. // Dalvik VM type signatures
  213. static JNINativeMethod gMethods[] = {
  214. { "_load",
  215. "(Ljava/io/FileDescriptor;JJI)I",
  216. (void *)android_media_SoundPool_load_FD
  217. },
  218. { "unload",
  219. "(I)Z",
  220. (void *)android_media_SoundPool_unload
  221. },
  222. { "_play",
  223. "(IFFIIF)I",
  224. (void *)android_media_SoundPool_play
  225. },
  226. { "pause",
  227. "(I)V",
  228. (void *)android_media_SoundPool_pause
  229. },
  230. { "resume",
  231. "(I)V",
  232. (void *)android_media_SoundPool_resume
  233. },
  234. { "autoPause",
  235. "()V",
  236. (void *)android_media_SoundPool_autoPause
  237. },
  238. { "autoResume",
  239. "()V",
  240. (void *)android_media_SoundPool_autoResume
  241. },
  242. { "stop",
  243. "(I)V",
  244. (void *)android_media_SoundPool_stop
  245. },
  246. { "_setVolume",
  247. "(IFF)V",
  248. (void *)android_media_SoundPool_setVolume
  249. },
  250. { "_mute",
  251. "(Z)V",
  252. (void *)android_media_SoundPool_mute
  253. },
  254. { "setPriority",
  255. "(II)V",
  256. (void *)android_media_SoundPool_setPriority
  257. },
  258. { "setLoop",
  259. "(II)V",
  260. (void *)android_media_SoundPool_setLoop
  261. },
  262. { "setRate",
  263. "(IF)V",
  264. (void *)android_media_SoundPool_setRate
  265. },
  266. { "native_setup",
  267. "(Ljava/lang/Object;ILjava/lang/Object;)I",
  268. (void*)android_media_SoundPool_native_setup
  269. },
  270. { "native_release",
  271. "()V",
  272. (void*)android_media_SoundPool_release
  273. }
  274. };
  275. static const char* const kClassPathName = "android/media/SoundPool";
  276. jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
  277. {
  278. JNIEnv* env = NULL;
  279. jint result = -1;
  280. jclass clazz;
  281. if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
  282. ALOGE("ERROR: GetEnv failed\n");
  283. return result;
  284. }
  285. assert(env != NULL);
  286. clazz = env->FindClass(kClassPathName);
  287. if (clazz == NULL) {
  288. ALOGE("Can't find %s", kClassPathName);
  289. return result;
  290. }
  291. fields.mNativeContext = env->GetFieldID(clazz, "mNativeContext", "J");
  292. if (fields.mNativeContext == NULL) {
  293. ALOGE("Can't find SoundPool.mNativeContext");
  294. return result;
  295. }
  296. fields.mPostEvent = env->GetStaticMethodID(clazz, "postEventFromNative",
  297. "(Ljava/lang/Object;IIILjava/lang/Object;)V");
  298. if (fields.mPostEvent == NULL) {
  299. ALOGE("Can't find android/media/SoundPool.postEventFromNative");
  300. return result;
  301. }
  302. // create a reference to class. Technically, we're leaking this reference
  303. // since it's a static object.
  304. fields.mSoundPoolClass = (jclass) env->NewGlobalRef(clazz);
  305. if (AndroidRuntime::registerNativeMethods(env, kClassPathName, gMethods, NELEM(gMethods)) < 0)
  306. return result;
  307. // Get the AudioAttributes class and fields
  308. jclass audioAttrClass = env->FindClass(kAudioAttributesClassPathName);
  309. if (audioAttrClass == NULL) {
  310. ALOGE("Can't find %s", kAudioAttributesClassPathName);
  311. return result;
  312. }
  313. jclass audioAttributesClassRef = (jclass)env->NewGlobalRef(audioAttrClass);
  314. javaAudioAttrFields.fieldUsage = env->GetFieldID(audioAttributesClassRef, "mUsage", "I");
  315. javaAudioAttrFields.fieldContentType
  316. = env->GetFieldID(audioAttributesClassRef, "mContentType", "I");
  317. javaAudioAttrFields.fieldFlags = env->GetFieldID(audioAttributesClassRef, "mFlags", "I");
  318. javaAudioAttrFields.fieldFormattedTags =
  319. env->GetFieldID(audioAttributesClassRef, "mFormattedTags", "Ljava/lang/String;");
  320. env->DeleteGlobalRef(audioAttributesClassRef);
  321. if (javaAudioAttrFields.fieldUsage == NULL || javaAudioAttrFields.fieldContentType == NULL
  322. || javaAudioAttrFields.fieldFlags == NULL
  323. || javaAudioAttrFields.fieldFormattedTags == NULL) {
  324. ALOGE("Can't initialize AudioAttributes fields");
  325. return result;
  326. }
  327. /* success -- return valid version number */
  328. return JNI_VERSION_1_4;
  329. }