/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#define USE_ERROR
#define USE_TRACE
/* include Java Sound specific headers as C code */
extern "C" {
#include "PLATFORM_API_WinOS_Util.h"
}
#if USE_PLATFORM_MIDI_IN == TRUE
#ifdef USE_ERROR
#include <stdio.h>
#define MIDIIN_CHECK_ERROR { \
if (err != MMSYSERR_NOERROR) \
}
#else
#define MIDIIN_CHECK_ERROR
#endif
/*
* Callback from the MIDI device for all messages.
*/
//$$fb dwParam1 holds a pointer for long messages. How can that be a DWORD then ???
void CALLBACK MIDI_IN_PutMessage( HMIDIIN hMidiIn, UINT wMsg, UINT_PTR dwInstance, UINT_PTR dwParam1, UINT_PTR dwParam2 ) {
switch(wMsg) {
case MIM_OPEN:
TRACE0("< MIDI_IN_PutMessage: MIM_OPEN\n");
break;
case MIM_CLOSE:
TRACE0("< MIDI_IN_PutMessage: MIM_CLOSE\n");
break;
case MIM_MOREDATA:
case MIM_DATA:
TRACE3(" MIDI_IN_PutMessage: MIM_MOREDATA or MIM_DATA. status=%x data1=%x data2=%x\n",
// queue stores packedMsg in big endian
//(dwParam1 << 24) | ((dwParam1 << 8) & 0xFF0000) | ((dwParam1 >> 8) & 0xFF00),
// queue uses microseconds
// overwrite if queue is full
TRUE);
}
TRACE0("< MIDI_IN_PutMessage\n");
break;
case MIM_LONGDATA:
TRACE1(" MIDI_IN_PutMessage: MIM_LONGDATA (%d bytes recorded)\n", (int) (((MIDIHDR*) dwParam1)->dwBytesRecorded));
TRACE2(" MIDI_IN_PutMessage: Adding to queue: index %d, %d bytes\n", (INT32) hdr->dwUser, hdr->dwBytesRecorded);
// sysex buffer index
// queue uses microseconds
// overwrite if queue is full
TRUE);
}
TRACE0("< MIDI_IN_PutMessage\n");
break;
case MIM_ERROR:
ERROR0("< MIDI_IN_PutMessage: MIM_ERROR!\n");
break;
case MIM_LONGERROR:
if (dwParam1 != 0) {
#ifdef USE_TRACE
if (hdr->dwBytesRecorded > 0) {
TRACE2(" MIDI_IN_PutMessage: MIM_LONGERROR! recorded: %d bytes with status 0x%2x\n",
}
#endif
// re-add hdr to device query
hdr->dwBytesRecorded = 0;
}
ERROR0("< MIDI_IN_PutMessage: MIM_LONGERROR!\n");
break;
default:
break;
} // switch (wMsg)
}
/*
** (joint into MidiIn_OpenHelper class)
** see 6415669 - MidiIn device stops work and crushes JVM after exiting
** from thread that has open the device (it looks like WinMM bug).
*/
class MidiIn_OpenHelper {
public:
/* opens MidiIn device */
/* checks for initialization success */
protected:
/* data class */
class Data {
public:
Data();
~Data();
// public data to access from parent class
// data to process; (handle == null) is command to thread terminating
} static data;
/* StartThread function */
};
/* MidiIn_OpenHelper class implementation
*/
threadHandle = NULL;
}
if (threadHandle != NULL) {
// terminate thread
threadHandle = NULL;
}
// - Windows will do during process shutdown
}
while (1) {
// wait for something to do
// (data.handle == NULL) is a signal to terminate thread
break;
}
}
return 0;
}
if (!isInitialized()) {
return MMSYSERR_ERROR;
}
return err;
}
// PLATFORM_MIDI_IN method implementations
/* not thread safe */
winMidiInErrMsg[0] = 0;
return winMidiInErrMsg;
}
return (INT32) midiInGetNumDevs();
}
return ((*err) == MMSYSERR_NOERROR);
}
return MIDI_SUCCESS;
}
return err;
}
return MIDI_NOT_SUPPORTED;
}
return MIDI_NOT_SUPPORTED;
}
sprintf(name, "%d.%d", (midiInCaps.vDriverVersion & 0xFF00) >> 8, midiInCaps.vDriverVersion & 0xFF);
return MIDI_SUCCESS;
}
return err;
}
int i;
ERROR0("MIDI_IN_prepareBuffers: handle, or longBuffers, or deviceHandle==NULL\n");
return MIDI_INVALID_HANDLE;
}
}
}
int i;
ERROR0("MIDI_IN_unprepareBuffers: handle, or longBuffers, or deviceHandle==NULL\n");
return MIDI_INVALID_HANDLE;
}
}
}
TRACE0("> MIDI_IN_OpenDevice\n");
#ifdef USE_ERROR
#endif
if (!(*handle)) {
ERROR0("< ERROR: MIDI_IN_OpenDevice: out of memory\n");
return MIDI_OUT_OF_MEMORY;
}
// create queue
ERROR0("< ERROR: MIDI_IN_OpenDevice: could not create queue\n");
return MIDI_OUT_OF_MEMORY;
}
// create long buffer queue
if (!MIDI_WinCreateLongBufferQueue(*handle, MIDI_IN_LONG_QUEUE_SIZE, MIDI_IN_LONG_MESSAGE_SIZE, NULL)) {
ERROR0("< ERROR: MIDI_IN_OpenDevice: could not create long Buffers\n");
return MIDI_OUT_OF_MEMORY;
}
// finally open the device
}
TRACE0("< MIDI_IN_OpenDevice: midiInOpen succeeded\n");
return MIDI_SUCCESS;
}
TRACE0("> MIDI_IN_CloseDevice: midiInClose\n");
if (!handle) {
ERROR0("ERROR: MIDI_IN_CloseDevice: handle is NULL\n");
return MIDI_INVALID_HANDLE;
}
}
TRACE0("< MIDI_IN_CloseDevice: midiInClose succeeded\n");
}
ERROR0("ERROR: MIDI_IN_StartDevice: handle or queue is NULL\n");
return MIDI_INVALID_HANDLE;
}
// clear all the events from the queue
if (!handle->platformData) {
ERROR0("ERROR: MIDI_IN_StartDevice: could not create event\n");
return MIDI_OUT_OF_MEMORY;
}
/* $$mp 200308-11: This method is already called in ...open(). It is
unclear why is is called again. The specification says that
MidiDevice.getMicrosecondPosition() returns the time since the
So I guess this call is obsolete. */
TRACE0("MIDI_IN_StartDevice: midiInStart finished\n");
}
TRACE0("> MIDI_IN_StopDevice: midiInStop \n");
ERROR0("ERROR: MIDI_IN_StopDevice: handle or event is NULL\n");
return MIDI_INVALID_HANDLE;
}
// encourage MIDI_IN_GetMessage to return soon
// wait until the Java thread has exited
TRACE0("< MIDI_IN_StopDevice: midiInStop finished\n");
}
/* return time stamp in microseconds */
return MIDI_GetTimeStamp(handle);
}
// read the next message from the queue
return NULL;
}
//fprintf(stdout, "GetMessage returns index %d\n", msg->data.l.index); fflush(stdout);
return msg;
}
TRACE0("MIDI_IN_GetMessage: before waiting\n");
if (res == WAIT_TIMEOUT) {
// break out back to Java from time to time - just to be sure
TRACE0("MIDI_IN_GetMessage: waiting finished with timeout\n");
break;
}
TRACE0("MIDI_IN_GetMessage: waiting finished\n");
}
return NULL;
}
return;
}
//fprintf(stdout, "ReleaseMessage index %d\n", msg->data.l.index); fflush(stdout);
hdr->dwBytesRecorded = 0;
}
}
#endif // USE_PLATFORM_MIDI_IN