📄 org_tritonus_lowlevel_alsa_asequencer0.c
字号:
/* * org_tritonus_lowlevel_alsa_ASequencer0.c */#include <errno.h>#include <string.h>#include <sys/asoundlib.h>#include "org_tritonus_lowlevel_alsa_ASequencer0.h"static voidsendEvent(JNIEnv *env, snd_seq_t* seq, snd_seq_event_t* pEvent);static voidthrowRuntimeException(JNIEnv *env, char* pStrMessage){ static jclass runtimeExceptionClass = NULL; if (runtimeExceptionClass == NULL) { runtimeExceptionClass = (*env)->FindClass(env, "java/lang/RuntimeException"); if (runtimeExceptionClass == NULL) { (*env)->FatalError(env, "cannot get class object for java.lang.RuntimeException"); } } (*env)->ThrowNew(env, runtimeExceptionClass, pStrMessage);}static jfieldIDgetNativeSeqFieldID(JNIEnv *env){ static jfieldID nativeSeqFieldID = NULL; // printf("hallo\n"); if (nativeSeqFieldID == NULL) { // TODO: use a passed object rather than the name of the class jclass cls = (*env)->FindClass(env, "org/tritonus/lowlevel/alsa/ASequencer0"); if (cls == NULL) { throwRuntimeException(env, "cannot get class object for org.tritonus.lowlevel.alsa.ASequencer0"); } nativeSeqFieldID = (*env)->GetFieldID(env, cls, "m_lNativeSeq", "J"); if (nativeSeqFieldID == NULL) { throwRuntimeException(env, "cannot get field ID for m_lNativeSeq of class Seq"); } } return nativeSeqFieldID;}static snd_seq_t*getNativeSeq(JNIEnv *env, jobject obj){ jfieldID fieldID = getNativeSeqFieldID(env); return (snd_seq_t*) (*env)->GetLongField(env, obj, fieldID);}static voidsetNativeSeq(JNIEnv *env, jobject obj, snd_seq_t* seq){ jfieldID fieldID = getNativeSeqFieldID(env); (*env)->SetLongField(env, obj, fieldID, (jlong) seq);}/* * Class: org_tritonus_lowlevel_alsa_ASequencer0 * Method: allocQueue * Signature: ()I */JNIEXPORT jint JNICALL Java_org_tritonus_lowlevel_alsa_ASequencer0_allocQueue(JNIEnv *env, jobject obj){ snd_seq_t* seq = getNativeSeq(env, obj); int nQueue = snd_seq_alloc_queue(seq); if (nQueue < 0) { throwRuntimeException(env, "snd_seq_alloc_queue failed"); } return (jint) nQueue;}/* * Class: org_tritonus_lowlevel_alsa_ASequencer0 * Method: close * Signature: ()V */JNIEXPORT void JNICALL Java_org_tritonus_lowlevel_alsa_ASequencer0_close (JNIEnv *env, jobject obj){ snd_seq_t* seq = getNativeSeq(env, obj); int nReturn = snd_seq_close(seq); if (nReturn < 0) { throwRuntimeException(env, "snd_seq_close failed"); }}/* * Class: org_tritonus_lowlevel_alsa_ASequencer0 * Method: createPort * Signature: (Ljava/lang/String;IIIIII)I */JNIEXPORT jint JNICALL Java_org_tritonus_lowlevel_alsa_ASequencer0_createPort(JNIEnv *env, jobject obj, jstring strName, jint nCapabilities, jint nGroupPermissions, jint nType, jint nMidiChannels, jint nMidiVoices, jint nSynthVoices){ snd_seq_t* seq = getNativeSeq(env, obj); snd_seq_port_info_t portInfo; const char* name; int nReturn; memset(&portInfo, 0, sizeof(portInfo)); name = (*env)->GetStringUTFChars(env, strName, NULL); if (name == NULL) { throwRuntimeException(env, "GetStringUTFChars failed"); } strncpy(portInfo.name, name, 63); portInfo.name[64] = 0; (*env)->ReleaseStringUTFChars(env, strName, name); // portInfo.capability = SND_SEQ_PORT_CAP_WRITE | SND_SEQ_PORT_CAP_SUBS_WRITE | SND_SEQ_PORT_CAP_READ; portInfo.capability = nCapabilities; portInfo.cap_group = nGroupPermissions; // portInfo.type = SND_SEQ_PORT_TYPE_MIDI_GENERIC; portInfo.type = nType; portInfo.midi_channels = nMidiChannels; portInfo.midi_voices = nMidiVoices; portInfo.synth_voices = nSynthVoices; //portInfo.write_use = 1; // R/O attrs? //portInfo.read_use = 1; // errno = 0; nReturn = snd_seq_create_port(seq, &portInfo); if (nReturn < 0) { throwRuntimeException(env, "snd_seq_create_port failed"); } return (jint) portInfo.port;}static voidfillClientInfoArrays(JNIEnv *env, jobject obj, snd_seq_client_info_t* clientInfo, jintArray anValues, jobjectArray astrValues){ int nLength; jstring strName; jstring strGroupName; jboolean bIsCopy; jint* pnValues; nLength = (*env)->GetArrayLength(env, anValues); if (nLength < 4) { throwRuntimeException(env, "array does not have enough elements (4 required)"); } pnValues = (*env)->GetIntArrayElements(env, anValues, &bIsCopy); if (pnValues == NULL) { throwRuntimeException(env, "GetIntArrayElements failed"); } pnValues[0] = clientInfo->client; pnValues[1] = clientInfo->type; pnValues[2] = clientInfo->filter; pnValues[3] = clientInfo->num_ports; if (bIsCopy) { (*env)->ReleaseIntArrayElements(env, anValues, pnValues, 0); } nLength = (*env)->GetArrayLength(env, astrValues); if (nLength < 2) { throwRuntimeException(env, "array does not have enough elements (2 required)"); } strName = (*env)->NewStringUTF(env, clientInfo->name); (*env)->SetObjectArrayElement(env, astrValues, 0, strName); strGroupName = (*env)->NewStringUTF(env, clientInfo->group); (*env)->SetObjectArrayElement(env, astrValues, 1, strGroupName);}static voidfillPortInfoArrays(JNIEnv *env, jobject obj, snd_seq_port_info_t* portInfo, jintArray anValues, jobjectArray astrValues){ int nLength; jstring strName; jstring strGroupName; jboolean bIsCopy; jint* pnValues; // printf("4a\n"); nLength = (*env)->GetArrayLength(env, anValues); if (nLength < 10) { throwRuntimeException(env, "array does not have enough elements (10 required)"); } // printf("4b\n"); pnValues = (*env)->GetIntArrayElements(env, anValues, &bIsCopy); if (pnValues == NULL) { throwRuntimeException(env, "GetIntArrayElements failed"); } // printf("4c\n"); pnValues[0] = portInfo->client; pnValues[1] = portInfo->port; pnValues[2] = portInfo->capability; pnValues[3] = portInfo->cap_group; pnValues[4] = portInfo->type; pnValues[5] = portInfo->midi_channels; pnValues[6] = portInfo->midi_voices; pnValues[7] = portInfo->synth_voices; pnValues[8] = portInfo->read_use; pnValues[9] = portInfo->write_use; // printf("4d\n"); if (bIsCopy) { (*env)->ReleaseIntArrayElements(env, anValues, pnValues, 0); } // printf("4e\n"); nLength = (*env)->GetArrayLength(env, astrValues); if (nLength < 2) { throwRuntimeException(env, "array does not have enough elements (2 required)"); } // printf("4f\n"); // printf("name: %s\n", portInfo->name); strName = (*env)->NewStringUTF(env, portInfo->name); if (strName == NULL) { printf("NewString failed\n"); } // printf("4g\n"); // this causes a segment violation (*env)->SetObjectArrayElement(env, astrValues, 0, strName); // printf("4h\n"); strGroupName = (*env)->NewStringUTF(env, portInfo->group); (*env)->SetObjectArrayElement(env, astrValues, 1, strGroupName); // printf("4i\n");}/* * Class: org_tritonus_lowlevel_alsa_ASequencer0 * Method: getClientInfo * Signature: (I[I[Ljava/lang/String;)V */JNIEXPORT jint JNICALL Java_org_tritonus_lowlevel_alsa_ASequencer0_getClientInfo (JNIEnv *env, jobject obj, jint nClient, jintArray anValues, jobjectArray astrValues){ snd_seq_client_info_t clientInfo; snd_seq_t* seq = getNativeSeq(env, obj); int nReturn; // int nLength; // jstring strName; // jstring strGroupName; // jboolean bIsCopy; memset(&clientInfo, 0, sizeof(clientInfo)); nReturn = snd_seq_get_any_client_info(seq, nClient, &clientInfo); if (nReturn < 0) { throwRuntimeException(env, "snd_seq_get_any_client_info failed"); } else { fillClientInfoArrays(env, obj, &clientInfo, anValues, astrValues);/* jint* pnValues; nLength = (*env)->GetArrayLength(env, anValues); if (nLength < 4) { throwRuntimeException(env, "array does not have enough elements (4 required)"); } pnValues = (*env)->GetIntArrayElements(env, anValues, &bIsCopy); if (pnValues == NULL) { throwRuntimeException(env, "GetIntArrayElements failed"); } pnValues[0] = clientInfo.client; pnValues[1] = clientInfo.type; pnValues[2] = clientInfo.filter; pnValues[3] = clientInfo.num_ports; if (bIsCopy) { (*env)->ReleaseIntArrayElements(env, anValues, pnValues, 0); } nLength = (*env)->GetArrayLength(env, astrValues); if (nLength < 2) { throwRuntimeException(env, "array does not have enough elements (2 required)"); } strName = (*env)->NewStringUTF(env, clientInfo.name); (*env)->SetObjectArrayElement(env, astrValues, 0, strName); strGroupName = (*env)->NewStringUTF(env, clientInfo.group); (*env)->SetObjectArrayElement(env, astrValues, 1, strGroupName);*/ } return (jint) nReturn;}/* * Class: org_tritonus_lowlevel_alsa_ASequencer0 * Method: getEvent * Signature: ([I[J[Ljava/lang/Object;)Z */JNIEXPORT jboolean JNICALLJava_org_tritonus_lowlevel_alsa_ASequencer0_getEvent(JNIEnv *env, jobject obj, jintArray anValues, jlongArray alValues, jobjectArray aObjValues){ snd_seq_t* seq = getNativeSeq(env, obj); snd_seq_event_t* pEvent; int nReturn; int nLength; jobject objectRef; jint* panValues; jlong* palValues; jboolean bIsCopyI; jboolean bIsCopyL; jbyteArray byteArray; /* * snd_seq_event_input() results in a blocking read on a * device file. There are two problems: * 1. green threads VMs do no blocking read. Therefore, this * code doesn't work with green threads at all. A solution is * outstanding. * 2. In some cases, the read is interrupted by a signal. This * is the reason for the do..while. */ do { // printf("1\n"); //errno = 0; nReturn = snd_seq_event_input(seq, &pEvent); //printf("return: %d\n", nReturn); // printf("event: %p\n", pEvent); //printf("errno: %d\n", errno); //perror("abc"); // printf("2\n"); } while (nReturn == -EINTR); if (pEvent == NULL) { return JNI_FALSE; } // now uesless? if (nReturn < 0) { throwRuntimeException(env, "snd_seq_event_input failed"); } nLength = (*env)->GetArrayLength(env, anValues); // printf("3\n"); if (nLength < 13) { throwRuntimeException(env, "array does not have enough elements (13 required)"); } panValues = (*env)->GetIntArrayElements(env, anValues, &bIsCopyI); // printf("4\n"); if (panValues == NULL) { throwRuntimeException(env, "GetIntArrayElements failed"); } nLength = (*env)->GetArrayLength(env, alValues); // printf("5\n"); if (nLength < 1) { throwRuntimeException(env, "array does not have enough elements (1 required)"); } palValues = (*env)->GetLongArrayElements(env, alValues, &bIsCopyL); // printf("6\n"); if (palValues == NULL) { throwRuntimeException(env, "GetLongArrayElements failed"); } // printf("6a\n"); panValues[0] = pEvent->type; // printf("6b\n"); panValues[1] = pEvent->flags; // printf("6c\n"); panValues[2] = pEvent->tag; // printf("6d\n"); panValues[3] = pEvent->queue; panValues[4] = pEvent->source.client;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -