Ok a quick hack, hope this helps. Really needs someone to make this into a module Brucey?
Download portmidi28aug06 and place it inside your project.
main.bmx
sysex.cpp
Download portmidi28aug06 and place it inside your project.
main.bmx
Strict Import "portmidi28aug06/porttime/*.h" Import "portmidi28aug06/porttime/porttime.c" Import "portmidi28aug06/pm_common/*.h" Import "portmidi28aug06/pm_common/portmidi.c" ?Win32 Import "portmidi28aug06/porttime/ptwinmm.c" Import "portmidi28aug06/pm_win/*.h" Import "portmidi28aug06/pm_win/pmwin.c" Import "portmidi28aug06/pm_win/pmdll.c" Import "portmidi28aug06/pm_win/pmwinmm.c" Import "sysex.cpp" Framework brl.d3d7max2d ?MacOS ?Linux ? Extern "C" ' sysex.cpp Global OutputDevice:Int Global InputDevice:Int Global LoopbackInputDevice:Int Global LoopbackOutputDevice:Int Global midi_message:Byte[] Function midi_open:Int() Function midi_close:Int() Function midi_test:Byte Ptr() Function loopback_open:Int() Function loopback_close:Int() Function loopback_test:Int() Function get_midi_in() Function get_midi_out() Function sysex_receive_open:Int() Function sysex_receive_get:Byte Ptr() Function sysex_receive_close:Int() Function sysex_send( message:Byte Ptr ) Function sysex_send_receive:Byte Ptr( message:Byte Ptr ) Function sysex_initalise() Function sysex_set_device:Int( device:Byte Ptr, dir:Int ) Function sysex_get_next_device:String( nxt:Int, dir:Int ) Function sysex_get_number_of_devices:Int() Function sysex_finalise() End Extern Global device_enquiry:Byte[]=[ Byte($F0),Byte($7E),Byte($00),Byte($06),Byte($01),Byte($F7) ] sysex_initalise() Delay(1000) ' List input / output devices For Local i:Int=0 To sysex_get_number_of_devices()-1 If sysex_get_next_device(i,True) = "" Else DebugLog "Output Device [" + i + "] = " + sysex_get_next_device(i,True) EndIf If sysex_get_next_device(i,False) = "" Else DebugLog "Input Device [" + i + "] = " + sysex_get_next_device(i,False) EndIf Next ' Change these to correct values for your setup. InputDevice = 2 OutputDevice = 5 ' If sysex_get_next_device( InputDevice , False ) = "" If Not Confirm( "No compatible MIDI input device selected, Continue?", True ) Return False EndIf EndIf ' If sysex_get_next_device( OutputDevice, True ) = "" If Not Confirm( "No compatible MIDI output device selected, Continue?", True ) Return False EndIf EndIf Global bp:Byte Ptr bp = sysex_send_receive(device_enquiry) ' For Local i:Int=0 To 4 DebugLog "bp[i] = " + bp[i] Next ' If bp[0]=$F0 And bp[1]=$7E And bp[2]=$00 And bp[3]=$06 And bp[4]=$02 ' Valid responce to device enquiry? ' Notify( "Correct responce from device enquiry" ) Else ' Notify( "Invalid response from DeviceEnquiry(), Retry?", False ) EndIf sysex_finalise() End
sysex.cpp
#include "stdio.h" #include "stdlib.h" #include "assert.h" #include "string.h" #include "portmidi28aug06/pm_common/portmidi.h" #include "portmidi28aug06/porttime/porttime.h" extern "C" { #define MIDI_SYSEX 0xf0 #define MIDI_EOX 0xf7 #define STRING_MAX 80 #define MIDI_MESSAGE_SIZE 1024 #define is_real_time_msg(msg) ((0xF0 & Pm_MessageStatus(msg)) == 0xF8) int InputDevice; int OutputDevice; int LoopbackInputDevice; int LoopbackOutputDevice; unsigned char midi_message[MIDI_MESSAGE_SIZE]; #define INPUT_BUFFER_SIZE 100 #define OUTPUT_BUFFER_SIZE 0 #define DRIVER_INFO NULL #define TIME_PROC ((long (*)(void *)) Pt_Time) #define TIME_INFO NULL #define TIME_START Pt_Start(1, 0, 0) /* timer started w/millisecond accuracy */ PmStream *midiIn = NULL; PmStream *midiOut = NULL; //char dummy[256]; PmStream *midi_in_stream; // ---------------------------------------------------------- // Reset the message buffer // ---------------------------------------------------------- void reset_message( void ) // ---------------------------------------------------------- { //return; int i; for ( i=0; i<MIDI_MESSAGE_SIZE; i++ ) { midi_message[i] = 0; } } // ---------------------------------------------------------- // Open the MIDI ports // ---------------------------------------------------------- bool midi_open( void ) // ---------------------------------------------------------- { //return true; // Pm_OpenInput( &midi_in_stream, InputDevice, DRIVER_INFO, INPUT_BUFFER_SIZE, TIME_PROC, TIME_INFO ); // if ( midi_in_stream != NULL ) { return true; } return false; } // ---------------------------------------------------------- // Close the MIDI ports // ---------------------------------------------------------- bool midi_close( void ) // ---------------------------------------------------------- { //return true; // if ( midi_in_stream != NULL) { Pm_Close(midi_in_stream); midi_in_stream = NULL; return true; } else { return false; } } // ---------------------------------------------------------- // Read a short message // ---------------------------------------------------------- signed char *midi_test( void ) // ---------------------------------------------------------- { //return true; PmEvent buffer[1]; PmError status, length; // status = Pm_Poll( midi_in_stream ); if ( status == true ) { reset_message(); length = Pm_Read( midi_in_stream, buffer, 1 ); if ( length > 0 ) { midi_message[0] = Pm_MessageStatus( buffer[0].message ); midi_message[1] = Pm_MessageData1( buffer[0].message ); midi_message[2] = Pm_MessageData2( buffer[0].message ); // printf("Got message: time %ld, %2lx %2lx %2lx\n", // buffer[0].timestamp, // midi_message[0] = Pm_MessageStatus( buffer[0].message ), // Pm_MessageData1( buffer[0].message ), // Pm_MessageData2( buffer[0].message )); // if ( Pm_MessageData1( buffer[0].message ) == 31 && Pm_MessageData2(buffer[0].message ) == 64 ) return true; return (signed char *)midi_message; } } return NULL; } // ---------------------------------------------------------- // Open the MIDI loopback ports // ---------------------------------------------------------- bool loopback_open() // ---------------------------------------------------------- { //return true; // Pm_OpenOutput( &midiOut, LoopbackOutputDevice, DRIVER_INFO, OUTPUT_BUFFER_SIZE, NULL, NULL, 0 ); // Pm_OpenInput( &midiIn, LoopbackInputDevice, DRIVER_INFO, INPUT_BUFFER_SIZE, TIME_PROC, TIME_INFO ); // if ( ( midiOut != NULL ) && ( midiIn != NULL ) ) { // // Pm_SetFilter( midiIn, PM_FILT_ACTIVE | PM_FILT_CLOCK ); // empty the buffer after setting filter, just in case anything got through. // while (Pm_Poll(midiIn)) { // Pm_Read( midiIn, buffer, 1 ); // } return true; } return false; } // ---------------------------------------------------------- // Close the MIDI loopback ports // ---------------------------------------------------------- bool loopback_close() // ---------------------------------------------------------- { //return true; // if ( midiOut != NULL ) { Pm_Close(midiOut); midiOut = NULL; if ( midiIn != NULL) { Pm_Close(midiIn); midiIn = NULL; return true; } else { return false; } } else { return false; } } // ---------------------------------------------------------- // Write a short message then poll for a returned message // ---------------------------------------------------------- bool loopback_test() // ---------------------------------------------------------- { //return true; PmEvent buffer[1]; PmError status, length; // Note on Pm_WriteShort( midiOut, TIME_PROC(TIME_INFO), Pm_Message(0x90, 31, 64) ); // Note off // Pm_WriteShort( midiOut, TIME_PROC(TIME_INFO), Pm_Message(0x80, 31, 40) ); // buffer[0].timestamp = TIME_PROC(TIME_INFO); // buffer[0].message = Pm_Message(0x90,31,64); // Pm_Write( midiOut, buffer, 1); // status = Pm_Poll( midiIn ); if ( status == true ) { length = Pm_Read( midiIn, buffer, 1 ); if (length > 0) { // printf("Got message: time %ld, %2lx %2lx %2lx\n", // buffer[0].timestamp, // Pm_MessageStatus( buffer[0].message ), // Pm_MessageData1( buffer[0].message ), // Pm_MessageData2( buffer[0].message )); if ( Pm_MessageData1( buffer[0].message ) == 31 && Pm_MessageData2(buffer[0].message ) == 64 ) return true; } } return false; } // ---------------------------------------------------------- // ---------------------------------------------------------- int get_midi_in( void ) // ---------------------------------------------------------- { //return true; return InputDevice; } // ---------------------------------------------------------- // ---------------------------------------------------------- int get_midi_out( void ) // ---------------------------------------------------------- { //return true; return OutputDevice; } // ---------------------------------------------------------- // ---------------------------------------------------------- void send_sysex( unsigned char *sysex_data ) // ---------------------------------------------------------- { //return; PmStream *midi_out; // Pm_OpenOutput( &midi_out, OutputDevice, DRIVER_INFO, OUTPUT_BUFFER_SIZE, NULL, NULL, 0 ); if ( midi_out != NULL ) { Pm_WriteSysEx( midi_out, 0, sysex_data ); Pm_Close( midi_out ); midi_out = NULL; } } // ---------------------------------------------------------- void receive_sysex( PmStream *midi ) // ---------------------------------------------------------- { //return; int shift = 0; unsigned char data = 0; int bytes_on_line = 0; PmEvent msg; PmError count; // read data and write to file while ( data != MIDI_EOX ) { count = Pm_Read(midi, &msg, 1); // CAUTION: this causes busy waiting. It would be better to // be in a polling loop to avoid being compute bound. PortMidi // does not support a blocking read since this is so seldom useful. if (count == 0) continue; // ignore real-time messages if (is_real_time_msg(Pm_MessageStatus(msg.message))) continue; // write 4 bytes of data until you reach an eox bool done = 0; for ( shift = 0; (shift < 32) && !done /*(data != MIDI_EOX)*/; shift += 8) { data = (msg.message >> shift) & 0xFF; // if this is a status byte that's not MIDI_EOX, the sysex // message is incomplete and there is no more sysex data midi_message[ bytes_on_line ] = data; ++bytes_on_line; done = ( data == MIDI_EOX ); } } } // ---------------------------------------------------------- unsigned char *sysex_send_receive( unsigned char *sysex_data ) // ---------------------------------------------------------- { //return; PmStream *midi_in; PmStream *midi_out; Pm_OpenInput( &midi_in, InputDevice, DRIVER_INFO, INPUT_BUFFER_SIZE, NULL, NULL); Pm_OpenOutput( &midi_out, OutputDevice, DRIVER_INFO, OUTPUT_BUFFER_SIZE, NULL, NULL, 0); if ( midi_out != NULL ) { Pm_WriteSysEx( midi_out, 0, sysex_data ); if ( midi_in != NULL) { reset_message(); receive_sysex( midi_in ); Pm_Close(midi_in); midi_in = NULL; } Pm_Close(midi_out); midi_out = NULL; } return midi_message; } // ---------------------------------------------------------- void sysex_send( unsigned char *message ) // ---------------------------------------------------------- { //return; int i; PmStream *midi_in; PmStream *midi_out; // fprintf( stderr, "opening output\n" ); Pm_OpenOutput( &midi_out, OutputDevice, DRIVER_INFO, OUTPUT_BUFFER_SIZE, NULL, NULL, 0 ); // fprintf( stderr, "opened output\n" ); if ( midi_out != NULL ) { // Pm_WriteSysEx( midi_out, 0, message ); // for( i=0; ( message[i] != MIDI_EOX ); i++ ) { // fprintf( stderr, "message[%d] = %.2x\n", i, message[i] ); // } Pm_Close(midi_out); midi_out = NULL; // fprintf( stderr, "closed output\n" ); } else { fprintf( stderr, "midi_out == NULL\n" ); } } PmStream *midi_in = NULL; // ---------------------------------------------------------- bool sysex_receive_open( void ) // ---------------------------------------------------------- { //return true; Pm_OpenInput( &midi_in, InputDevice, NULL, 512, NULL, NULL ); if ( midi_in != NULL) { return true; } return false; } // ---------------------------------------------------------- unsigned char *sysex_receive_get( void ) // ---------------------------------------------------------- { //return dummy; if ( midi_in != NULL) { if ( Pm_Poll( midi_in ) > 0 ) { reset_message(); receive_sysex( midi_in ); return midi_message; } else { return NULL; } } else { return NULL; } } // ---------------------------------------------------------- bool sysex_receive_close( void ) // ---------------------------------------------------------- { //return true; if ( midi_in != NULL) { Pm_Close(midi_in); midi_in = NULL; return true; } return false; } #if 0 // ---------------------------------------------------------- char *sysex_send_receive( unsigned char *message ) // ---------------------------------------------------------- { //return dummy; reset_message(); send_receive_sysex( message ); return midi_message; } #endif // ---------------------------------------------------------- void sysex_initalise( void ) // ---------------------------------------------------------- { //return; int i; // Pm_Initialize(); #if 0 // list device information for (i = 0; i < Pm_CountDevices(); i++) { const PmDeviceInfo *info = Pm_GetDeviceInfo(i); printf("%d: %s, %s", i, info->interf, info->name); if (info->input) printf(" (input)"); if (info->output) printf(" (output)"); printf("\n"); if ( ( strcmp( info->name, "USB Audio Device" ) == 0 ) && info->output ) { printf( "found output device %d\n", i ); OutputDevice = i; } if ( ( strcmp( info->name, "USB Audio Device" ) == 0 ) && info->input ) { printf( "found input device @ %d\n", i ); InputDevice = i; } if ( ( strcmp( info->name, "USB Audio Device [3]" ) == 0 ) && info->input ) { printf( "found intput loopback device @ %d\n", i ); LoopbackInputDevice = i; } if ( ( strcmp( info->name, "USB Audio Device [2]" ) == 0 ) && info->output ) { printf( "found output loopback device @ %d\n", i ); LoopbackOutputDevice = i; } } #endif // reset_message(); } // ---------------------------------------------------------- int sysex_set_device( char *select, int dir ) // ---------------------------------------------------------- { int i; // list device information for (i = 0; i < Pm_CountDevices(); i++) { const PmDeviceInfo *info = Pm_GetDeviceInfo(i); // printf("%d: %s, %s", i, info->interf, info->name); // if (info->input) printf(" (input)"); // if (info->output) printf(" (output)"); // printf("\n"); if ( dir == true ) { if ( ( strcmp( info->name, select ) == 0 ) && info->output ) { return i; } } else { if ( ( strcmp( info->name, select ) == 0 ) && info->input ) { return i; } } } return -1; } #include <brl.mod/blitz.mod/blitz_string.h> // ---------------------------------------------------------- BBString *sysex_get_next_device( int nxt, int dir ) // ---------------------------------------------------------- { const PmDeviceInfo *info = Pm_GetDeviceInfo( nxt ); // printf( "pointer = %p", info ); // printf("%d: %s, %s", nxt, info->interf, info->name); // if (info->input) printf(" (input)"); // if (info->output) printf(" (output)"); // printf("\n"); if ( info != NULL ) { if ( (dir == true) && info->output ) { return bbStringFromCString(info->name); } if ( (dir == false) && info->input ) { return bbStringFromCString(info->name); } } return bbStringFromCString(""); } // ---------------------------------------------------------- int sysex_get_device_dir( int nxt ) // ---------------------------------------------------------- { int dir = 0; const PmDeviceInfo *info = Pm_GetDeviceInfo( nxt ); if ( info != NULL ) { if ( info->output ) dir |= 1; if ( info->input ) dir |= 2; return dir; } } // ---------------------------------------------------------- int sysex_get_number_of_devices( void ) { // ---------------------------------------------------------- return Pm_CountDevices(); } // ---------------------------------------------------------- void sysex_finalise( void ) // ---------------------------------------------------------- { //return; Pm_Terminate(); } } // extern "C" }