Example #1
0
Error MIDIDriverCoreMidi::open() {

	CFStringRef name = CFStringCreateWithCString(NULL, "Godot", kCFStringEncodingASCII);
	OSStatus result = MIDIClientCreate(name, NULL, NULL, &client);
	CFRelease(name);
	if (result != noErr) {
		ERR_PRINTS("MIDIClientCreate failed, code: " + itos(result));
		return ERR_CANT_OPEN;
	}

	result = MIDIInputPortCreate(client, CFSTR("Godot Input"), MIDIDriverCoreMidi::read, (void *)this, &port_in);
	if (result != noErr) {
		ERR_PRINTS("MIDIInputPortCreate failed, code: " + itos(result));
		return ERR_CANT_OPEN;
	}

	int sources = MIDIGetNumberOfSources();
	for (int i = 0; i < sources; i++) {

		MIDIEndpointRef source = MIDIGetSource(i);
		if (source) {
			MIDIPortConnectSource(port_in, source, (void *)this);
			connected_sources.insert(i, source);
		}
	}

	return OK;
}
Example #2
0
int main(void) {

   // Prepare MIDI Interface Client/Port for writing MIDI data:
   MIDIClientRef midiclient;
   MIDIPortRef   midiin;
   OSStatus status;
   if (status = MIDIClientCreate(CFSTR("TeStInG"), NULL, NULL, &midiclient)) {
      printf("Error trying to create MIDI Client structure: %d\n", status);
      printf("%s\n", GetMacOSStatusErrorString(status));
      exit(status);
   }
   if (status = MIDIInputPortCreate(midiclient, CFSTR("InPuT"), myReadProc, 
         NULL, &midiin)) {
      printf("Error trying to create MIDI output port: %d\n", status);
      printf("%s\n", GetMacOSStatusErrorString(status));
      exit(status);
   }

   ItemCount nSrcs = MIDIGetNumberOfSources();
   ItemCount iSrc;
   for (iSrc=0; iSrc<nSrcs; iSrc++) {
      MIDIEndpointRef src = MIDIGetSource(iSrc);
      MIDIPortConnectSource(midiin, src, NULL);
   }
   t = lo_address_new(NULL, "7777");

   CFRunLoopRef runLoop;
   runLoop = CFRunLoopGetCurrent();
   CFRunLoopRun();

   return 0;
}
Example #3
0
MidiInput::MidiInput(std::vector<unsigned int> sources)
{
	if(OSStatus status = MIDIClientCreate(CFSTR("March"), 0, 0, &_midi_client))
	{   
		std::cerr << "Couldn't create MIDI client: " << status << std::endl;
#ifdef GetMacOSStatusErrorString
		std::cerr << GetMacOSStatusErrorString(status) << std::endl;
#endif
		throw "Couldn't create MIDI client.";
	}   

	if(OSStatus status = MIDIInputPortCreate(_midi_client, CFSTR("March Input"), MidiInput::read, this, &_midi_in))
	{
		std::cerr << "Couldn't create MIDI input port: " << status << std::endl;
#ifdef GetMacOSStatusErrorString
		std::cerr << GetMacOSStatusErrorString(status) << std::endl;
#endif
		throw "Couldn't create MIDI input port.";
	}

	for(std::vector<unsigned int>::iterator it = sources.begin(); it != sources.end(); it++)
	{
		MIDIEndpointRef src = MIDIGetSource(*it);
		std::cout << "Using source " << *it << " (" << sourceName(src) << ", " << sourceModel(src) << ", " << sourceManufacturer(src) << ")" << std::endl;
		MIDIPortConnectSource(_midi_in, src, 0);
	}
}
Example #4
0
std::vector<QString> CoreMidiDriver::getOutputPortList()
{
	INFOLOG( "retrieving output list" );
	OSStatus err = noErr;

	std::vector<QString> cmPortList;
	cmSources = MIDIGetNumberOfSources();

	INFOLOG ( "Getting number of MIDI sources . . .\n" );

	unsigned i;
	for ( i = 0; i < cmSources; i++ ) {
		CFStringRef H2MidiNames;
		cmH2Src = MIDIGetSource( i );
		if ( cmH2Src == NULL ) {
			ERRORLOG( "Could not open input device" );
		}
		if ( cmH2Src ) {
			err = MIDIObjectGetStringProperty( cmH2Src, kMIDIPropertyName, &H2MidiNames );
			INFOLOG ( "Getting MIDI object string property . . .\n" );
			char cmName[ 64 ];
			CFStringGetCString( H2MidiNames, cmName, 64, kCFStringEncodingASCII );
			INFOLOG ( "Getting MIDI object name . . .\n" );
			QString h2MidiPortName = cmName;
			cmPortList.push_back( h2MidiPortName );
		}
		CFRelease( H2MidiNames );
	}
		
	return cmPortList;
}
Example #5
0
static void _macosx_poll(struct midi_provider *p)
{
	struct macosx_midi *data;
	MIDIEndpointRef ep;
	int i;

	int num_out, num_in;

	num_out = MIDIGetNumberOfDestinations();
	num_in = MIDIGetNumberOfSources();

	for (i = max_outputs; i < num_out; i++) {
		ep = MIDIGetDestination(i);
		if (!ep) continue;
		data = mem_alloc(sizeof(struct macosx_midi));
		memcpy(&data->ep, &ep, sizeof(ep));
		data->name = get_ep_name(ep);
		midi_port_register(p, MIDI_OUTPUT, data->name, data, 1);
	}
	max_outputs = i;


	for (i = max_inputs; i < num_in; i++) {
		ep = MIDIGetSource(i);
		if (!ep) continue;
		data = mem_alloc(sizeof(struct macosx_midi));
		memcpy(&data->ep, &ep, sizeof(ep));
		data->name = get_ep_name(ep);
		midi_port_register(p, MIDI_INPUT, data->name, data, 1);
	}
	max_inputs = i;

}
void setupMIDI(MyMIDIPlayer *player) {
	
	MIDIClientRef client;
	CheckError (MIDIClientCreate(CFSTR("Core MIDI to System Sounds Demo"), MyMIDINotifyProc, player, &client),
				"Couldn't create MIDI client");
	
	MIDIPortRef inPort;
	CheckError (MIDIInputPortCreate(client, CFSTR("Input port"), MyMIDIReadProc, player, &inPort),
				"Couldn't create MIDI input port");
	
	unsigned long sourceCount = MIDIGetNumberOfSources();
	printf ("%ld sources\n", sourceCount);
	for (int i = 0; i < sourceCount; ++i) {
		MIDIEndpointRef src = MIDIGetSource(i);
		CFStringRef endpointName = NULL;
		CheckError(MIDIObjectGetStringProperty(src, kMIDIPropertyName, &endpointName),
				   "Couldn't get endpoint name");
		char endpointNameC[255];
		CFStringGetCString(endpointName, endpointNameC, 255, kCFStringEncodingUTF8);
		printf("  source %d: %s\n", i, endpointNameC);
		CheckError (MIDIPortConnectSource(inPort, src, NULL),
					"Couldn't connect MIDI port");
	}
	
	
}
Example #7
0
 void reloadDeviceList(bool advanced)
 {
     int num = MIDIGetNumberOfSources();
     m_clientFilter = !advanced;
     m_inputDevices.clear();
     for (int i = 0; i < num; ++i) {
         bool excluded = false;
         MIDIEndpointRef dest = MIDIGetSource( i );
         if (dest != 0) {
             QString name = getEndpointName(dest);
             if ( m_clientFilter &&
                     name.contains(QLatin1String("IAC"), Qt::CaseSensitive) )
                 continue;
             if ( name.contains(m_publicName))
                 continue;
             foreach( const QString& n, m_excludedNames) {
                 if (name.contains(n)) {
                     excluded = true;
                     break;
                 }
             }
             if (!excluded)
                 m_inputDevices << name;
         }
     }
Example #8
0
    static StringArray findDevices (const bool forInput)
    {
        // It seems that OSX can be a bit picky about the thread that's first used to
        // search for devices. It's safest to use the message thread for calling this.
        jassert (MessageManager::getInstance()->isThisTheMessageThread());

        const ItemCount num = forInput ? MIDIGetNumberOfSources()
                                       : MIDIGetNumberOfDestinations();
        StringArray s;

        for (ItemCount i = 0; i < num; ++i)
        {
            MIDIEndpointRef dest = forInput ? MIDIGetSource (i)
                                            : MIDIGetDestination (i);
            String name;

            if (dest != 0)
                name = getConnectedEndpointName (dest);

            if (name.isEmpty())
                name = "<error>";

            s.add (name);
        }

        return s;
    }
static int findLaunchpadPro()
{
	// find the input hardware port
	for (ItemCount i=0; i < MIDIGetNumberOfSources(); ++i)
	{
		MIDIEndpointRef endpoint = MIDIGetSource(i);
		if (endpoint)
		{
			// get the endpoint name (always available)
			CFStringRef endpointName = NULL;
			if (noErr != MIDIObjectGetStringProperty(endpoint, kMIDIPropertyName, &endpointName))
			{
				return -1;
			}
			
			if (CFStringCompare(endpointName, CFSTR("Standalone Port"), kCFCompareCaseInsensitive) == 0)
			{
				// found it!  open the endpoint.
				if (noErr != MIDIInputPortCreate(g_client, CFSTR("In"), readProc, NULL, &g_inDevPort))
				{
					return -1;
				}
				
				
				if (noErr != MIDIPortConnectSource(g_inDevPort, endpoint, NULL))
				{
					return -1;
				}
			}
		}
	}
	
	// now find the output
	for (ItemCount i=0; i < MIDIGetNumberOfDestinations(); ++i)
	{
		MIDIEndpointRef endpoint = MIDIGetDestination(i);
		if (endpoint)
		{
			// get the endpoint name (always available)
			CFStringRef endpointName = NULL;
			if (noErr != MIDIObjectGetStringProperty(endpoint, kMIDIPropertyName, &endpointName))
			{
				return -1;
			}
			
			if (CFStringCompare(endpointName, CFSTR("Standalone Port"), kCFCompareCaseInsensitive) == 0)
			{
				// found it!  open the endpoint.
				if (noErr != MIDIOutputPortCreate(g_client, CFSTR("Out"), &g_outDevPort))
				{
					return -1;
				}
				g_outDevEndpoint = endpoint;
			}
		}
	}
	
	return !(g_inDevPort && g_outDevPort);
}
Example #10
0
const MidiInput::SourceInfo MidiInput::getSourceInfo(unsigned int source)
{
	SourceInfo source_info;
	MIDIEndpointRef src = MIDIGetSource(source);
	source_info.name = sourceName(src);
	source_info.model = sourceModel(src);
	source_info.manufacturer = sourceManufacturer(src);
	return source_info;
}
Example #11
0
File: midi.c Project: huangjs/cl
int mus_midi_open_read(const char *name)
{
  init_midi();
  if (us == NULL) 
    MIDIClientCreate(CFSTR("MIDI Read"), NULL, NULL, &us);
  if (inp == NULL)
    MIDIInputPortCreate(us, CFSTR("Input port"), midi_read_callback, NULL, &inp);
  MIDIPortConnectSource(inp, MIDIGetSource(0), NULL);
  return(0);
}
Example #12
0
const char * MidiIn::getDeviceInName(int index)
{
    static char name[128+1];
    MIDIEndpointRef sourceRef = MIDIGetSource(index);
    CFStringRef displayName;
    MIDIObjectGetStringProperty(sourceRef, kMIDIPropertyDisplayName, &displayName);
    CFStringGetCString(displayName, name, 129, kCFStringEncodingUTF8);
    name[128] = 0;
    return name;
}
Example #13
0
MidiIn::MidiIn(int index, MIDIINCALLBACK callback) :
    callback(callback), handle(0)
{
    if (!midiInClient)
        MIDIClientCreate(CFSTR("OPA Editor"), NULL, NULL, &midiInClient);
    MIDIPortRef port;
    MIDIInputPortCreate(midiInClient, CFSTR("input"), coreMIDIListener, this, &port);
    fflush(stdout);
    MIDIPortConnectSource(port, MIDIGetSource(index), (void *) index);
    handle = (uint64_t) port;
}
Example #14
0
// source is identified by the index in the array returned by get_sources
// input_port is an InputPort class
static VALUE t_disconnect_source_from_port(VALUE self, VALUE source_idx, VALUE input_port)
{
    RbInputPort* port;
    Data_Get_Struct(input_port, RbInputPort, port);
    
    MIDIEndpointRef source = MIDIGetSource(FIX2INT(source_idx));
    
    MIDIPortDisconnectSource(port->input_port, source);
    
    return Qtrue;
}
CFStringRef MidiDeviceUtil::GetInDeviceManufacturer(int index)
{
    MIDIEndpointRef endpoint = MIDIGetSource(index);
    
    CFStringRef manufacturer = NULL;
    
    MIDIObjectGetStringProperty(endpoint,
                                kMIDIPropertyManufacturer,
                                &manufacturer);
    
    return manufacturer;
}
CFStringRef MidiDeviceUtil::GetInDeviceName(int index)
{
    MIDIEndpointRef endpoint = MIDIGetSource(index);
    
    CFStringRef deviceName = NULL;

    MIDIObjectGetStringProperty(endpoint,
                                kMIDIPropertyName,
                                &deviceName);

    return deviceName;
}
void PlatformMIDIDevices::refresh()
{
	for (int i = 0; i < MIDIGetNumberOfSources(); ++i)
	{
		m_devicesIn.push_back(new MIDIDeviceIn(MIDIGetSource(i)));
	}

	for (int i = 0; i < MIDIGetNumberOfDestinations(); ++i)
	{
		//m_devicesOut.push_back(new MIDIDeviceOut(MIDIGetDestination(i)));
	}
}
Example #18
0
bool Midi_CoreMidi::start() {
  OSStatus err;
  MIDIPortRef mport;
  err = MIDIClientCreate(CFSTR("murth"), 0, NULL, &mcli);
  CHECK_ERR("MIDIClientCreate");
  err = MIDIInputPortCreate(mcli, CFSTR("input"), midiread_cb, this, &mport);
  CHECK_ERR("MIDIInputPortCreate");
  
  unsigned long midi_sources = MIDIGetNumberOfSources();
  for (int i = 0; i < midi_sources; ++i)
    MIDIPortConnectSource(mport, MIDIGetSource(i), 0);
  return true;
}
INT32 MIDI_Utils_OpenDevice(int direction, INT32 deviceID, MacMidiDeviceHandle** handle, 
                            int num_msgs, int num_long_msgs, 
                            size_t lm_size)
{
    midiInit();

    int err = MIDI_ERROR_NONE;
    MIDIEndpointRef endpoint = (MIDIEndpointRef) NULL;

    TRACE0("MIDI_Utils_OpenDevice\n");

    (*handle) = (MacMidiDeviceHandle*) malloc(sizeof(MacMidiDeviceHandle));
    if (!(*handle)) {
        ERROR0("ERROR: MIDI_Utils_OpenDevice: out of memory\n");
        return MIDI_OUT_OF_MEMORY;
    }
    memset(*handle, 0, sizeof(MacMidiDeviceHandle));

    // Create the infrastructure for MIDI in/out, and after that,
    // get the device's endpoint.
    if (direction == MIDI_IN) {
        // Create queue and the pthread condition variable.
        (*handle)->h.queue = MIDI_CreateQueue(num_msgs);
        (*handle)->h.platformData = MIDI_CreateConditionVariable();
        if (!(*handle)->h.queue || !(*handle)->h.platformData) {
            ERROR0("< ERROR: MIDI_IN_OpenDevice: could not create queue or condition variable\n");
            free(*handle);
            (*handle) = NULL;
            return MIDI_OUT_OF_MEMORY;
        }
        endpoint = MIDIGetSource(deviceID);
        (*handle)->port = inPort;
    } else if (direction == MIDI_OUT) {
        endpoint = MIDIGetDestination(deviceID);
        (*handle)->port = outPort;
    }

    if (!endpoint) {
        // An error occurred.
        free(*handle);
        return MIDI_INVALID_DEVICEID;
    }
    (*handle)->h.deviceHandle = (void*) (intptr_t) endpoint;
    (*handle)->h.startTime = getCurrentTimeInNanos();
    (*handle)->direction = direction;
    (*handle)->deviceID = deviceID;

    TRACE0("MIDI_Utils_OpenDevice: succeeded\n");
    return err;
}
Example #20
0
// ----------------------------------------------------------
vector<string> ofxAudioUnitMidi::getSourceNames()
// ----------------------------------------------------------
{
	vector<string> sourceNames;
	ItemCount sourceCount = MIDIGetNumberOfSources();
	for(int i = 0; i < sourceCount; i++)
	{
		MIDIEndpointRef source = MIDIGetSource(i);
		CFStringRef sourceName = NULL;
		MIDIObjectGetStringProperty(source, kMIDIPropertyName, &sourceName);
		char sourceNameCString[255];
		CFStringGetCString(sourceName, sourceNameCString, 255, kCFStringEncodingUTF8);
		sourceNames.push_back(sourceNameCString);
	}
	return sourceNames;
}
Example #21
0
MIDIEndpointRef MIDIClient::getSource(CFStringRef name) {
    MIDIEndpointRef ret(0);
    
    for(int i=0;i<MIDIGetNumberOfSources();++i) {
        MIDIEndpointRef src = MIDIGetSource(i);
        
        CFStringRef n = getName(src);
        if(CFStringFind(name, name, kCFCompareCaseInsensitive).length == CFStringGetLength(name)) {
            CFRelease(n);
            return src;
        }
        CFRelease(n);
    }
    
    return ret;
}
Example #22
0
// ----------------------------------------------------------
bool ofxAudioUnitMidiReceiver::connectToMidiSource(unsigned long midiSourceIndex)
// ----------------------------------------------------------
{
	if(!_port)
	{
		OSStatus s = MIDIInputPortCreate(_client, 
										 CFSTR("oF MIDI Input Port"), 
										 ofxAudioUnitMidiReadProc, 
										 &_unit, 
										 &_port);
		if(s != noErr) return false;
	}
	
	OFXAU_RET_BOOL(MIDIPortConnectSource(_port, MIDIGetSource(midiSourceIndex), NULL),
				   "connecting MIDI receiver to source");
}
Example #23
0
void Input::initialize()
{
	MIDIEndpointRef source = NULL;
	
	ItemCount sourceCount = MIDIGetNumberOfSources();
	for (ItemCount i = 0; i < sourceCount; i++) {
		MIDIEndpointRef src = MIDIGetSource(i);
		source = src;
		break;
	}
	if (source) {
		MIDIClientRef client;
		MIDIClientCreate(CFSTR("Greg"), Input::notifyProc, NULL, &client);
		MIDIPortRef inputPort;
		MIDIInputPortCreate(client, CFSTR("Greg Input"), Input::readProc, NULL, &inputPort);
		MIDIPortConnectSource(inputPort, source, NULL);
	}
}
Example #24
0
void CoreMidiDriver::open()
{
	INFOLOG( "open" );

	OSStatus err = noErr;

	QString sMidiPortName = Preferences::get_instance()->m_sMidiPortName;

	cmSources = MIDIGetNumberOfSources();
	unsigned i;
	for ( i = 0; i < cmSources; i++ ) {
		CFStringRef H2MidiNames;
		cmH2Src = MIDIGetSource( i );

		if ( cmH2Src ) {
			err = MIDIObjectGetStringProperty( cmH2Src, kMIDIPropertyName, &H2MidiNames );
			char cmName[64];
			err = CFStringGetCString( H2MidiNames, cmName, 64, kCFStringEncodingASCII );
			QString h2MidiPortName = cmName;
			if ( h2MidiPortName == sMidiPortName ) {
				MIDIPortConnectSource ( h2InputRef, cmH2Src, NULL );
				m_bRunning = true;
			}
		}
		CFRelease ( H2MidiNames );
	}
	
	int n = MIDIGetNumberOfDestinations();
	if (n > 0) {
		cmH2Dst = MIDIGetDestination(0);
	}

	if (cmH2Dst != NULL) {
		CFStringRef H2MidiNames;
		
		MIDIObjectGetStringProperty(cmH2Dst, kMIDIPropertyName, &H2MidiNames);
		//CFStringGetCString(pname, name, sizeof(name), 0);
		//MIDIPortConnectSource ( h2OutputRef, cmH2Dst, NULL );
		MIDIPortConnectSource ( h2OutputRef, cmH2Dst, NULL );
		if( H2MidiNames != NULL){
		    CFRelease( H2MidiNames );
		}
	}
}
Example #25
0
void	CAMIDIEndpoints::UpdateFromCurrentState()
{
	Clear();

	UInt32 i, n;
	MIDIEndpointRef epRef;
	
	n = MIDIGetNumberOfSources();
	mSources.reserve(n);
	for (i = 0; i < n; ++i) {
		epRef = MIDIGetSource(i);
		if (epRef)
			AddEndpoints(epRef, mSources);
	}

	n = MIDIGetNumberOfDestinations();
	mDestinations.reserve(n);
	for (i = 0; i < n; ++i) {
		epRef = MIDIGetDestination(i);
		if (epRef)
			AddEndpoints(epRef, mDestinations);
	}
	
	// pairing
	for (EndpointList::iterator dit = mDestinations.begin(); dit != mDestinations.end(); ++dit) {
		Endpoint *ep = *dit;
		MIDIEntityRef destEntity = ep->Entity();
		if (destEntity != NULL) {
			for (EndpointList::iterator eit = mSources.begin(); eit != mSources.end(); ++eit) {
				Endpoint *ep2 = *eit;
				MIDIEntityRef srcEntity = ep2->Entity();
				if (srcEntity == destEntity && ep2->DriverOwned() == ep->DriverOwned()) {
					ep2->SetPairMate(ep);
					ep->SetPairMate(ep2);
				}
			}
		}
	}
}
Example #26
0
// Return an array of all available sources, filled with the names of the sources
static VALUE t_get_sources(VALUE self)
{    
    int number_of_sources = MIDIGetNumberOfSources();
    
    VALUE source_ary = rb_ary_new2(number_of_sources);
    
    int idx;
    for(idx = 0; idx < number_of_sources; ++idx)
    {
        MIDIEndpointRef src = MIDIGetSource(idx);
        CFStringRef pname;
        char name[64];
        
        MIDIObjectGetStringProperty(src, kMIDIPropertyName, &pname);
        CFStringGetCString(pname, name, sizeof(name), 0);
        CFRelease(pname);
        
        rb_ary_push(source_ary, rb_str_new2(name));
    }
    
    return source_ary;
}
//
// @see com.sun.media.sound.AbstractMidiDeviceProvider.getDeviceInfo().
static int getEndpointProperty(int direction, INT32 deviceID, char *buffer, int bufferLength, CFStringRef propertyID) {
    
    if (deviceID < 0) {
        return MIDI_INVALID_DEVICEID;
    }

    MIDIEndpointRef endpoint;
    
    if (direction == MIDI_IN) {
        endpoint = MIDIGetSource(deviceID);
    } else if (direction == MIDI_OUT) {
        endpoint = MIDIGetDestination(deviceID);
    } else {
        return MIDI_INVALID_ARGUMENT;
    }

    if (!endpoint) {
        return MIDI_INVALID_DEVICEID;
    }

    int status = MIDI_SUCCESS;
    if (propertyID == kMIDIPropertyDriverVersion) {
        SInt32 driverVersion;
        status = MIDIObjectGetIntegerProperty(endpoint, kMIDIPropertyDriverVersion, &driverVersion);
        if (status != MIDI_SUCCESS) return status;
        snprintf(buffer,
                 bufferLength,
                 "%d",
                 (int) driverVersion);
    }
    else {
        CFStringRef pname;
        status = MIDIObjectGetStringProperty(endpoint, propertyID, &pname);
        if (status != MIDI_SUCCESS) return status;
        CFStringExtractCString(pname, buffer, bufferLength, 0);
    }
    return MIDI_ERROR_NONE;
}
Example #28
0
    static StringArray findDevices (const bool forInput)
    {
        const ItemCount num = forInput ? MIDIGetNumberOfSources()
                                       : MIDIGetNumberOfDestinations();
        StringArray s;

        for (ItemCount i = 0; i < num; ++i)
        {
            MIDIEndpointRef dest = forInput ? MIDIGetSource (i)
                                            : MIDIGetDestination (i);
            String name;

            if (dest != 0)
                name = getConnectedEndpointName (dest);

            if (name.isEmpty())
                name = "<error>";

            s.add (name);
        }

        return s;
    }
Example #29
0
LONG CoreAudio_MIDIInit(void)
{
    int i;
    CHAR szPname[MAXPNAMELEN] = {0};

    int numDest = MIDIGetNumberOfDestinations();
    CFStringRef name = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("wineMIDIClient.%d"), getpid());

    wineMIDIClient = CoreMIDI_CreateClient( name );
    if (wineMIDIClient == NULL)
    {
        CFRelease(name);
        ERR("can't create wineMIDIClient\n");
        return DRV_FAILURE;
    }
    CFRelease(name);

    MIDIOut_NumDevs = MAX_MIDI_SYNTHS;
    MIDIOut_NumDevs += numDest;

    MIDIIn_NumDevs = MIDIGetNumberOfSources();

    TRACE("MIDIOut_NumDevs %d MIDIIn_NumDevs %d\n", MIDIOut_NumDevs, MIDIIn_NumDevs);

    destinations = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, MIDIOut_NumDevs * sizeof(MIDIDestination));
    sources = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, MIDIIn_NumDevs * sizeof(MIDISource));

    if (MIDIIn_NumDevs > 0)
    {
        InitializeCriticalSection(&midiInLock);
        MIDIInThreadPortName = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("MIDIInThreadPortName.%u"), getpid());
        CreateThread(NULL, 0, MIDIIn_MessageThread, NULL, 0, NULL);

        name = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("WineInputPort.%u"), getpid());
        MIDIInputPortCreate(wineMIDIClient, name, MIDIIn_ReadProc, NULL, &MIDIInPort);
        CFRelease(name);
    }
    if (numDest > 0)
    {
        name = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("WineOutputPort.%u"), getpid());
        MIDIOutputPortCreate(wineMIDIClient, name, &MIDIOutPort);
        CFRelease(name);
    }

    /* initialize sources */
    for (i = 0; i < MIDIIn_NumDevs; i++)
    {
        sources[i].wDevID = i;
        sources[i].source = MIDIGetSource(i);

        CoreMIDI_GetObjectName(sources[i].source, szPname, sizeof(szPname));
        MultiByteToWideChar(CP_ACP, 0, szPname, -1, sources[i].caps.szPname, sizeof(sources[i].caps.szPname)/sizeof(WCHAR));

        MIDIPortConnectSource(MIDIInPort, sources[i].source, &sources[i].wDevID);

        sources[i].state = 0;
        /* FIXME */
        sources[i].caps.wMid = 0x00FF; 	/* Manufac ID */
        sources[i].caps.wPid = 0x0001; 	/* Product ID */
        sources[i].caps.vDriverVersion = 0x0001;
        sources[i].caps.dwSupport = 0;
    }

    /* initialise MIDI synths */
    for (i = 0; i < MAX_MIDI_SYNTHS; i++)
    {
        snprintf(szPname, sizeof(szPname), "CoreAudio MIDI Synth %d", i);
        MultiByteToWideChar(CP_ACP, 0, szPname, -1, destinations[i].caps.szPname, sizeof(destinations[i].caps.szPname)/sizeof(WCHAR));

        destinations[i].caps.wTechnology = MOD_SYNTH;
        destinations[i].caps.wChannelMask = 0xFFFF;

        destinations[i].caps.wMid = 0x00FF; 	/* Manufac ID */
        destinations[i].caps.wPid = 0x0001; 	/* Product ID */
        destinations[i].caps.vDriverVersion = 0x0001;
        destinations[i].caps.dwSupport = MIDICAPS_VOLUME;
        destinations[i].caps.wVoices = 16;
        destinations[i].caps.wNotes = 16;
    }
    /* initialise available destinations */
    for (i = MAX_MIDI_SYNTHS; i < numDest + MAX_MIDI_SYNTHS; i++)
    {
        destinations[i].dest = MIDIGetDestination(i - MAX_MIDI_SYNTHS);

        CoreMIDI_GetObjectName(destinations[i].dest, szPname, sizeof(szPname));
        MultiByteToWideChar(CP_ACP, 0, szPname, -1, destinations[i].caps.szPname, sizeof(destinations[i].caps.szPname)/sizeof(WCHAR));

        destinations[i].caps.wTechnology = MOD_MIDIPORT;
        destinations[i].caps.wChannelMask = 0xFFFF;

        destinations[i].caps.wMid = 0x00FF; 	/* Manufac ID */
        destinations[i].caps.wPid = 0x0001;
        destinations[i].caps.vDriverVersion = 0x0001;
        destinations[i].caps.dwSupport = 0;
        destinations[i].caps.wVoices = 0;
        destinations[i].caps.wNotes = 0;
    }
    return DRV_SUCCESS;
}
int prListMIDIEndpoints(struct VMGlobals *g, int numArgsPushed)
{
	OSStatus error;
	PyrSlot *a = g->sp;
	int numSrc = (int)MIDIGetNumberOfSources();
	int numDst = (int)MIDIGetNumberOfDestinations();

	PyrObject* idarray = newPyrArray(g->gc, 6 * sizeof(PyrObject), 0 , true);
		SetObject(a, idarray);

	PyrObject* idarraySo = newPyrArray(g->gc, numSrc * sizeof(SInt32), 0 , true);
		SetObject(idarray->slots+idarray->size++, idarraySo);
		g->gc->GCWrite(idarray, idarraySo);

	PyrObject* devarraySo = newPyrArray(g->gc, numSrc * sizeof(PyrObject), 0 , true);
		SetObject(idarray->slots+idarray->size++, devarraySo);
		g->gc->GCWrite(idarray, devarraySo);

		PyrObject* namearraySo = newPyrArray(g->gc, numSrc * sizeof(PyrObject), 0 , true);
		SetObject(idarray->slots+idarray->size++, namearraySo);
		g->gc->GCWrite(idarray, namearraySo);

	PyrObject* idarrayDe = newPyrArray(g->gc, numDst * sizeof(SInt32), 0 , true);
		SetObject(idarray->slots+idarray->size++, idarrayDe);
		g->gc->GCWrite(idarray, idarrayDe);

	PyrObject* namearrayDe = newPyrArray(g->gc, numDst * sizeof(PyrObject), 0 , true);
		SetObject(idarray->slots+idarray->size++, namearrayDe);
		g->gc->GCWrite(idarray, namearrayDe);

	PyrObject* devarrayDe = newPyrArray(g->gc, numDst * sizeof(PyrObject), 0 , true);
		SetObject(idarray->slots+idarray->size++, devarrayDe);
		g->gc->GCWrite(idarray, devarrayDe);


	for (int i=0; i<numSrc; ++i) {
		MIDIEndpointRef src = MIDIGetSource(i);
		SInt32 id;
		MIDIObjectGetIntegerProperty(src, kMIDIPropertyUniqueID, &id);

		MIDIEntityRef ent;
		error = MIDIEndpointGetEntity(src, &ent);

		CFStringRef devname, endname;
		char cendname[1024], cdevname[1024];

		// Virtual sources don't have entities
		if(error)
		{
			MIDIObjectGetStringProperty(src, kMIDIPropertyName, &devname);
			MIDIObjectGetStringProperty(src, kMIDIPropertyName, &endname);
			CFStringGetCString(devname, cdevname, 1024, kCFStringEncodingUTF8);
			CFStringGetCString(endname, cendname, 1024, kCFStringEncodingUTF8);
		}
		else
		{
			MIDIDeviceRef dev;

			MIDIEntityGetDevice(ent, &dev);
			MIDIObjectGetStringProperty(dev, kMIDIPropertyName, &devname);
			MIDIObjectGetStringProperty(src, kMIDIPropertyName, &endname);
			CFStringGetCString(devname, cdevname, 1024, kCFStringEncodingUTF8);
			CFStringGetCString(endname, cendname, 1024, kCFStringEncodingUTF8);
		}

		PyrString *string = newPyrString(g->gc, cendname, 0, true);
		SetObject(namearraySo->slots+i, string);
		namearraySo->size++;
		g->gc->GCWrite(namearraySo, (PyrObject*)string);

		PyrString *devstring = newPyrString(g->gc, cdevname, 0, true);
		SetObject(devarraySo->slots+i, devstring);
		devarraySo->size++;
		g->gc->GCWrite(devarraySo, (PyrObject*)devstring);

		SetInt(idarraySo->slots+i, id);
		idarraySo->size++;

		CFRelease(devname);
		CFRelease(endname);
	}



//      post("numDst %d\n",  numDst);
	for (int i=0; i<numDst; ++i) {
		MIDIEndpointRef dst = MIDIGetDestination(i);
		SInt32 id;
		MIDIObjectGetIntegerProperty(dst, kMIDIPropertyUniqueID, &id);

		MIDIEntityRef ent;
		error = MIDIEndpointGetEntity(dst, &ent);

		CFStringRef devname, endname;
		char cendname[1024], cdevname[1024];

		// Virtual destinations don't have entities either
		if(error)
		{
			MIDIObjectGetStringProperty(dst, kMIDIPropertyName, &devname);
			MIDIObjectGetStringProperty(dst, kMIDIPropertyName, &endname);
			CFStringGetCString(devname, cdevname, 1024, kCFStringEncodingUTF8);
			CFStringGetCString(endname, cendname, 1024, kCFStringEncodingUTF8);

		}
		else
		{
			MIDIDeviceRef dev;

			MIDIEntityGetDevice(ent, &dev);
			MIDIObjectGetStringProperty(dev, kMIDIPropertyName, &devname);
			MIDIObjectGetStringProperty(dst, kMIDIPropertyName, &endname);
			CFStringGetCString(devname, cdevname, 1024, kCFStringEncodingUTF8);
			CFStringGetCString(endname, cendname, 1024, kCFStringEncodingUTF8);
		}

		PyrString *string = newPyrString(g->gc, cendname, 0, true);
		SetObject(namearrayDe->slots+namearrayDe->size++, string);
		g->gc->GCWrite(namearrayDe, (PyrObject*)string);

		PyrString *devstring = newPyrString(g->gc, cdevname, 0, true);

		SetObject(devarrayDe->slots+devarrayDe->size++, devstring);
		g->gc->GCWrite(devarrayDe, (PyrObject*)devstring);

		SetInt(idarrayDe->slots+idarrayDe->size++, id);

		CFRelease(devname);
		CFRelease(endname);

	}
	return errNone;
}