Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/java.desktop/share/native/libjsound/MidiInDevice.c
41149 views
1
/*
2
* Copyright (c) 1999, 2007, 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
/*****************************************************************************/
27
/*
28
** Native functions for interfacing Java with the native implementation
29
** of PlatformMidi.h's functions.
30
*/
31
/*****************************************************************************/
32
33
#define USE_ERROR
34
#define USE_TRACE
35
36
37
#include <jni.h>
38
/* for memcpy */
39
#include <string.h>
40
#include "SoundDefs.h"
41
#include "PlatformMidi.h"
42
#include "com_sun_media_sound_MidiInDevice.h"
43
44
45
JNIEXPORT jlong JNICALL
46
Java_com_sun_media_sound_MidiInDevice_nOpen(JNIEnv* e, jobject thisObj, jint index) {
47
48
MidiDeviceHandle* deviceHandle = NULL;
49
INT32 err = MIDI_NOT_SUPPORTED;
50
51
TRACE1("> Java_com_sun_media_sound_MidiInDevice_nOpen: index: %d\n", index);
52
53
#if USE_PLATFORM_MIDI_IN == TRUE
54
err = MIDI_IN_OpenDevice((INT32) index, &deviceHandle);
55
#endif
56
57
/* $$mp 2003-08-28:
58
So far, the return value (err) hasn't been taken into account.
59
Now, it is also expected to be MIDI_SUCCESS (0).
60
This works for Linux, but has to be checked on other platforms.
61
62
It would be better to settle on one method of signaling error:
63
either returned error codes or a NULL handle. If the latter is used,
64
the return value should be removed from the signature of
65
MIDI_IN_OpenDevice.
66
*/
67
// if we didn't get a valid handle, throw a MidiUnavailableException
68
if (!deviceHandle || err != MIDI_SUCCESS) {
69
deviceHandle = NULL;
70
ERROR0("Java_com_sun_media_sound_MidiInDevice_nOpen: ");
71
ThrowJavaMessageException(e, JAVA_MIDI_PACKAGE_NAME"/MidiUnavailableException",
72
MIDI_IN_InternalGetErrorString(err));
73
} else {
74
TRACE0("< Java_com_sun_media_sound_MidiInDevice_nOpen succeeded\n");
75
}
76
return (jlong) (UINT_PTR) deviceHandle;
77
}
78
79
80
JNIEXPORT void JNICALL
81
Java_com_sun_media_sound_MidiInDevice_nClose(JNIEnv* e, jobject thisObj, jlong deviceHandle) {
82
83
TRACE0("> Java_com_sun_media_sound_MidiInDevice_nClose.\n");
84
85
#if USE_PLATFORM_MIDI_IN == TRUE
86
MIDI_IN_CloseDevice((MidiDeviceHandle*) (UINT_PTR) deviceHandle);
87
#endif
88
89
TRACE0("< Java_com_sun_media_sound_MidiInDevice_nClose succeeded\n");
90
}
91
92
93
JNIEXPORT void JNICALL
94
Java_com_sun_media_sound_MidiInDevice_nStart(JNIEnv* e, jobject thisObj, jlong deviceHandle) {
95
96
INT32 err = MIDI_NOT_SUPPORTED;
97
98
TRACE0("> Java_com_sun_media_sound_MidiInDevice_nStart.\n");
99
100
#if USE_PLATFORM_MIDI_IN == TRUE
101
err = MIDI_IN_StartDevice((MidiDeviceHandle*) (UINT_PTR) deviceHandle);
102
#endif
103
104
if (err != MIDI_SUCCESS) {
105
ERROR0("Java_com_sun_media_sound_MidiInDevice_nStart: ");
106
ThrowJavaMessageException(e, JAVA_MIDI_PACKAGE_NAME"/MidiUnavailableException",
107
MIDI_IN_InternalGetErrorString(err));
108
} else {
109
TRACE0("< Java_com_sun_media_sound_MidiInDevice_nStart succeeded\n");
110
}
111
}
112
113
114
JNIEXPORT void JNICALL
115
Java_com_sun_media_sound_MidiInDevice_nStop(JNIEnv* e, jobject thisObj, jlong deviceHandle) {
116
117
TRACE0("> Java_com_sun_media_sound_MidiInDevice_nStop.\n");
118
119
#if USE_PLATFORM_MIDI_IN == TRUE
120
// stop the device and remove all queued events for this device handle
121
MIDI_IN_StopDevice((MidiDeviceHandle*) (UINT_PTR) deviceHandle);
122
#endif
123
124
TRACE0("< Java_com_sun_media_sound_MidiInDevice_nStop succeeded\n");
125
}
126
127
JNIEXPORT jlong JNICALL
128
Java_com_sun_media_sound_MidiInDevice_nGetTimeStamp(JNIEnv* e, jobject thisObj, jlong deviceHandle) {
129
130
jlong ret = -1;
131
132
TRACE0("Java_com_sun_media_sound_MidiInDevice_nGetTimeStamp.\n");
133
134
#if USE_PLATFORM_MIDI_IN == TRUE
135
ret = (jlong) MIDI_IN_GetTimeStamp((MidiDeviceHandle*) (UINT_PTR) deviceHandle);
136
#endif
137
138
/* Handle error codes. */
139
if (ret < -1) {
140
ERROR1("Java_com_sun_media_sound_MidiInDevice_nGetTimeStamp: MIDI_IN_GetTimeStamp returned %lld\n", ret);
141
ret = -1;
142
}
143
return ret;
144
}
145
146
147
JNIEXPORT void JNICALL
148
Java_com_sun_media_sound_MidiInDevice_nGetMessages(JNIEnv* e, jobject thisObj, jlong deviceHandle) {
149
150
#if USE_PLATFORM_MIDI_IN == TRUE
151
MidiMessage* pMessage;
152
jclass javaClass = NULL;
153
jmethodID callbackShortMessageMethodID = NULL;
154
jmethodID callbackLongMessageMethodID = NULL;
155
#endif
156
157
TRACE0("> Java_com_sun_media_sound_MidiInDevice_nGetMessages\n");
158
159
#if USE_PLATFORM_MIDI_IN == TRUE
160
while ((pMessage = MIDI_IN_GetMessage((MidiDeviceHandle*) (UINT_PTR) deviceHandle))) {
161
if ((javaClass == NULL) || (callbackShortMessageMethodID == NULL)) {
162
if (!thisObj) {
163
ERROR0("MidiInDevice: Java_com_sun_media_sound_MidiInDevice_nGetMessages: thisObj is NULL\n");
164
return;
165
}
166
167
if (javaClass == NULL) {
168
javaClass = (*e)->GetObjectClass(e, thisObj);
169
if (javaClass == NULL) {
170
ERROR0("MidiInDevice: Java_com_sun_media_sound_MidiInDevice_nGetMessages: javaClass is NULL\n");
171
return;
172
}
173
}
174
175
if (callbackShortMessageMethodID == NULL) {
176
// save the callbackShortMessage callback method id.
177
// this is valid as long as the class is not unloaded.
178
callbackShortMessageMethodID = (*e)->GetMethodID(e, javaClass, "callbackShortMessage", "(IJ)V");
179
if (callbackShortMessageMethodID == 0) {
180
ERROR0("MidiInDevice: Java_com_sun_media_sound_MidiInDevice_nGetMessages: callbackShortMessageMethodID is 0\n");
181
return;
182
}
183
}
184
if (callbackLongMessageMethodID == NULL) {
185
// save the callbackLongMessage callback method id.
186
// this is valid as long as the class is not unloaded.
187
callbackLongMessageMethodID = (*e)->GetMethodID(e, javaClass, "callbackLongMessage", "([BJ)V");
188
if (callbackLongMessageMethodID == 0) {
189
ERROR0("MidiInDevice: Java_com_sun_media_sound_MidiInDevice_nGetMessages: callbackLongMessageMethodID is 0\n");
190
return;
191
}
192
}
193
}
194
195
switch ((int)pMessage->type) {
196
case SHORT_MESSAGE: {
197
jint msg = (jint)pMessage->data.s.packedMsg;
198
jlong ts = (jlong)pMessage->timestamp;
199
TRACE0("Java_com_sun_media_sound_MidiInDevice_nGetMessages: got SHORT_MESSAGE\n");
200
// now we can put this message object back in the queue
201
MIDI_IN_ReleaseMessage((MidiDeviceHandle*) (UINT_PTR) deviceHandle, pMessage);
202
// and notify Java space
203
(*e)->CallVoidMethod(e, thisObj, callbackShortMessageMethodID, msg, ts);
204
break;
205
}
206
207
case LONG_MESSAGE: {
208
jlong ts = (jlong)pMessage->timestamp;
209
jbyteArray jData;
210
UBYTE* data;
211
int isSXCont = 0;
212
TRACE0("Java_com_sun_media_sound_MidiInDevice_nGetMessages: got LONG_MESSAGE\n");
213
if ((*(pMessage->data.l.data) != 0xF0)
214
&& (*(pMessage->data.l.data) != 0xF7)) {
215
// this is a continued sys ex message
216
// need to prepend 0xF7
217
isSXCont = 1;
218
}
219
jData = (*e)->NewByteArray(e, pMessage->data.l.size + isSXCont);
220
if (!jData) {
221
ERROR0("Java_com_sun_media_sound_MidiInDevice_nGetMessages: cannot create long byte array.\n");
222
break;
223
}
224
data = (UBYTE*) ((*e)->GetByteArrayElements(e, jData, NULL));
225
if (!data) {
226
ERROR0("MidiInDevice: Java_com_sun_media_sound_MidiInDevice_nGetMessages: array data is NULL\n");
227
break;
228
}
229
// finally copy the long message
230
memcpy(data + isSXCont, pMessage->data.l.data, pMessage->data.l.size);
231
232
// now we can put this message object back in the queue
233
MIDI_IN_ReleaseMessage((MidiDeviceHandle*) (UINT_PTR) deviceHandle, pMessage);
234
235
// if this is a patched continued sys ex message, prepend 0xF7
236
if (isSXCont) {
237
*data = 0xF7;
238
}
239
240
// commit the byte array
241
(*e)->ReleaseByteArrayElements(e, jData, (jbyte*) data, (jint) 0);
242
243
(*e)->CallVoidMethod(e, thisObj, callbackLongMessageMethodID, jData, ts);
244
// release local reference to array: not needed anymore.
245
(*e)->DeleteLocalRef(e, jData);
246
break;
247
}
248
249
default:
250
// put this message object back in the queue
251
MIDI_IN_ReleaseMessage((MidiDeviceHandle*) (UINT_PTR) deviceHandle, pMessage);
252
ERROR1("Java_com_sun_media_sound_MidiInDevice_nGetMessages: got unsupported message, type %d\n", pMessage->type);
253
break;
254
} // switch
255
}
256
257
#endif // USE_PLATFORM_MIDI_IN
258
259
TRACE0("< Java_com_sun_media_sound_MidiInDevice_nGetMessages returning\n");
260
}
261
262