Blitzmax MIDI IN

BlitzMax Forums/BlitzMax Programming/Blitzmax MIDI IN

Anyone know of a way of achieving MIDI IN in blitzmax? I've read the old postings which seem never to have got anywhere, and the FMOD stuff, but no MIDI IN. Anyone planning on doing MIDI stuff for Blitzmax???

This is an interesting idea actually. I am getting more into the MIDI controller scene... never even thought to really write anything for it. A ReWire header would be really cool too...

Use portmidi it works! I have a C wrapper for BlitzMax and If I am able to find some time I will post it.

There was an attempt by Nigel Brown with portMidi, not sure if he succeeded.

EDIT : well it seems so! Just a tad faster than me at posting.

If I have more time I would like to help

I guess, a professionell way is to integrate the Max/MSP Language into BMAX
maybe its possible and then the whole world of MIDI AUDIO and Video is open for BMAX PRogrammers

http://www.cycling74.com/

max/msp isn't language. Second it's closed source, so no hope to "integrate" it. But you can have max/msp and a program compiled in blitzmax talking, through midi, tcp/ip or osc (this one you would have to code it from scratch).

If you are considering making an osc library for blitzmax, I am in.

What level of midi-in do you need?

I have a simple midi in/out mod working. I use it for controller reading/setting.
It does not do sysex dumps and other more tricky stuff.

I am busy at the moment , but if my arm is twisted I could write a demo and make the module public.

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
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" }



Wow - thanks so much for that Nigel- soon as I get a minute (ie. never!) I'm gonna get stuck right in to it. I'm a Blitzmax newbie but very familiar with MIDI, being a musician.

Answer to Zilch: I don't need sysex or MIDI controller stuff for my project, I just need simple note on/off, velocity and pedal data (I'm aiming for Mac and PC versions).

I would go with nigels method then. As my mod only handles windows.

Hello,

In sysex_initialise there is a typo (you'll have to choose in between "sysex_initialise" or "sysex_initalise" without "i".

After that, I have an error building main.bmx...

Building main
Compiling:porttime.c
Compiling:portmidi.c
Compiling:ptwinmm.c
Compiling:pmwin.c
Compiling:pmdll.c
Compiling:pmwinmm.c
Compiling:sysex.cpp
Compiling:main.bmx
flat assembler version 1.66
3 passes, 3348 bytes.
Linking:main.exe
C:/Documents and Settings/jerome/Desktop/portmidi28aug06/portmidi28aug06/pm_win/.bmx/pmdll.c.release.win32.x86.o(.text+0x24):pmdll.c: multiple definition of `DllMain@12'
C:/Program Files/BlitzMax/mod/brl.mod/appstub.mod/appstub.release.win32.x86.a(appstub.win32.c.release.win32.x86.o)(.text+0x172):appstub.win32.c: first defined here
Build Error: Failed to link C:/Documents and Settings/jerome/Desktop/portmidi28aug06/main.exe
Process complete

any body succeeded in compiling this under windows?

Try renaming the DllMain() in \portmidi28aug06\pm_win\pmdll.c to DllMain2()

And using the edited code main.bmx above. This now compiles on my dev system.

Thanks Nigel it compiles. However it fails capturing any Midi in messages and even worst it doesn't close *always* cleanly. I looked at portmidi readme and I tried the #define USE_DLL_FOR_CLEANUP as recommended for windows.

The above example "main.bmx" fails silently on sysex_send_receive. The device detection is working(and I edited input/output device numbers) but I can't get anything working further than that.

I will continue messing up with it...

Could you indicate me how to open a port, and print the incoming messages? I am a bit confused by the wrapped functions... From there I should be able to test it completely.

Thanks

I have uploaded the whole folder including the port MIDI I am using to:

http://www.nigelibrown.pwp.blueyonder.co.uk/blitz/userlibs/index.htm

If you just want to deal exclusivley with MIDI messages then try opening - reading and then closing with something like this:

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

	sysex_initalise()
	Delay(5000)

	' 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

	midi_open()

	Repeat
	
		bp = midi_test()

		If bp <> Null
			DebugLog "status = " + bp[0]
			DebugLog "data1 = " + bp[1]
			DebugLog "data2 = " + bp[2]
			DebugLog ""
		EndIf
	
	Until KeyDown(KEY_ESCAPE)
	
	midi_close()
	

sysex_finalise()

End




Thanks Nigel, with the wrapped version downloaded on your website it works. It still doesn't close correctly all the time, but this could be my setup.

If I ever get enough time I will wrap this as a BMax module. And do things a little more elegantly.

If you need it to do more please let me know, when you say "It still doesn't close correctly all the time" can you be a little more specific so I can try and emulate the same problem here?

Well the problem occurs, when compiling the MIDI.bmx example, closing it pressing escape key, then one minute or 2 latter, recompiling it, it reports than midi.exe or midi.debug.exe is currently in use (so not closed properly although the exe doesn't appear in task manager anymore). It does it but not *always*, I tried a delay before closing bmx program (similar to the one after sysex_initialize), but it still happens "randomly".

My test system is WinXP pro, with a MAudio midisport Uno USB (input 1, output 4 in my setup) and a doepfer pocketdial (I have a Kaoss pad II, and a pocketfader as well but not wired currently).

I want to support Midi controllers principally (on the 3 platforms, from there comes my interest for portmidi), but some of them require midi feedback/ouput (to update a display or a motorized fader for example).

With Blitz3d I did a midichannel based dll (not based on devices), reading/writing midi messages only (the 3 nibbles).

If I ever get enough time I will wrap this as a BMax module.

If I had anything remotely Midi I could test this with, I would have been happy to help with that...

Well I did my Blitz3D dll without Midi Hardware, I was using this software midi controller : http://www.analogx.com/contents/download/audio/mousemod.htm and the virtual piano controller (on the same website) along with Midi-Ox and Midi-Yoke http://www.midiox.com/

I suppose similar soft-midi exist for Linux and MacOS.

LAB[au]

Take a look at BAH modules. Brucey now has a portmidi module available. I will answer any questions that I am able to.

Yeah! It works perfect (didn't tried sysex yet).

I'd like to use Brucey's portmidi package, and it seems to work (just started, but it did find all my midi-devices) but i think i'm having the same prob as Lab[au] described earlier.

Whenever i open a midi-device ( midi.openInput(devicenum) ) the program doesn't want to close anymore. The code after the openInput (which is opening a graphics window and do a while-wend loop on not pressing escape) does run (the window is opened), but pressing escape doesn't do anything. I see the process in my TaskManager, but i cant kill it (the prg-window disappears but the exe stays in the taskmanager->processes).

It does kill itself after about 5 minutes, but that's a long wait to be able to recompile my prg :(

Does anybody have some info or hints on this?

Found out that the running process will shut down only if i turn off my (external) midi-interface (or wait 5 minutes). Tried that with 2 different midi-interfaces, and the same thing happens.

Example code please, and I will have a look. Here are some ideas you should try.

in \portmidi28aug06\pm_win\pmwin.dll make sure that the line #define USE_DLL_FOR_CLEANUP is not commented out.

in your source include:
Import "portmidi28aug06/pm_win/pmdll.c"

and make sure you have the pmdll.dll inside your project folder.