1 /* 2 * Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 //#define USE_TRACE 27 #define USE_ERROR 28 29 30 #include <jni.h> 31 #include <jni_util.h> 32 #include "SoundDefs.h" 33 #include "Ports.h" 34 #include "Utilities.h" 35 #include "com_sun_media_sound_PortMixer.h" 36 37 38 //////////////////////////////////////////// PortMixer //////////////////////////////////////////// 39 40 JNIEXPORT jlong JNICALL Java_com_sun_media_sound_PortMixer_nOpen 41 (JNIEnv *env, jclass cls, jint mixerIndex) { 42 43 jlong ret = 0; 44 #if USE_PORTS == TRUE 45 ret = (jlong) (INT_PTR) PORT_Open(mixerIndex); 46 #endif 47 return ret; 48 } 49 50 JNIEXPORT void JNICALL Java_com_sun_media_sound_PortMixer_nClose 51 (JNIEnv *env, jclass cls, jlong id) { 52 53 #if USE_PORTS == TRUE 54 if (id != 0) { 55 PORT_Close((void*) (INT_PTR) id); 56 } 57 #endif 58 } 59 60 JNIEXPORT jint JNICALL Java_com_sun_media_sound_PortMixer_nGetPortCount 61 (JNIEnv *env, jclass cls, jlong id) { 62 63 jint ret = 0; 64 #if USE_PORTS == TRUE 65 if (id != 0) { 66 ret = (jint) PORT_GetPortCount((void*) (INT_PTR) id); 67 } 68 #endif 69 return ret; 70 } 71 72 73 JNIEXPORT jint JNICALL Java_com_sun_media_sound_PortMixer_nGetPortType 74 (JNIEnv *env, jclass cls, jlong id, jint portIndex) { 75 76 jint ret = 0; 77 TRACE1("Java_com_sun_media_sound_PortMixer_nGetPortType(%d).\n", portIndex); 78 79 #if USE_PORTS == TRUE 80 if (id != 0) { 81 ret = (jint) PORT_GetPortType((void*) (INT_PTR) id, portIndex); 82 } 83 #endif 84 85 TRACE1("Java_com_sun_media_sound_PortMixerProvider_nGetPortType returning %d.\n", ret); 86 return ret; 87 } 88 89 JNIEXPORT jstring JNICALL Java_com_sun_media_sound_PortMixer_nGetPortName 90 (JNIEnv *env, jclass cls, jlong id, jint portIndex) { 91 92 char str[PORT_STRING_LENGTH]; 93 jstring jString = NULL; 94 TRACE1("Java_com_sun_media_sound_PortMixer_nGetPortName(%d).\n", portIndex); 95 96 str[0] = 0; 97 #if USE_PORTS == TRUE 98 if (id != 0) { 99 PORT_GetPortName((void*) (INT_PTR) id, portIndex, str, PORT_STRING_LENGTH); 100 } 101 #endif 102 jString = (*env)->NewStringUTF(env, str); 103 104 TRACE1("Java_com_sun_media_sound_PortMixerProvider_nGetName returning \"%s\".\n", str); 105 return jString; 106 } 107 108 JNIEXPORT void JNICALL Java_com_sun_media_sound_PortMixer_nControlSetIntValue 109 (JNIEnv *env, jclass cls, jlong controlID, jint value) { 110 #if USE_PORTS == TRUE 111 if (controlID != 0) { 112 PORT_SetIntValue((void*) (UINT_PTR) controlID, (INT32) value); 113 } 114 #endif 115 } 116 117 JNIEXPORT jint JNICALL Java_com_sun_media_sound_PortMixer_nControlGetIntValue 118 (JNIEnv *env, jclass cls, jlong controlID) { 119 INT32 ret = 0; 120 #if USE_PORTS == TRUE 121 if (controlID != 0) { 122 ret = PORT_GetIntValue((void*) (UINT_PTR) controlID); 123 } 124 #endif 125 return (jint) ret; 126 } 127 128 JNIEXPORT void JNICALL Java_com_sun_media_sound_PortMixer_nControlSetFloatValue 129 (JNIEnv *env, jclass cls, jlong controlID, jfloat value) { 130 #if USE_PORTS == TRUE 131 if (controlID != 0) { 132 PORT_SetFloatValue((void*) (UINT_PTR) controlID, (float) value); 133 } 134 #endif 135 } 136 137 JNIEXPORT jfloat JNICALL Java_com_sun_media_sound_PortMixer_nControlGetFloatValue 138 (JNIEnv *env, jclass cls, jlong controlID) { 139 float ret = 0; 140 #if USE_PORTS == TRUE 141 if (controlID != 0) { 142 ret = PORT_GetFloatValue((void*) (UINT_PTR) controlID); 143 } 144 #endif 145 return (jfloat) ret; 146 } 147 148 /* ************************************** native control creation support ********************* */ 149 150 // contains all the needed references so that the platform dependent code can call JNI wrapper functions 151 typedef struct tag_ControlCreatorJNI { 152 // this member is seen by the platform dependent code 153 PortControlCreator creator; 154 // general JNI variables 155 JNIEnv *env; 156 // the vector to be filled with controls (initialized before usage) 157 jobject vector; 158 jmethodID vectorAddElement; 159 // control specific constructors (initialized on demand) 160 jclass boolCtrlClass; 161 jmethodID boolCtrlConstructor; // signature (JLjava/lang/String;)V 162 jclass controlClass; // class of javax.sound.sampled.Control 163 jclass compCtrlClass; 164 jmethodID compCtrlConstructor; // signature (Ljava/lang/String;[Ljavax/sound/sampled/Control;)V 165 jclass floatCtrlClass; 166 jmethodID floatCtrlConstructor1; // signature (JLjava/lang/String;FFFLjava/lang/String;)V 167 jmethodID floatCtrlConstructor2; // signature (JIFFFLjava/lang/String;)V 168 } ControlCreatorJNI; 169 170 171 void* PORT_NewBooleanControl(void* creatorV, void* controlID, char* type) { 172 ControlCreatorJNI* creator = (ControlCreatorJNI*) creatorV; 173 jobject ctrl = NULL; 174 jstring typeString; 175 176 #ifdef USE_TRACE 177 if (((UINT_PTR) type) <= CONTROL_TYPE_MAX) { 178 TRACE1("PORT_NewBooleanControl: creating '%d'\n", (int) (UINT_PTR) type); 179 } else { 180 TRACE1("PORT_NewBooleanControl: creating '%s'\n", type); 181 } 182 #endif 183 if (!creator->boolCtrlClass) { 184 // retrieve class and constructor of PortMixer.BoolCtrl 185 creator->boolCtrlClass = (*creator->env)->FindClass(creator->env, IMPLEMENTATION_PACKAGE_NAME"/PortMixer$BoolCtrl"); 186 if (!creator->boolCtrlClass) { 187 ERROR0("PORT_NewBooleanControl: boolCtrlClass is NULL\n"); 188 return NULL; 189 } 190 creator->boolCtrlConstructor = (*creator->env)->GetMethodID(creator->env, creator->boolCtrlClass, 191 "<init>", "(JLjava/lang/String;)V"); 192 if (!creator->boolCtrlConstructor) { 193 ERROR0("PORT_NewBooleanControl: boolCtrlConstructor is NULL\n"); 194 return NULL; 195 } 196 } 197 if (type == CONTROL_TYPE_MUTE) { 198 type = "Mute"; 199 } 200 else if (type == CONTROL_TYPE_SELECT) { 201 type = "Select"; 202 } 203 204 typeString = (*creator->env)->NewStringUTF(creator->env, type); 205 CHECK_NULL_RETURN(typeString, (void*) ctrl); 206 ctrl = (*creator->env)->NewObject(creator->env, creator->boolCtrlClass, 207 creator->boolCtrlConstructor, 208 (jlong) (UINT_PTR) controlID, typeString); 209 if (!ctrl) { 210 ERROR0("PORT_NewBooleanControl: ctrl is NULL\n"); 211 } 212 if ((*creator->env)->ExceptionOccurred(creator->env)) { 213 ERROR0("PORT_NewBooleanControl: ExceptionOccurred!\n"); 214 } 215 TRACE0("PORT_NewBooleanControl succeeded\n"); 216 return (void*) ctrl; 217 } 218 219 void* PORT_NewCompoundControl(void* creatorV, char* type, void** controls, int controlCount) { 220 ControlCreatorJNI* creator = (ControlCreatorJNI*) creatorV; 221 jobject ctrl = NULL; 222 jobjectArray controlArray; 223 int i; 224 jstring typeString; 225 226 TRACE2("PORT_NewCompoundControl: creating '%s' with %d controls\n", type, controlCount); 227 if (!creator->compCtrlClass) { 228 TRACE0("PORT_NewCompoundControl: retrieve method ids\n"); 229 // retrieve class and constructor of PortMixer.BoolCtrl 230 creator->compCtrlClass = (*creator->env)->FindClass(creator->env, IMPLEMENTATION_PACKAGE_NAME"/PortMixer$CompCtrl"); 231 if (!creator->compCtrlClass) { 232 ERROR0("PORT_NewCompoundControl: compCtrlClass is NULL\n"); 233 return NULL; 234 } 235 creator->compCtrlConstructor = (*creator->env)->GetMethodID(creator->env, creator->compCtrlClass, 236 "<init>", "(Ljava/lang/String;[Ljavax/sound/sampled/Control;)V"); 237 if (!creator->compCtrlConstructor) { 238 ERROR0("PORT_NewCompoundControl: compCtrlConstructor is NULL\n"); 239 return NULL; 240 } 241 creator->controlClass = (*creator->env)->FindClass(creator->env, JAVA_SAMPLED_PACKAGE_NAME"/Control"); 242 if (!creator->controlClass) { 243 ERROR0("PORT_NewCompoundControl: controlClass is NULL\n"); 244 return NULL; 245 } 246 } 247 TRACE0("PORT_NewCompoundControl: creating array\n"); 248 // create new array for the controls 249 controlArray = (*creator->env)->NewObjectArray(creator->env, controlCount, creator->controlClass, (jobject) NULL); 250 if (!controlArray) { 251 ERROR0("PORT_NewCompoundControl: controlArray is NULL\n"); 252 return NULL; 253 } 254 TRACE0("PORT_NewCompoundControl: setting array values\n"); 255 for (i = 0; i < controlCount; i++) { 256 (*creator->env)->SetObjectArrayElement(creator->env, controlArray, i, (jobject) controls[i]); 257 } 258 TRACE0("PORT_NewCompoundControl: creating compound control\n"); 259 typeString = (*creator->env)->NewStringUTF(creator->env, type); 260 CHECK_NULL_RETURN(typeString, (void*) ctrl); 261 ctrl = (*creator->env)->NewObject(creator->env, creator->compCtrlClass, 262 creator->compCtrlConstructor, 263 typeString, controlArray); 264 if (!ctrl) { 265 ERROR0("PORT_NewCompoundControl: ctrl is NULL\n"); 266 } 267 if ((*creator->env)->ExceptionOccurred(creator->env)) { 268 ERROR0("PORT_NewCompoundControl: ExceptionOccurred!\n"); 269 } 270 TRACE0("PORT_NewCompoundControl succeeded\n"); 271 return (void*) ctrl; 272 } 273 274 void* PORT_NewFloatControl(void* creatorV, void* controlID, char* type, 275 float min, float max, float precision, const char* units) { 276 ControlCreatorJNI* creator = (ControlCreatorJNI*) creatorV; 277 jobject ctrl = NULL; 278 jstring unitsString; 279 jstring typeString; 280 281 #ifdef USE_TRACE 282 if (((UINT_PTR) type) <= CONTROL_TYPE_MAX) { 283 TRACE1("PORT_NewFloatControl: creating '%d'\n", (int) (UINT_PTR) type); 284 } else { 285 TRACE1("PORT_NewFloatControl: creating '%s'\n", type); 286 } 287 #endif 288 if (!creator->floatCtrlClass) { 289 // retrieve class and constructor of PortMixer.BoolCtrl 290 creator->floatCtrlClass = (*creator->env)->FindClass(creator->env, IMPLEMENTATION_PACKAGE_NAME"/PortMixer$FloatCtrl"); 291 if (!creator->floatCtrlClass) { 292 ERROR0("PORT_NewFloatControl: floatCtrlClass is NULL\n"); 293 return NULL; 294 } 295 creator->floatCtrlConstructor1 = (*creator->env)->GetMethodID(creator->env, creator->floatCtrlClass, 296 "<init>", "(JLjava/lang/String;FFFLjava/lang/String;)V"); 297 if (!creator->floatCtrlConstructor1) { 298 ERROR0("PORT_NewFloatControl: floatCtrlConstructor1 is NULL\n"); 299 return NULL; 300 } 301 creator->floatCtrlConstructor2 = (*creator->env)->GetMethodID(creator->env, creator->floatCtrlClass, 302 "<init>", "(JIFFFLjava/lang/String;)V"); 303 if (!creator->floatCtrlConstructor2) { 304 ERROR0("PORT_NewFloatControl: floatCtrlConstructor2 is NULL\n"); 305 return NULL; 306 } 307 } 308 unitsString = (*creator->env)->NewStringUTF(creator->env, units); 309 CHECK_NULL_RETURN(unitsString, (void*) ctrl); 310 if (((UINT_PTR) type) <= CONTROL_TYPE_MAX) { 311 // constructor with int parameter 312 TRACE1("PORT_NewFloatControl: calling constructor2 with type %d\n", (int) (UINT_PTR) type); 313 ctrl = (*creator->env)->NewObject(creator->env, creator->floatCtrlClass, 314 creator->floatCtrlConstructor2, 315 (jlong) (UINT_PTR) controlID, (jint) (UINT_PTR) type, 316 min, max, precision, unitsString); 317 } else { 318 TRACE0("PORT_NewFloatControl: calling constructor1\n"); 319 // constructor with string parameter 320 typeString = (*creator->env)->NewStringUTF(creator->env, type); 321 CHECK_NULL_RETURN(typeString, (void*) ctrl); 322 ctrl = (*creator->env)->NewObject(creator->env, creator->floatCtrlClass, 323 creator->floatCtrlConstructor1, 324 (jlong) (UINT_PTR) controlID, typeString, 325 min, max, precision, unitsString); 326 } 327 if (!ctrl) { 328 ERROR0("PORT_NewFloatControl: ctrl is NULL!\n"); 329 } 330 if ((*creator->env)->ExceptionOccurred(creator->env)) { 331 ERROR0("PORT_NewFloatControl: ExceptionOccurred!\n"); 332 } 333 TRACE1("PORT_NewFloatControl succeeded %p\n", (void*) ctrl); 334 return (void*) ctrl; 335 } 336 337 int PORT_AddControl(void* creatorV, void* control) { 338 ControlCreatorJNI* creator = (ControlCreatorJNI*) creatorV; 339 340 TRACE1("PORT_AddControl %p\n", (void*) control); 341 (*creator->env)->CallVoidMethod(creator->env, creator->vector, creator->vectorAddElement, (jobject) control); 342 if ((*creator->env)->ExceptionOccurred(creator->env)) { 343 ERROR0("PORT_AddControl: ExceptionOccurred!\n"); 344 } 345 TRACE0("PORT_AddControl succeeded\n"); 346 return TRUE; 347 } 348 349 JNIEXPORT void JNICALL Java_com_sun_media_sound_PortMixer_nGetControls 350 (JNIEnv *env, jclass cls, jlong id, jint portIndex, jobject vector) { 351 352 ControlCreatorJNI creator; 353 jclass vectorClass; 354 355 #if USE_PORTS == TRUE 356 if (id != 0) { 357 memset(&creator, 0, sizeof(ControlCreatorJNI)); 358 creator.creator.newBooleanControl = &PORT_NewBooleanControl; 359 creator.creator.newCompoundControl = &PORT_NewCompoundControl; 360 creator.creator.newFloatControl = &PORT_NewFloatControl; 361 creator.creator.addControl = &PORT_AddControl; 362 creator.env = env; 363 vectorClass = (*env)->GetObjectClass(env, vector); 364 if (vectorClass == NULL) { 365 ERROR0("Java_com_sun_media_sound_PortMixer_nGetControls: vectorClass is NULL\n"); 366 return; 367 } 368 creator.vector = vector; 369 creator.vectorAddElement = (*env)->GetMethodID(env, vectorClass, "addElement", "(Ljava/lang/Object;)V"); 370 if (creator.vectorAddElement == NULL) { 371 ERROR0("Java_com_sun_media_sound_PortMixer_nGetControls: addElementMethodID is NULL\n"); 372 return; 373 } 374 PORT_GetControls((void*) (UINT_PTR) id, (INT32) portIndex, (PortControlCreator*) &creator); 375 } 376 #endif 377 }