summaryrefslogtreecommitdiff
path: root/portmidi/pm_java
diff options
context:
space:
mode:
Diffstat (limited to 'portmidi/pm_java')
-rw-r--r--portmidi/pm_java/CMakeLists.txt56
-rw-r--r--portmidi/pm_java/README.txt62
-rw-r--r--portmidi/pm_java/jportmidi/JPortMidi.java541
-rw-r--r--portmidi/pm_java/jportmidi/JPortMidiApi.java117
-rw-r--r--portmidi/pm_java/jportmidi/JPortMidiException.java12
-rw-r--r--portmidi/pm_java/make.bat50
-rw-r--r--portmidi/pm_java/pmjni/jportmidi_JportMidiApi.h293
-rw-r--r--portmidi/pm_java/pmjni/pmjni.c354
-rw-r--r--portmidi/pm_java/pmjni/pmjni.rc63
9 files changed, 1548 insertions, 0 deletions
diff --git a/portmidi/pm_java/CMakeLists.txt b/portmidi/pm_java/CMakeLists.txt
new file mode 100644
index 0000000..55a20f4
--- /dev/null
+++ b/portmidi/pm_java/CMakeLists.txt
@@ -0,0 +1,56 @@
1# pm_java/CMakeLists.txt -- builds pmjni
2
3find_package(Java)
4message(STATUS "Java_JAVA_EXECUTABLE is " ${Java_JAVA_EXECUTABLE})
5
6# Build pmjni
7# this CMakeLists.txt is only loaded if BUILD_JAVA_NATIVE_INTERFACE
8# This jni library includes portmidi sources to give just
9# one library for JPortMidi users to manage rather than two.
10if(UNIX)
11 include(FindJNI)
12 # message(STATUS "JAVA_JVM_LIB_PATH is " ${JAVA_JVM_LIB_PATH})
13 # message(STATUS "JAVA_INCLUDE_PATH is " ${JAVA_INCLUDE_PATH})
14 # note: should use JAVA_JVM_LIB_PATH, but it is not set properly
15 # note: user might need to set JAVA_INCLUDE_PATH manually
16 #
17 # this will probably break on BSD and other Unix systems; the fix
18 # depends on whether FindJNI can find Java or not. If yes, then
19 # we should try to rely on automatically set JAVA_INCLUDE_PATH and
20 # JAVA_INCLUDE_PATH2; if no, then we need to make both JAVA_INCLUDE_PATH
21 # and JAVA_INCLUDE_PATH2 set by user (will need clear documentation
22 # because JAVA_INCLUDE_PATH2 is pretty obscure)
23 set(JAVA_INCLUDE_PATH ${JAVA_INCLUDE_PATH-UNKNOWN}
24 CACHE STRING "where to find Java SDK include directory")
25 # libjvm.so is found relative to JAVA_INCLUDE_PATH:
26 if (HAIKU)
27 set(JAVA_INCLUDE_PATHS ${JAVA_INCLUDE_PATH} ${JAVA_INCLUDE_PATH}/haiku)
28 else()
29 set(JAVA_INCLUDE_PATHS ${JAVA_INCLUDE_PATH} ${JAVA_INCLUDE_PATH}/linux)
30 endif()
31elseif(WIN32)
32 include(FindJNI)
33 # note: should use JAVA_JVM_LIB_PATH, but it is not set properly
34 set(JAVAVM_LIB ${JAVA_INCLUDE_PATH}/../lib/jvm.lib)
35
36 set(JAVA_INCLUDE_PATHS ${JAVA_INCLUDE_PATH} ${JAVA_INCLUDE_PATH2})
37 # message(STATUS "JAVA_INCLUDE_PATHS: " ${JAVA_INCLUDE_PATHS})
38 # message(STATUS "JAVAVM_LIB: " ${JAVAVM_LIB})
39endif()
40
41add_library(pmjni SHARED pmjni/pmjni.c)
42target_sources(pmjni PRIVATE ${PM_LIB_PUBLIC_SRC} ${PM_LIB_PRIVATE_SRC})
43message(STATUS "Java paths ${JAVA_INCLUDE_PATHS}")
44# message(STATUS "Java pmjni src: pmjni/pmjni.c ${PM_LIB_SHARED_SRC} "
45# "${PM_LIB_PRIVATE_SRC}")
46target_include_directories(pmjni PUBLIC ${JAVA_INCLUDE_PATHS})
47target_link_libraries(pmjni ${PM_NEEDED_LIBS})
48set_target_properties(pmjni PROPERTIES
49 VERSION ${LIBRARY_VERSION}
50 SOVERSION ${LIBRARY_SOVERSION}
51 LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
52 RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
53 ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}"
54 EXECUTABLE_EXTENSION "jnilib"
55 MACOSX_RPATH ON)
56
diff --git a/portmidi/pm_java/README.txt b/portmidi/pm_java/README.txt
new file mode 100644
index 0000000..d1e5ad5
--- /dev/null
+++ b/portmidi/pm_java/README.txt
@@ -0,0 +1,62 @@
1README.txt
2Roger B. Dannenberg
316 Jun 2009
4updated 2021
5
6This directory implements a JNI library so that Java programs can use
7the PortMidi API. This was mainly created to implement PmDefaults, a
8program to set default input and output devices for PortMidi
9applications. Because it is rarely used, PmDefaults was dropped from
10PortMidi starting with v3. I recommend you implement per-application
11preferences and store default PortMidi device numbers for input and
12output there. (Or better yet, store device *names* since numbers can
13change if you plug in or remove USB devices.)
14
15Even without PmDefaults, a PortMidi API for Java is probably an
16improvement over other Java libraries, but there is very little MIDI
17development in Java, so I have not maintained this API. The only thing
18probably seriously wrong now is an interface to the
19Pm_CreateVirtualInput and Pm_CreateVirtualOutput functions, which are
20new additions.
21
22I will leave the code here, and if there is a demand, please either
23update it or let your needs be known. Perhaps I or someone can help.
24
25==================================================================
26
27BUILDING Java EXTERNAL LIBRARY
28
29You must have a JDK installed (Java development kit including javac
30(the Java compiler), jni.h, etc.
31
32Test java on the command line, e.g., type: javac -version
33
34Enable these options in the main CMakeLists.txt file (run CMake
35from your top-level repository directory):
36 BUILD_JAVA_NATIVE_INTERFACE
37In my Ubuntu linux with jdk-15, ccmake was unable to find my JDK, so
38I have to manually set CMake variables as follows (type 't' to see
39these in ccmake):
40 JAVA_AWT_INCLUDE_PATH /usr/lib/jvm/jdk-15/include
41 JAVA_AWT_LIBRARY /usr/lib/jvm/jdk-15/lib
42 JAVA_INCLUDE_PATH /usr/lib/jvm/jdk-15/include
43 JAVA_INCLUDE_PATH2 /usr/lib/jvm/jdk-15/include
44 JAVA_JVM_LIBRARY /usr/lib/jvm/jdk-15/lib
45Of course, your paths may differ.
46
47
48---- old implementation notes ----
49
50For Windows, we use the free software JavaExe.exe. The copy here was
51downloaded from
52
53http://software.techrepublic.com.com/abstract.aspx?kw=javaexe&docid=767485
54
55I found this page by visiting http://software.techrepublic.com.com and
56searching in the "Software" category for "JavaExe"
57
58JavaExe works by placing the JavaExe.exe file in the directory with the
59Java application jar file and then *renaming* JavaExe.exe to the name
60of the jar file, but keeping the .exe extension. (See make.bat for this
61step.) Documentation for JavaExe can be obtained by downloading the
62whole program from the URL(s) above.
diff --git a/portmidi/pm_java/jportmidi/JPortMidi.java b/portmidi/pm_java/jportmidi/JPortMidi.java
new file mode 100644
index 0000000..7116e19
--- /dev/null
+++ b/portmidi/pm_java/jportmidi/JPortMidi.java
@@ -0,0 +1,541 @@
1package jportmidi;
2
3/* PortMidi is a general class intended for any Java program using
4 the PortMidi library. It encapsulates JPortMidiApi with a more
5 object-oriented interface. A single PortMidi object can manage
6 up to one input stream and one output stream.
7
8 This class is not safely callable from multiple threads. It
9 is the client's responsibility to periodically call the Poll
10 method which checks for midi input and handles it.
11*/
12
13import jportmidi.*;
14import jportmidi.JPortMidiApi.*;
15
16public class JPortMidi {
17
18 // timecode to send message immediately
19 public final int NOW = 0;
20
21 // midi codes
22 public final int MIDI_NOTE_OFF = 0x80;
23 public final int MIDI_NOTE_ON = 0x90;
24 public final int CTRL_ALL_OFF = 123;
25 public final int MIDI_PITCH_BEND = 0xE0;
26 public final int MIDI_CLOCK = 0xF8;
27 public final int MIDI_CONTROL = 0xB0;
28 public final int MIDI_PROGRAM = 0xC0;
29 public final int MIDI_START = 0xFA;
30 public final int MIDI_STOP = 0xFC;
31 public final int MIDI_POLY_TOUCH = 0xA0;
32 public final int MIDI_TOUCH = 0xD0;
33
34 // error code -- cannot refresh device list while stream is open:
35 public final int pmStreamOpen = -5000;
36 public final int pmOutputNotOpen = -4999;
37
38 // access to JPortMidiApi is through a single, global instance
39 private static JPortMidiApi pm;
40 // a reference count tracks how many objects have it open
41 private static int pmRefCount = 0;
42 private static int openCount = 0;
43
44 public int error; // user can check here for error codes
45 private PortMidiStream input;
46 private PortMidiStream output;
47 private PmEvent buffer;
48 protected int timestamp; // remember timestamp from incoming messages
49 protected boolean trace = false; // used to print midi msgs for debugging
50
51
52 public JPortMidi() throws JPortMidiException {
53 if (pmRefCount == 0) {
54 pm = new JPortMidiApi();
55 pmRefCount++;
56 System.out.println("Calling Pm_Initialize");
57 checkError(pm.Pm_Initialize());
58 System.out.println("Called Pm_Initialize");
59 }
60 buffer = new PmEvent();
61 }
62
63 public boolean getTrace() { return trace; }
64
65 // set the trace flag and return previous value
66 public boolean setTrace(boolean flag) {
67 boolean previous = trace;
68 trace = flag;
69 return previous;
70 }
71
72 // WARNING: you must not call this if any devices are open
73 public void refreshDeviceLists()
74 throws JPortMidiException
75 {
76 if (openCount > 0) {
77 throw new JPortMidiException(pmStreamOpen,
78 "RefreshDeviceLists called while stream is open");
79 }
80 if (trace) System.out.println("Pm_Terminate");
81 checkError(pm.Pm_Terminate());
82 if (trace) System.out.println("Pm_Initialize");
83 checkError(pm.Pm_Initialize());
84 }
85
86 // there is no control over when/whether this is called, but it seems
87 // to be a good idea to close things when this object is collected
88 public void finalize() {
89 if (input != null) {
90 error = pm.Pm_Close(input);
91 }
92 if (input != null) {
93 int rslt = pm.Pm_Close(output);
94 // we may lose an error code from closing output, but don't
95 // lose any real error from closing input...
96 if (error == pm.pmNoError) error = rslt;
97 }
98 pmRefCount--;
99 if (pmRefCount == 0) {
100 error = pm.Pm_Terminate();
101 }
102 }
103
104 int checkError(int err) throws JPortMidiException
105 {
106 // note that Pm_Read and Pm_Write return positive result values
107 // which are not errors, so compare with >=
108 if (err >= pm.pmNoError) return err;
109 if (err == pm.pmHostError) {
110 throw new JPortMidiException(err, pm.Pm_GetHostErrorText());
111 } else {
112 throw new JPortMidiException(err, pm.Pm_GetErrorText(err));
113 }
114 }
115
116 // ******** ACCESS TO TIME ***********
117
118 public void timeStart(int resolution) throws JPortMidiException {
119 checkError(pm.Pt_TimeStart(resolution));
120 }
121
122 public void timeStop() throws JPortMidiException {
123 checkError(pm.Pt_TimeStop());
124 }
125
126 public int timeGet() {
127 return pm.Pt_Time();
128 }
129
130 public boolean timeStarted() {
131 return pm.Pt_TimeStarted();
132 }
133
134 // ******* QUERY DEVICE INFORMATION *********
135
136 public int countDevices() throws JPortMidiException {
137 return checkError(pm.Pm_CountDevices());
138 }
139
140 public int getDefaultInputDeviceID() throws JPortMidiException {
141 return checkError(pm.Pm_GetDefaultInputDeviceID());
142 }
143
144 public int getDefaultOutputDeviceID() throws JPortMidiException {
145 return checkError(pm.Pm_GetDefaultOutputDeviceID());
146 }
147
148 public String getDeviceInterf(int i) {
149 return pm.Pm_GetDeviceInterf(i);
150 }
151
152 public String getDeviceName(int i) {
153 return pm.Pm_GetDeviceName(i);
154 }
155
156 public boolean getDeviceInput(int i) {
157 return pm.Pm_GetDeviceInput(i);
158 }
159
160 public boolean getDeviceOutput(int i) {
161 return pm.Pm_GetDeviceOutput(i);
162 }
163
164 // ********** MIDI INTERFACE ************
165
166 public boolean isOpenInput() {
167 return input != null;
168 }
169
170 public void openInput(int inputDevice, int bufferSize)
171 throws JPortMidiException
172 {
173 openInput(inputDevice, "", bufferSize);
174 }
175
176 public void openInput(int inputDevice, String inputDriverInfo, int bufferSize)
177 throws JPortMidiException
178 {
179 if (isOpenInput()) pm.Pm_Close(input);
180 else input = new PortMidiStream();
181 if (trace) {
182 System.out.println("openInput " + getDeviceName(inputDevice));
183 }
184 checkError(pm.Pm_OpenInput(input, inputDevice,
185 inputDriverInfo, bufferSize));
186 // if no exception, then increase count of open streams
187 openCount++;
188 }
189
190 public boolean isOpenOutput() {
191 return output != null;
192 }
193
194 public void openOutput(int outputDevice, int bufferSize, int latency)
195 throws JPortMidiException
196 {
197 openOutput(outputDevice, "", bufferSize, latency);
198 }
199
200 public void openOutput(int outputDevice, String outputDriverInfo,
201 int bufferSize, int latency) throws JPortMidiException {
202 if (isOpenOutput()) pm.Pm_Close(output);
203 else output = new PortMidiStream();
204 if (trace) {
205 System.out.println("openOutput " + getDeviceName(outputDevice));
206 }
207 checkError(pm.Pm_OpenOutput(output, outputDevice, outputDriverInfo,
208 bufferSize, latency));
209 // if no exception, then increase count of open streams
210 openCount++;
211 }
212
213 public void setFilter(int filters) throws JPortMidiException {
214 if (input == null) return; // no effect if input not open
215 checkError(pm.Pm_SetFilter(input, filters));
216 }
217
218 public void setChannelMask(int mask) throws JPortMidiException {
219 if (input == null) return; // no effect if input not open
220 checkError(pm.Pm_SetChannelMask(input, mask));
221 }
222
223 public void abort() throws JPortMidiException {
224 if (output == null) return; // no effect if output not open
225 checkError(pm.Pm_Abort(output));
226 }
227
228 // In keeping with the idea that this class represents an input and output,
229 // there are separate Close methods for input and output streams, avoiding
230 // the need for clients to ever deal directly with a stream object
231 public void closeInput() throws JPortMidiException {
232 if (input == null) return; // no effect if input not open
233 checkError(pm.Pm_Close(input));
234 input = null;
235 openCount--;
236 }
237
238 public void closeOutput() throws JPortMidiException {
239 if (output == null) return; // no effect if output not open
240 checkError(pm.Pm_Close(output));
241 output = null;
242 openCount--;
243 }
244
245 // Poll should be called by client to process input messages (if any)
246 public void poll() throws JPortMidiException {
247 if (input == null) return; // does nothing until input is opened
248 while (true) {
249 int rslt = pm.Pm_Read(input, buffer);
250 checkError(rslt);
251 if (rslt == 0) return; // no more messages
252 handleMidiIn(buffer);
253 }
254 }
255
256 public void writeShort(int when, int msg) throws JPortMidiException {
257 if (output == null)
258 throw new JPortMidiException(pmOutputNotOpen,
259 "Output stream not open");
260 if (trace) {
261 System.out.println("writeShort: " + Integer.toHexString(msg));
262 }
263 checkError(pm.Pm_WriteShort(output, when, msg));
264 }
265
266 public void writeSysEx(int when, byte msg[]) throws JPortMidiException {
267 if (output == null)
268 throw new JPortMidiException(pmOutputNotOpen,
269 "Output stream not open");
270 if (trace) {
271 System.out.print("writeSysEx: ");
272 for (int i = 0; i < msg.length; i++) {
273 System.out.print(Integer.toHexString(msg[i]));
274 }
275 System.out.print("\n");
276 }
277 checkError(pm.Pm_WriteSysEx(output, when, msg));
278 }
279
280 public int midiChanMessage(int chan, int status, int data1, int data2) {
281 return (((data2 << 16) & 0xFF0000) |
282 ((data1 << 8) & 0xFF00) |
283 (status & 0xF0) |
284 (chan & 0xF));
285 }
286
287 public int midiMessage(int status, int data1, int data2) {
288 return ((((data2) << 16) & 0xFF0000) |
289 (((data1) << 8) & 0xFF00) |
290 ((status) & 0xFF));
291 }
292
293 public void midiAllOff(int channel) throws JPortMidiException {
294 midiAllOff(channel, NOW);
295 }
296
297 public void midiAllOff(int chan, int when) throws JPortMidiException {
298 writeShort(when, midiChanMessage(chan, MIDI_CONTROL, CTRL_ALL_OFF, 0));
299 }
300
301 public void midiPitchBend(int chan, int value) throws JPortMidiException {
302 midiPitchBend(chan, value, NOW);
303 }
304
305 public void midiPitchBend(int chan, int value, int when)
306 throws JPortMidiException {
307 writeShort(when,
308 midiChanMessage(chan, MIDI_PITCH_BEND, value, value >> 7));
309 }
310
311 public void midiClock() throws JPortMidiException {
312 midiClock(NOW);
313 }
314
315 public void midiClock(int when) throws JPortMidiException {
316 writeShort(when, midiMessage(MIDI_CLOCK, 0, 0));
317 }
318
319 public void midiControl(int chan, int control, int value)
320 throws JPortMidiException {
321 midiControl(chan, control, value, NOW);
322 }
323
324 public void midiControl(int chan, int control, int value, int when)
325 throws JPortMidiException {
326 writeShort(when, midiChanMessage(chan, MIDI_CONTROL, control, value));
327 }
328
329 public void midiNote(int chan, int pitch, int vel)
330 throws JPortMidiException {
331 midiNote(chan, pitch, vel, NOW);
332 }
333
334 public void midiNote(int chan, int pitch, int vel, int when)
335 throws JPortMidiException {
336 writeShort(when, midiChanMessage(chan, MIDI_NOTE_ON, pitch, vel));
337 }
338
339 public void midiProgram(int chan, int program)
340 throws JPortMidiException {
341 midiProgram(chan, program, NOW);
342 }
343
344 public void midiProgram(int chan, int program, int when)
345 throws JPortMidiException {
346 writeShort(when, midiChanMessage(chan, MIDI_PROGRAM, program, 0));
347 }
348
349 public void midiStart()
350 throws JPortMidiException {
351 midiStart(NOW);
352 }
353
354 public void midiStart(int when)
355 throws JPortMidiException {
356 writeShort(when, midiMessage(MIDI_START, 0, 0));
357 }
358
359 public void midiStop()
360 throws JPortMidiException {
361 midiStop(NOW);
362 }
363
364 public void midiStop(int when)
365 throws JPortMidiException {
366 writeShort(when, midiMessage(MIDI_STOP, 0, 0));
367 }
368
369 public void midiPolyTouch(int chan, int key, int value)
370 throws JPortMidiException {
371 midiPolyTouch(chan, key, value, NOW);
372 }
373
374 public void midiPolyTouch(int chan, int key, int value, int when)
375 throws JPortMidiException {
376 writeShort(when, midiChanMessage(chan, MIDI_POLY_TOUCH, key, value));
377 }
378
379 public void midiTouch(int chan, int value)
380 throws JPortMidiException {
381 midiTouch(chan, value, NOW);
382 }
383
384 public void midiTouch(int chan, int value, int when)
385 throws JPortMidiException {
386 writeShort(when, midiChanMessage(chan, MIDI_TOUCH, value, 0));
387 }
388
389 // ****** now we implement the message handlers ******
390
391 // an array for incoming sysex messages that can grow.
392 // The downside is that after getting a message, we
393
394 private byte sysexBuffer[] = null;
395 private int sysexBufferIndex = 0;
396
397 void sysexBufferReset() {
398 sysexBufferIndex = 0;
399 if (sysexBuffer == null) sysexBuffer = new byte[256];
400 }
401
402 void sysexBufferCheck() {
403 if (sysexBuffer.length < sysexBufferIndex + 4) {
404 byte bigger[] = new byte[sysexBuffer.length * 2];
405 for (int i = 0; i < sysexBufferIndex; i++) {
406 bigger[i] = sysexBuffer[i];
407 }
408 sysexBuffer = bigger;
409 }
410 // now we have space to write some bytes
411 }
412
413 // call this to insert Sysex and EOX status bytes
414 // call sysexBufferAppendBytes to insert anything else
415 void sysexBufferAppendStatus(byte status) {
416 sysexBuffer[sysexBufferIndex++] = status;
417 }
418
419 void sysexBufferAppendBytes(int msg, int len) {
420 for (int i = 0; i < len; i++) {
421 byte b = (byte) msg;
422 if ((msg & 0x80) != 0) {
423 if (b == 0xF7) { // end of sysex
424 sysexBufferAppendStatus(b);
425 sysex(sysexBuffer, sysexBufferIndex);
426 return;
427 }
428 // recursively handle embedded real-time messages
429 PmEvent buffer = new PmEvent();
430 buffer.timestamp = timestamp;
431 buffer.message = b;
432 handleMidiIn(buffer);
433 } else {
434 sysexBuffer[sysexBufferIndex++] = b;
435 }
436 msg = msg >> 8;
437 }
438 }
439
440 void sysexBegin(int msg) {
441 sysexBufferReset(); // start from 0, we have at least 256 bytes now
442 sysexBufferAppendStatus((byte) (msg & 0xFF)); // first byte is special
443 sysexBufferAppendBytes(msg >> 8, 3); // process remaining bytes
444 }
445
446 public void handleMidiIn(PmEvent buffer)
447 {
448 if (trace) {
449 System.out.println("handleMidiIn: " +
450 Integer.toHexString(buffer.message));
451 }
452 // rather than pass timestamps to every handler, where typically
453 // timestamps are ignored, just save the timestamp as a member
454 // variable where methods can access it if they want it
455 timestamp = buffer.timestamp;
456 int status = buffer.message & 0xFF;
457 if (status < 0x80) {
458 sysexBufferCheck(); // make enough space
459 sysexBufferAppendBytes(buffer.message, 4); // process 4 bytes
460 return;
461 }
462 int command = status & 0xF0;
463 int channel = status & 0x0F;
464 int data1 = (buffer.message >> 8) & 0xFF;
465 int data2 = (buffer.message >> 16) & 0xFF;
466 switch (command) {
467 case MIDI_NOTE_OFF:
468 noteOff(channel, data1, data2); break;
469 case MIDI_NOTE_ON:
470 if (data2 > 0) {
471 noteOn(channel, data1, data2); break;
472 } else {
473 noteOff(channel, data1);
474 }
475 break;
476 case MIDI_CONTROL:
477 control(channel, data1, data2); break;
478 case MIDI_POLY_TOUCH:
479 polyTouch(channel, data1, data2); break;
480 case MIDI_TOUCH:
481 touch(channel, data1); break;
482 case MIDI_PITCH_BEND:
483 pitchBend(channel, (data1 + (data2 << 7)) - 8192); break;
484 case MIDI_PROGRAM:
485 program(channel, data1); break;
486 case 0xF0:
487 switch (channel) {
488 case 0: sysexBegin(buffer.message); break;
489 case 1: mtcQuarterFrame(data1);
490 case 2: songPosition(data1 + (data2 << 7)); break;
491 case 3: songSelect(data1); break;
492 case 4: /* unused */ break;
493 case 5: /* unused */ break;
494 case 6: tuneRequest(); break;
495 case 7: sysexBufferAppendBytes(buffer.message, buffer.message); break;
496 case 8: clock(); break;
497 case 9: tick(); break;
498 case 0xA: clockStart(); break;
499 case 0xB: clockContinue(); break;
500 case 0xC: clockStop(); break;
501 case 0xD: /* unused */ break;
502 case 0xE: activeSense(); break;
503 case 0xF: reset(); break;
504 }
505 }
506 }
507
508 // the value ranges from +8181 to -8192. The interpretation is
509 // synthesizer dependent. Often the range is +/- one whole step
510 // (two semitones), but the range is usually adjustable within
511 // the synthesizer.
512 void pitchBend(int channel, int value) { return; }
513 void control(int channel, int control, int value) { return; }
514 void noteOn(int channel, int pitch, int velocity) { return; }
515 // you can handle velocity in note-off if you want, but the default
516 // is to drop the velocity and call the simpler NoteOff handler
517 void noteOff(int channel, int pitch, int velocity) {
518 noteOff(channel, pitch);
519 }
520 // if the subclass wants to implement NoteOff with velocity, it
521 // should override the following to make sure all NoteOffs are handled
522 void noteOff(int channel, int pitch) { return; }
523 void program(int channel, int program) { return; }
524 // the byte array may be bigger than the message, length tells how
525 // many bytes in the array are part of the message
526 void sysex(byte[] msg, int length) { return; }
527 void polyTouch(int channel, int key, int value) { return; }
528 void touch(int channel, int value) { return; }
529 void mtcQuarterFrame(int value) { return; }
530 // the value is a 14-bit integer representing 16th notes
531 void songPosition(int value) { return; }
532 void songSelect(int value) { return; }
533 void tuneRequest() { return; }
534 void clock() { return; } // represents 1/24th of a quarter note
535 void tick() { return; } // represents 10ms
536 void clockStart() { return; }
537 void clockStop() { return; }
538 void clockContinue() { return; }
539 void activeSense() { return; }
540 void reset() { return; }
541}
diff --git a/portmidi/pm_java/jportmidi/JPortMidiApi.java b/portmidi/pm_java/jportmidi/JPortMidiApi.java
new file mode 100644
index 0000000..45dd9d9
--- /dev/null
+++ b/portmidi/pm_java/jportmidi/JPortMidiApi.java
@@ -0,0 +1,117 @@
1package jportmidi;
2
3public class JPortMidiApi {
4 public static class PortMidiStream {
5 private long address;
6 }
7 public static class PmEvent {
8 public int message;
9 public int timestamp;
10 }
11
12 // PmError bindings
13 public final int pmNoError = 0;
14 public final int pmNoData = 0;
15 public final int pmGotData = -1;
16 public final int pmHostError = -10000;
17 public final int pmInvalidDeviceId = -9999;
18 public final int pmInsufficientMemory = -9998;
19 public final int pmBufferTooSmall = -9997;
20 public final int pmBufferOverflow = -9996;
21 public final int pmBadPtr = -9995;
22 public final int pmBadData = -9994;
23 public final int pmInternalError = -9993;
24 public final int pmBufferMaxSize = -9992;
25
26 static public native int Pm_Initialize();
27 static public native int Pm_Terminate();
28 static public native int Pm_HasHostError(PortMidiStream stream);
29 static public native String Pm_GetErrorText(int errnum);
30 static public native String Pm_GetHostErrorText();
31 final int pmNoDevice = -1;
32 static public native int Pm_CountDevices();
33 static public native int Pm_GetDefaultInputDeviceID();
34 static public native int Pm_GetDefaultOutputDeviceID();
35 static public native String Pm_GetDeviceInterf(int i);
36 static public native String Pm_GetDeviceName(int i);
37 static public native boolean Pm_GetDeviceInput(int i);
38 static public native boolean Pm_GetDeviceOutput(int i);
39 static public native int Pm_OpenInput(PortMidiStream stream,
40 int inputDevice,
41 String inputDriverInfo,
42 int bufferSize);
43 static public native int Pm_OpenOutput(PortMidiStream stream,
44 int outputDevice,
45 String outnputDriverInfo,
46 int bufferSize,
47 int latency);
48 final static public int PM_FILT_ACTIVE = (1 << 0x0E);
49 final static public int PM_FILT_SYSEX = (1 << 0x00);
50 final static public int PM_FILT_CLOCK = (1 << 0x08);
51 final static public int PM_FILT_PLAY =
52 (1 << 0x0A) | (1 << 0x0C) | (1 << 0x0B);
53 final static public int PM_FILT_TICK = (1 << 0x09);
54 final static public int PM_FILT_FD = (1 << 0x0D);
55 final static public int PM_FILT_UNDEFINED = PM_FILT_FD;
56 final static public int PM_FILT_RESET = (1 << 0x0F);
57 final static public int PM_FILT_REALTIME =
58 PM_FILT_ACTIVE | PM_FILT_SYSEX | PM_FILT_CLOCK;
59 final static public int PM_FILT_NOTE = (1 << 0x19) | (1 << 0x18);
60 final static public int PM_FILT_CHANNEL_AFTERTOUCH = (1 << 0x1D);
61 final static public int PM_FILT_POLY_AFTERTOUCH = (1 << 0x1A);
62 final static public int PM_FILT_AFTERTOUCH =
63 (PM_FILT_CHANNEL_AFTERTOUCH | PM_FILT_POLY_AFTERTOUCH);
64 final static public int PM_FILT_PROGRAM = (1 << 0x1C);
65 final static public int PM_FILT_CONTROL = (1 << 0x1B);
66 final static public int PM_FILT_PITCHBEND = (1 << 0x1E);
67 final static public int PM_FILT_MTC = (1 << 0x01);
68 final static public int PM_FILT_SONG_POSITION = (1 << 0x02);
69 final static public int PM_FILT_SONG_SELECT = (1 << 0x03);
70 final static public int PM_FILT_TUNE = (1 << 0x06);
71 final static public int PM_FILT_SYSTEMCOMMON =
72 (PM_FILT_MTC | PM_FILT_SONG_POSITION |
73 PM_FILT_SONG_SELECT | PM_FILT_TUNE);
74 static public native int Pm_SetFilter(PortMidiStream stream, int filters);
75 static public int Pm_Channel(int channel) { return 1 << channel; }
76 final static public native int Pm_SetChannelMask(PortMidiStream stream,
77 int mask);
78 final static public native int Pm_Abort(PortMidiStream stream);
79 final static public native int Pm_Close(PortMidiStream stream);
80 static public int Pm_Message(int status, int data1, int data2) {
81 return (((data2 << 16) & 0xFF0000) |
82 ((data1 << 8) & 0xFF00) |
83 (status & 0xFF));
84 }
85 static public int Pm_MessageStatus(int msg) {
86 return msg & 0xFF;
87 }
88 static public int Pm_MessageData1(int msg) {
89 return (msg >> 8) & 0xFF;
90 }
91 static public int Pm_MessageData2(int msg) {
92 return (msg >> 16) & 0xFF;
93 }
94 // only supports reading one buffer at a time
95 static public native int Pm_Read(PortMidiStream stream, PmEvent buffer);
96 static public native int Pm_Poll(PortMidiStream stream);
97 // only supports writing one buffer at a time
98 static public native int Pm_Write(PortMidiStream stream, PmEvent buffer);
99 static public native int Pm_WriteShort(PortMidiStream stream,
100 int when, int msg);
101 static public native int Pm_WriteSysEx(PortMidiStream stream,
102 int when, byte msg[]);
103
104 public final int ptNoError = 0;
105 public final int ptAlreadyStarted = -10000;
106 public final int ptAlreadyStopped = -9999;
107 public final int PtInsufficientMemory = -9998;
108 static public native int Pt_TimeStart(int resolution);
109 static public native int Pt_TimeStop();
110 static public native int Pt_Time();
111 static public native boolean Pt_TimeStarted();
112 static {
113 System.out.println("Loading pmjni");
114 System.loadLibrary("pmjni");
115 System.out.println("done loading pmjni");
116 }
117}
diff --git a/portmidi/pm_java/jportmidi/JPortMidiException.java b/portmidi/pm_java/jportmidi/JPortMidiException.java
new file mode 100644
index 0000000..9be8aaf
--- /dev/null
+++ b/portmidi/pm_java/jportmidi/JPortMidiException.java
@@ -0,0 +1,12 @@
1// JPortMidiException -- thrown by JPortMidi methods
2
3package jportmidi;
4
5public class JPortMidiException extends Exception {
6 public int error = 0;
7 public JPortMidiException(int err, String msg) {
8 super(msg);
9 error = err;
10 }
11}
12
diff --git a/portmidi/pm_java/make.bat b/portmidi/pm_java/make.bat
new file mode 100644
index 0000000..ff15c2b
--- /dev/null
+++ b/portmidi/pm_java/make.bat
@@ -0,0 +1,50 @@
1@echo off
2
3rem This is an out-of-date script for Windows to build a Java application
4rem (PmDefaults) with PortMidi external library.xb
5
6rem Compile the java PortMidi interface classes.
7javac jportmidi/*.java
8
9rem Compile the pmdefaults application.
10javac -classpath . pmdefaults/*.java
11
12rem Temporarily copy the portmusic_logo.png file here to add to the jar file.
13copy pmdefaults\portmusic_logo.png . > nul
14
15rem Create a directory to hold the distribution.
16mkdir win32
17
18rem Attempt to copy the interface DLL to the distribution directory.
19
20if exist "..\release\pmjni.dll" goto have-dll
21
22echo "ERROR: pmjni.dll not found!"
23exit /b 1
24
25:have-dll
26copy "..\release\pmjni.dll" win32\pmjni.dll > nul
27
28rem Create a java archive (jar) file of the distribution.
29jar cmf pmdefaults\manifest.txt win32\pmdefaults.jar pmdefaults\*.class portmusic_logo.png jportmidi\*.class
30
31rem Clean up the temporary image file now that it is in the jar file.
32del portmusic_logo.png
33
34rem Copy the java execution code obtained from
35rem http://devwizard.free.fr/html/en/JavaExe.html to the distribution
36rem directory. The copy also renames the file to our desired executable
37rem name.
38copy JavaExe.exe win32\pmdefaults.exe > nul
39
40rem Integrate the icon into the executable using UpdateRsrcJavaExe from
41rem http://devwizard.free.fr
42UpdateRsrcJavaExe -run -exe=win32\pmdefaults.exe -ico=pmdefaults\pmdefaults.ico
43
44rem Copy the 32-bit windows read me file to the distribution directory.
45copy pmdefaults\readme-win32.txt win32\README.txt > nul
46
47rem Copy the license file to the distribution directory.
48copy pmdefaults\pmdefaults-license.txt win32\license.txt > nul
49
50echo "You can run pmdefaults.exe in win32"
diff --git a/portmidi/pm_java/pmjni/jportmidi_JportMidiApi.h b/portmidi/pm_java/pmjni/jportmidi_JportMidiApi.h
new file mode 100644
index 0000000..2208be6
--- /dev/null
+++ b/portmidi/pm_java/pmjni/jportmidi_JportMidiApi.h
@@ -0,0 +1,293 @@
1/* DO NOT EDIT THIS FILE - it is machine generated */
2#include <jni.h>
3/* Header for class jportmidi_JPortMidiApi */
4
5#ifndef _Included_jportmidi_JPortMidiApi
6#define _Included_jportmidi_JPortMidiApi
7#ifdef __cplusplus
8extern "C" {
9#endif
10#undef jportmidi_JPortMidiApi_PM_FILT_ACTIVE
11#define jportmidi_JPortMidiApi_PM_FILT_ACTIVE 16384L
12#undef jportmidi_JPortMidiApi_PM_FILT_SYSEX
13#define jportmidi_JPortMidiApi_PM_FILT_SYSEX 1L
14#undef jportmidi_JPortMidiApi_PM_FILT_CLOCK
15#define jportmidi_JPortMidiApi_PM_FILT_CLOCK 256L
16#undef jportmidi_JPortMidiApi_PM_FILT_PLAY
17#define jportmidi_JPortMidiApi_PM_FILT_PLAY 7168L
18#undef jportmidi_JPortMidiApi_PM_FILT_TICK
19#define jportmidi_JPortMidiApi_PM_FILT_TICK 512L
20#undef jportmidi_JPortMidiApi_PM_FILT_FD
21#define jportmidi_JPortMidiApi_PM_FILT_FD 8192L
22#undef jportmidi_JPortMidiApi_PM_FILT_UNDEFINED
23#define jportmidi_JPortMidiApi_PM_FILT_UNDEFINED 8192L
24#undef jportmidi_JPortMidiApi_PM_FILT_RESET
25#define jportmidi_JPortMidiApi_PM_FILT_RESET 32768L
26#undef jportmidi_JPortMidiApi_PM_FILT_REALTIME
27#define jportmidi_JPortMidiApi_PM_FILT_REALTIME 16641L
28#undef jportmidi_JPortMidiApi_PM_FILT_NOTE
29#define jportmidi_JPortMidiApi_PM_FILT_NOTE 50331648L
30#undef jportmidi_JPortMidiApi_PM_FILT_CHANNEL_AFTERTOUCH
31#define jportmidi_JPortMidiApi_PM_FILT_CHANNEL_AFTERTOUCH 536870912L
32#undef jportmidi_JPortMidiApi_PM_FILT_POLY_AFTERTOUCH
33#define jportmidi_JPortMidiApi_PM_FILT_POLY_AFTERTOUCH 67108864L
34#undef jportmidi_JPortMidiApi_PM_FILT_AFTERTOUCH
35#define jportmidi_JPortMidiApi_PM_FILT_AFTERTOUCH 603979776L
36#undef jportmidi_JPortMidiApi_PM_FILT_PROGRAM
37#define jportmidi_JPortMidiApi_PM_FILT_PROGRAM 268435456L
38#undef jportmidi_JPortMidiApi_PM_FILT_CONTROL
39#define jportmidi_JPortMidiApi_PM_FILT_CONTROL 134217728L
40#undef jportmidi_JPortMidiApi_PM_FILT_PITCHBEND
41#define jportmidi_JPortMidiApi_PM_FILT_PITCHBEND 1073741824L
42#undef jportmidi_JPortMidiApi_PM_FILT_MTC
43#define jportmidi_JPortMidiApi_PM_FILT_MTC 2L
44#undef jportmidi_JPortMidiApi_PM_FILT_SONG_POSITION
45#define jportmidi_JPortMidiApi_PM_FILT_SONG_POSITION 4L
46#undef jportmidi_JPortMidiApi_PM_FILT_SONG_SELECT
47#define jportmidi_JPortMidiApi_PM_FILT_SONG_SELECT 8L
48#undef jportmidi_JPortMidiApi_PM_FILT_TUNE
49#define jportmidi_JPortMidiApi_PM_FILT_TUNE 64L
50#undef jportmidi_JPortMidiApi_PM_FILT_SYSTEMCOMMON
51#define jportmidi_JPortMidiApi_PM_FILT_SYSTEMCOMMON 78L
52/*
53 * Class: jportmidi_JPortMidiApi
54 * Method: Pm_Initialize
55 * Signature: ()I
56 */
57JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1Initialize
58 (JNIEnv *, jclass);
59
60/*
61 * Class: jportmidi_JPortMidiApi
62 * Method: Pm_Terminate
63 * Signature: ()I
64 */
65JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1Terminate
66 (JNIEnv *, jclass);
67
68/*
69 * Class: jportmidi_JPortMidiApi
70 * Method: Pm_HasHostError
71 * Signature: (Ljportmidi/JPortMidiApi/PortMidiStream;)I
72 */
73JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1HasHostError
74 (JNIEnv *, jclass, jobject);
75
76/*
77 * Class: jportmidi_JPortMidiApi
78 * Method: Pm_GetErrorText
79 * Signature: (I)Ljava/lang/String;
80 */
81JNIEXPORT jstring JNICALL Java_jportmidi_JPortMidiApi_Pm_1GetErrorText
82 (JNIEnv *, jclass, jint);
83
84/*
85 * Class: jportmidi_JPortMidiApi
86 * Method: Pm_GetHostErrorText
87 * Signature: ()Ljava/lang/String;
88 */
89JNIEXPORT jstring JNICALL Java_jportmidi_JPortMidiApi_Pm_1GetHostErrorText
90 (JNIEnv *, jclass);
91
92/*
93 * Class: jportmidi_JPortMidiApi
94 * Method: Pm_CountDevices
95 * Signature: ()I
96 */
97JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1CountDevices
98 (JNIEnv *, jclass);
99
100/*
101 * Class: jportmidi_JPortMidiApi
102 * Method: Pm_GetDefaultInputDeviceID
103 * Signature: ()I
104 */
105JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1GetDefaultInputDeviceID
106 (JNIEnv *, jclass);
107
108/*
109 * Class: jportmidi_JPortMidiApi
110 * Method: Pm_GetDefaultOutputDeviceID
111 * Signature: ()I
112 */
113JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1GetDefaultOutputDeviceID
114 (JNIEnv *, jclass);
115
116/*
117 * Class: jportmidi_JPortMidiApi
118 * Method: Pm_GetDeviceInterf
119 * Signature: (I)Ljava/lang/String;
120 */
121JNIEXPORT jstring JNICALL Java_jportmidi_JPortMidiApi_Pm_1GetDeviceInterf
122 (JNIEnv *, jclass, jint);
123
124/*
125 * Class: jportmidi_JPortMidiApi
126 * Method: Pm_GetDeviceName
127 * Signature: (I)Ljava/lang/String;
128 */
129JNIEXPORT jstring JNICALL Java_jportmidi_JPortMidiApi_Pm_1GetDeviceName
130 (JNIEnv *, jclass, jint);
131
132/*
133 * Class: jportmidi_JPortMidiApi
134 * Method: Pm_GetDeviceInput
135 * Signature: (I)Z
136 */
137JNIEXPORT jboolean JNICALL Java_jportmidi_JPortMidiApi_Pm_1GetDeviceInput
138 (JNIEnv *, jclass, jint);
139
140/*
141 * Class: jportmidi_JPortMidiApi
142 * Method: Pm_GetDeviceOutput
143 * Signature: (I)Z
144 */
145JNIEXPORT jboolean JNICALL Java_jportmidi_JPortMidiApi_Pm_1GetDeviceOutput
146 (JNIEnv *, jclass, jint);
147
148/*
149 * Class: jportmidi_JPortMidiApi
150 * Method: Pm_OpenInput
151 * Signature: (Ljportmidi/JPortMidiApi/PortMidiStream;ILjava/lang/String;I)I
152 */
153JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1OpenInput
154 (JNIEnv *, jclass, jobject, jint, jstring, jint);
155
156/*
157 * Class: jportmidi_JPortMidiApi
158 * Method: Pm_OpenOutput
159 * Signature: (Ljportmidi/JPortMidiApi/PortMidiStream;ILjava/lang/String;II)I
160 */
161JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1OpenOutput
162 (JNIEnv *, jclass, jobject, jint, jstring, jint, jint);
163
164/*
165 * Class: jportmidi_JPortMidiApi
166 * Method: Pm_SetFilter
167 * Signature: (Ljportmidi/JPortMidiApi/PortMidiStream;I)I
168 */
169JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1SetFilter
170 (JNIEnv *, jclass, jobject, jint);
171
172/*
173 * Class: jportmidi_JPortMidiApi
174 * Method: Pm_SetChannelMask
175 * Signature: (Ljportmidi/JPortMidiApi/PortMidiStream;I)I
176 */
177JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1SetChannelMask
178 (JNIEnv *, jclass, jobject, jint);
179
180/*
181 * Class: jportmidi_JPortMidiApi
182 * Method: Pm_Abort
183 * Signature: (Ljportmidi/JPortMidiApi/PortMidiStream;)I
184 */
185JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1Abort
186 (JNIEnv *, jclass, jobject);
187
188/*
189 * Class: jportmidi_JPortMidiApi
190 * Method: Pm_Close
191 * Signature: (Ljportmidi/JPortMidiApi/PortMidiStream;)I
192 */
193JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1Close
194 (JNIEnv *, jclass, jobject);
195
196/*
197 * Class: jportmidi_JPortMidiApi
198 * Method: Pm_Read
199 * Signature: (Ljportmidi/JPortMidiApi/PortMidiStream;Ljportmidi/JPortMidiApi/PmEvent;)I
200 */
201JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1Read
202 (JNIEnv *, jclass, jobject, jobject);
203
204/*
205 * Class: jportmidi_JPortMidiApi
206 * Method: Pm_Poll
207 * Signature: (Ljportmidi/JPortMidiApi/PortMidiStream;)I
208 */
209JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1Poll
210 (JNIEnv *, jclass, jobject);
211
212/*
213 * Class: jportmidi_JPortMidiApi
214 * Method: Pm_Write
215 * Signature: (Ljportmidi/JPortMidiApi/PortMidiStream;Ljportmidi/JPortMidiApi/PmEvent;)I
216 */
217JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1Write
218 (JNIEnv *, jclass, jobject, jobject);
219
220/*
221 * Class: jportmidi_JPortMidiApi
222 * Method: Pm_WriteShort
223 * Signature: (Ljportmidi/JPortMidiApi/PortMidiStream;II)I
224 */
225JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1WriteShort
226 (JNIEnv *, jclass, jobject, jint, jint);
227
228/*
229 * Class: jportmidi_JPortMidiApi
230 * Method: Pm_WriteSysEx
231 * Signature: (Ljportmidi/JPortMidiApi/PortMidiStream;I[B)I
232 */
233JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1WriteSysEx
234 (JNIEnv *, jclass, jobject, jint, jbyteArray);
235
236/*
237 * Class: jportmidi_JPortMidiApi
238 * Method: Pt_TimeStart
239 * Signature: (I)I
240 */
241JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pt_1TimeStart
242 (JNIEnv *, jclass, jint);
243
244/*
245 * Class: jportmidi_JPortMidiApi
246 * Method: Pt_TimeStop
247 * Signature: ()I
248 */
249JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pt_1TimeStop
250 (JNIEnv *, jclass);
251
252/*
253 * Class: jportmidi_JPortMidiApi
254 * Method: Pt_Time
255 * Signature: ()I
256 */
257JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pt_1Time
258 (JNIEnv *, jclass);
259
260/*
261 * Class: jportmidi_JPortMidiApi
262 * Method: Pt_TimeStarted
263 * Signature: ()Z
264 */
265JNIEXPORT jboolean JNICALL Java_jportmidi_JPortMidiApi_Pt_1TimeStarted
266 (JNIEnv *, jclass);
267
268#ifdef __cplusplus
269}
270#endif
271#endif
272/* Header for class jportmidi_JPortMidiApi_PmEvent */
273
274#ifndef _Included_jportmidi_JPortMidiApi_PmEvent
275#define _Included_jportmidi_JPortMidiApi_PmEvent
276#ifdef __cplusplus
277extern "C" {
278#endif
279#ifdef __cplusplus
280}
281#endif
282#endif
283/* Header for class jportmidi_JPortMidiApi_PortMidiStream */
284
285#ifndef _Included_jportmidi_JPortMidiApi_PortMidiStream
286#define _Included_jportmidi_JPortMidiApi_PortMidiStream
287#ifdef __cplusplus
288extern "C" {
289#endif
290#ifdef __cplusplus
291}
292#endif
293#endif
diff --git a/portmidi/pm_java/pmjni/pmjni.c b/portmidi/pm_java/pmjni/pmjni.c
new file mode 100644
index 0000000..c60cffb
--- /dev/null
+++ b/portmidi/pm_java/pmjni/pmjni.c
@@ -0,0 +1,354 @@
1#include "portmidi.h"
2#include "porttime.h"
3#include "jportmidi_JportMidiApi.h"
4#include <stdio.h>
5
6// these macros assume JNIEnv *env is declared and valid:
7//
8#define CLASS(c, obj) jclass c = (*env)->GetObjectClass(env, obj)
9#define ADDRESS_FID(fid, c) \
10 jfieldID fid = (*env)->GetFieldID(env, c, "address", "J")
11// Uses Java Long (64-bit) to make sure there is room to store a
12// pointer. Cast this to a C long (either 32 or 64 bit) to match
13// the size of a pointer. Finally cast int to pointer. All this
14// is supposed to avoid C compiler warnings and (worse) losing
15// address bits.
16#define PMSTREAM(obj, fid) ((PmStream *) (intptr_t) (*env)->GetLongField(env, obj, fid))
17// Cast stream to long to convert integer to pointer, then expand
18// integer to 64-bit jlong. This avoids compiler warnings.
19#define SET_PMSTREAM(obj, fid, stream) \
20 (*env)->SetLongField(env, obj, fid, (jlong) (intptr_t) stream)
21
22
23/*
24 * Method: Pm_Initialize
25 */
26JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1Initialize
27 (JNIEnv *env, jclass cl)
28{
29 return Pm_Initialize();
30}
31
32
33/*
34 * Method: Pm_Terminate
35 */
36JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1Terminate
37 (JNIEnv *env, jclass cl)
38{
39 return Pm_Terminate();
40}
41
42
43/*
44 * Method: Pm_HasHostError
45 */
46JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1HasHostError
47 (JNIEnv *env, jclass cl, jobject jstream)
48{
49 CLASS(c, jstream);
50 ADDRESS_FID(fid, c);
51 return Pm_HasHostError(PMSTREAM(jstream, fid));
52}
53
54
55/*
56 * Method: Pm_GetErrorText
57 */
58JNIEXPORT jstring JNICALL Java_jportmidi_JPortMidiApi_Pm_1GetErrorText
59 (JNIEnv *env, jclass cl, jint i)
60{
61 return (*env)->NewStringUTF(env, Pm_GetErrorText(i));
62}
63
64
65/*
66 * Method: Pm_GetHostErrorText
67 */
68JNIEXPORT jstring JNICALL Java_jportmidi_JPortMidiApi_Pm_1GetHostErrorText
69 (JNIEnv *env, jclass cl)
70{
71 char msg[PM_HOST_ERROR_MSG_LEN];
72 Pm_GetHostErrorText(msg, PM_HOST_ERROR_MSG_LEN);
73 return (*env)->NewStringUTF(env, msg);
74}
75
76
77/*
78 * Method: Pm_CountDevices
79 */
80JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1CountDevices
81 (JNIEnv *env, jclass cl)
82{
83 return Pm_CountDevices();
84}
85
86
87/*
88 * Method: Pm_GetDefaultInputDeviceID
89 */
90JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1GetDefaultInputDeviceID
91 (JNIEnv *env, jclass cl)
92{
93 return Pm_GetDefaultInputDeviceID();
94}
95
96
97/*
98 * Method: Pm_GetDefaultOutputDeviceID
99 */
100JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1GetDefaultOutputDeviceID
101 (JNIEnv *env, jclass cl)
102{
103 return Pm_GetDefaultOutputDeviceID();
104}
105
106
107/*
108 * Method: Pm_GetDeviceInterf
109 */
110JNIEXPORT jstring JNICALL Java_jportmidi_JPortMidiApi_Pm_1GetDeviceInterf
111 (JNIEnv *env, jclass cl, jint i)
112{
113 const PmDeviceInfo *info = Pm_GetDeviceInfo(i);
114 if (!info) return NULL;
115 return (*env)->NewStringUTF(env, info->interf);
116}
117
118
119/*
120 * Method: Pm_GetDeviceName
121 */
122JNIEXPORT jstring JNICALL Java_jportmidi_JPortMidiApi_Pm_1GetDeviceName
123 (JNIEnv *env, jclass cl, jint i)
124{
125 const PmDeviceInfo *info = Pm_GetDeviceInfo(i);
126 if (!info) return NULL;
127 return (*env)->NewStringUTF(env, info->name);
128}
129
130
131/*
132 * Method: Pm_GetDeviceInput
133 */
134JNIEXPORT jboolean JNICALL Java_jportmidi_JPortMidiApi_Pm_1GetDeviceInput
135 (JNIEnv *env, jclass cl, jint i)
136{
137 const PmDeviceInfo *info = Pm_GetDeviceInfo(i);
138 if (!info) return (jboolean) 0;
139 return (jboolean) info->input;
140}
141
142
143/*
144 * Method: Pm_GetDeviceOutput
145 */
146JNIEXPORT jboolean JNICALL Java_jportmidi_JPortMidiApi_Pm_1GetDeviceOutput
147 (JNIEnv *env, jclass cl, jint i)
148{
149 const PmDeviceInfo *info = Pm_GetDeviceInfo(i);
150 if (!info) return (jboolean) 0;
151 return (jboolean) info->output;
152}
153
154
155/*
156 * Method: Pm_OpenInput
157 */
158JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1OpenInput
159 (JNIEnv *env, jclass cl,
160 jobject jstream, jint index, jstring extras, jint bufsiz)
161{
162 PmError rslt;
163 PortMidiStream *stream;
164 CLASS(c, jstream);
165 ADDRESS_FID(fid, c);
166 rslt = Pm_OpenInput(&stream, index, NULL, bufsiz, NULL, NULL);
167 SET_PMSTREAM(jstream, fid, stream);
168 return rslt;
169}
170
171
172/*
173 * Method: Pm_OpenOutput
174 */
175JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1OpenOutput
176 (JNIEnv *env, jclass cl, jobject jstream, jint index, jstring extras,
177 jint bufsiz, jint latency)
178{
179 PmError rslt;
180 PortMidiStream *stream;
181 CLASS(c, jstream);
182 ADDRESS_FID(fid, c);
183 rslt = Pm_OpenOutput(&stream, index, NULL, bufsiz, NULL, NULL, latency);
184 SET_PMSTREAM(jstream, fid, stream);
185 return rslt;
186}
187
188
189/*
190 * Method: Pm_SetFilter
191 */
192JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1SetFilter
193 (JNIEnv *env, jclass cl, jobject jstream, jint filters)
194{
195 CLASS(c, jstream);
196 ADDRESS_FID(fid, c);
197 return Pm_SetFilter(PMSTREAM(jstream, fid), filters);
198}
199
200
201/*
202 * Method: Pm_SetChannelMask
203 */
204JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1SetChannelMask
205 (JNIEnv *env, jclass cl, jobject jstream, jint mask)
206{
207 CLASS(c, jstream);
208 ADDRESS_FID(fid, c);
209 return Pm_SetChannelMask(PMSTREAM(jstream, fid), mask);
210}
211
212
213/*
214 * Method: Pm_Abort
215 */
216JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1Abort
217 (JNIEnv *env, jclass cl, jobject jstream)
218{
219 CLASS(c, jstream);
220 ADDRESS_FID(fid, c);
221 return Pm_Abort(PMSTREAM(jstream, fid));
222}
223
224
225/*
226 * Method: Pm_Close
227 */
228JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1Close
229 (JNIEnv *env, jclass cl, jobject jstream)
230{
231 CLASS(c, jstream);
232 ADDRESS_FID(fid, c);
233 return Pm_Close(PMSTREAM(jstream, fid));
234}
235
236
237/*
238 * Method: Pm_Read
239 */
240JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1Read
241 (JNIEnv *env, jclass cl, jobject jstream, jobject jpmevent)
242{
243 CLASS(jstream_class, jstream);
244 ADDRESS_FID(address_fid, jstream_class);
245 jclass jpmevent_class = (*env)->GetObjectClass(env, jpmevent);
246 jfieldID message_fid =
247 (*env)->GetFieldID(env, jpmevent_class, "message", "I");
248 jfieldID timestamp_fid =
249 (*env)->GetFieldID(env, jpmevent_class, "timestamp", "I");
250 PmEvent buffer;
251 PmError rslt = Pm_Read(PMSTREAM(jstream, address_fid), &buffer, 1);
252 (*env)->SetIntField(env, jpmevent, message_fid, buffer.message);
253 (*env)->SetIntField(env, jpmevent, timestamp_fid, buffer.timestamp);
254 return rslt;
255}
256
257
258/*
259 * Method: Pm_Poll
260 */
261JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1Poll
262 (JNIEnv *env, jclass cl, jobject jstream)
263{
264 CLASS(c, jstream);
265 ADDRESS_FID(fid, c);
266 return Pm_Poll(PMSTREAM(jstream, fid));
267}
268
269
270/*
271 * Method: Pm_Write
272 */
273JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1Write
274 (JNIEnv *env, jclass cl, jobject jstream, jobject jpmevent)
275{
276 CLASS(jstream_class, jstream);
277 ADDRESS_FID(address_fid, jstream_class);
278 jclass jpmevent_class = (*env)->GetObjectClass(env, jpmevent);
279 jfieldID message_fid =
280 (*env)->GetFieldID(env, jpmevent_class, "message", "I");
281 jfieldID timestamp_fid =
282 (*env)->GetFieldID(env, jpmevent_class, "timestamp", "I");
283 // note that we call WriteShort because it's simpler than constructing
284 // a buffer and passing it to Pm_Write
285 return Pm_WriteShort(PMSTREAM(jstream, address_fid),
286 (*env)->GetIntField(env, jpmevent, timestamp_fid),
287 (*env)->GetIntField(env, jpmevent, message_fid));
288}
289
290
291/*
292 * Method: Pm_WriteShort
293 */
294JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1WriteShort
295 (JNIEnv *env, jclass cl, jobject jstream, jint when, jint msg)
296{
297 CLASS(c, jstream);
298 ADDRESS_FID(fid, c);
299 return Pm_WriteShort(PMSTREAM(jstream, fid), when, msg);
300}
301
302
303/*
304 * Method: Pm_WriteSysEx
305 */
306JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pm_1WriteSysEx
307 (JNIEnv *env, jclass cl, jobject jstream, jint when, jbyteArray jmsg)
308{
309 CLASS(c, jstream);
310 ADDRESS_FID(fid, c);
311 jbyte *bytes = (*env)->GetByteArrayElements(env, jmsg, 0);
312 PmError rslt = Pm_WriteSysEx(PMSTREAM(jstream, fid), when,
313 (unsigned char *) bytes);
314 (*env)->ReleaseByteArrayElements(env, jmsg, bytes, 0);
315 return rslt;
316}
317
318/*
319 * Method: Pt_TimeStart
320 */
321JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pt_1TimeStart
322 (JNIEnv *env, jclass c, jint resolution)
323{
324 return Pt_Start(resolution, NULL, NULL);
325}
326
327/*
328 * Method: Pt_TimeStop
329 */
330JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pt_1TimeStop
331 (JNIEnv *env, jclass c)
332 {
333 return Pt_Stop();
334 }
335
336/*
337 * Method: Pt_Time
338 */
339JNIEXPORT jint JNICALL Java_jportmidi_JPortMidiApi_Pt_1Time
340 (JNIEnv *env, jclass c)
341 {
342 return Pt_Time();
343 }
344
345/*
346 * Method: Pt_TimeStarted
347 */
348JNIEXPORT jboolean JNICALL Java_jportmidi_JPortMidiApi_Pt_1TimeStarted
349 (JNIEnv *env, jclass c)
350{
351 return Pt_Started();
352}
353
354
diff --git a/portmidi/pm_java/pmjni/pmjni.rc b/portmidi/pm_java/pmjni/pmjni.rc
new file mode 100644
index 0000000..1b7522b
--- /dev/null
+++ b/portmidi/pm_java/pmjni/pmjni.rc
@@ -0,0 +1,63 @@
1// Microsoft Visual C++ generated resource script.
2//
3#include "resource.h"
4
5#define APSTUDIO_READONLY_SYMBOLS
6/////////////////////////////////////////////////////////////////////////////
7//
8// Generated from the TEXTINCLUDE 2 resource.
9//
10#include "afxres.h"
11
12/////////////////////////////////////////////////////////////////////////////
13#undef APSTUDIO_READONLY_SYMBOLS
14
15/////////////////////////////////////////////////////////////////////////////
16// English (U.S.) resources
17
18#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
19#ifdef _WIN32
20LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
21#pragma code_page(1252)
22#endif //_WIN32
23
24#ifdef APSTUDIO_INVOKED
25/////////////////////////////////////////////////////////////////////////////
26//
27// TEXTINCLUDE
28//
29
301 TEXTINCLUDE
31BEGIN
32 "resource.h\0"
33END
34
352 TEXTINCLUDE
36BEGIN
37 "#include ""afxres.h""\r\n"
38 "\0"
39END
40
413 TEXTINCLUDE
42BEGIN
43 "\r\n"
44 "\0"
45END
46
47#endif // APSTUDIO_INVOKED
48
49#endif // English (U.S.) resources
50/////////////////////////////////////////////////////////////////////////////
51
52
53
54#ifndef APSTUDIO_INVOKED
55/////////////////////////////////////////////////////////////////////////////
56//
57// Generated from the TEXTINCLUDE 3 resource.
58//
59
60
61/////////////////////////////////////////////////////////////////////////////
62#endif // not APSTUDIO_INVOKED
63