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 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 reloadDeviceList(bool advanced) { int num = MIDIGetNumberOfDestinations(); m_clientFilter = !advanced; m_outputDevices.clear(); for (int i = 0; i < num; ++i) { bool excluded = false; MIDIEndpointRef dest = MIDIGetDestination( 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_outputDevices << name; } }
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); }
static VALUE core_midi_get_destination (VALUE mod, VALUE idx) { ItemCount ic = NUM2UINT(idx); MIDIEndpointRef ref = MIDIGetDestination(ic); if ((UInt32)NULL == ref) { return Qnil; } return ULONG2NUM((UInt32) ref); }
int mus_midi_write(int line, unsigned char *buffer, int bytes) { MIDIPacketList *list = (MIDIPacketList *)bb; MIDIPacket *pk; if ((line < 1) || (buffer == NULL) || (outp == NULL)) return(-1); /* create the packetlist and packet */ pk = MIDIPacketListInit(list); MIDIPacketListAdd(list, sizeof(bb), pk, 0, bytes, (Byte *)buffer); /* 0 is the time stamp = now? */ MIDISend(outp, MIDIGetDestination(0), list); return(0); }
CFStringRef MidiDeviceUtil::GetOutDeviceManufacturer(int index) { MIDIEndpointRef endpoint = MIDIGetDestination(index); CFStringRef manufacturer = NULL; MIDIObjectGetStringProperty(endpoint, kMIDIPropertyManufacturer, &manufacturer); return manufacturer; }
CFStringRef MidiDeviceUtil::GetOutDeviceName(int index) { MIDIEndpointRef endpoint = MIDIGetDestination(index); CFStringRef deviceName = NULL; MIDIObjectGetStringProperty(endpoint, kMIDIPropertyName, &deviceName); return deviceName; }
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; }
MIDIChango::MIDIChango(Mahalo *M){ fprintf(stderr,"DOING THE MIDI THING!\n"); MIDIClientRef client; MIDIClientCreate( CFStringCreateWithCString(NULL, "D-Ball's Client", kCFStringEncodingASCII), NULL, NULL, &client); MIDIOutputPortCreate(client, CFSTR("My output port"), &outputPort); for(int i = 0 ; i < 6; i++){ eps[i] = MIDIGetDestination(i); } }
MIDIEndpointRef MIDIClient::getDestination(CFStringRef name) { MIDIEndpointRef ret(0); for(int i=0;i<MIDIGetNumberOfDestinations();++i) { MIDIEndpointRef src = MIDIGetDestination(i); CFStringRef n = getName(src); if(CFStringFind(n, name, kCFCompareCaseInsensitive).length == CFStringGetLength(name)) { CFRelease(n); return src; } CFRelease(n); } return ret; }
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 ); } } }
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); } } } } }
// // @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; }
int MidiDriver_CoreMIDI::open() { if (mDest) return MERR_ALREADY_OPEN; OSStatus err = noErr; mOutPort = 0; int dests = MIDIGetNumberOfDestinations(); if (dests > 0 && mClient) { mDest = MIDIGetDestination(0); err = MIDIOutputPortCreate( mClient, CFSTR("scummvm_output_port"), &mOutPort); } else { return MERR_DEVICE_NOT_AVAILABLE; } if (err != noErr) return MERR_CANNOT_CONNECT; return 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; }
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; }
JNIEXPORT jint JNICALL Java_com_apple_audio_midi_MIDISetup_MIDIGetDestination (JNIEnv *, jclass, jint destIndex0) { return (jint)MIDIGetDestination((ItemCount)destIndex0); }
//_________________________________________________________ void AddSlots (short refNum) { int i, n; MIDIEndpointRef src,dest; CFStringRef pname; char slotname[SlotLength], name[StringLen], model[StringLen]; // 'name' + 'model' length must be < slotname 'length' OSStatus err; SlotPtr slot; n = MIDIGetNumberOfSources(); for (i=0; i<n; i++) { src = MIDIGetSource(i); err = MIDIObjectGetStringProperty(src, kMIDIPropertyName, &pname); if (err == noErr) { CFStringGetCString(pname, name, sizeof(name), 0); CFRelease(pname); // If found, add the model name before the device name, copy no more than SlotLength if (GetModel(src,model,StringLen)) { snprintf(slotname, SlotLength-1, "%s:%s", name,model); // 'name' and 'model' are concatenated to build 'slotname' }else { strncpy(slotname,name,SlotLength-1); } slot = CreateSlot (refNum, slotname, MidiInputSlot, src); if (slot) { slot->next = gInSlots; gInSlots = slot; // No connection with the source : done by the application alarm } } } n = MIDIGetNumberOfDestinations(); for (i=0; i<n; i++) { dest = MIDIGetDestination(i); err = MIDIObjectGetStringProperty(dest, kMIDIPropertyName, &pname); if (err == noErr) { CFStringGetCString(pname, name, sizeof(name), 0); CFRelease(pname); // If found, add the model name before the device name, copy no more than SlotLength if (GetModel(dest,model,StringLen)) { snprintf(slotname, SlotLength-1, "%s:%s",name, model); // 'name' and 'model' are concatenated to build 'slotname' }else { strncpy(slotname,name,SlotLength-1); } slot = CreateSlot (refNum, slotname, MidiOutputSlot, 0); if (slot) { slot->port = gOutPort; slot->dest = dest; slot->next = gOutSlots; gOutSlots = slot; } } } }
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; }
int main (int argc, const char * argv[]) { if (argc == 1) { fprintf (stderr, "%s\n", usageStr); exit(0); } char* filePath = 0; bool shouldPlay = false; bool shouldSetBank = false; bool shouldUseMIDIEndpoint = false; bool shouldPrint = true; bool waitAtEnd = false; bool diskStream = false; OSType dataFormat = 0; Float64 srate = 0; const char* outputFilePath = 0; MusicSequenceLoadFlags loadFlags = 0; char* bankPath = 0; Float32 startTime = 0; UInt32 numFrames = 512; std::set<int> trackSet; for (int i = 1; i < argc; ++i) { if (!strcmp ("-p", argv[i])) { shouldPlay = true; } else if (!strcmp ("-w", argv[i])) { waitAtEnd = true; } else if (!strcmp ("-d", argv[i])) { diskStream = true; } else if (!strcmp ("-b", argv[i])) { shouldSetBank = true; if (++i == argc) goto malformedInput; bankPath = const_cast<char*>(argv[i]); } else if (!strcmp ("-n", argv[i])) { shouldPrint = false; } else if ((filePath == 0) && (argv[i][0] == '/' || argv[i][0] == '~')) { filePath = const_cast<char*>(argv[i]); } else if (!strcmp ("-s", argv[i])) { if (++i == argc) goto malformedInput; sscanf (argv[i], "%f", &startTime); } else if (!strcmp ("-t", argv[i])) { int index; if (++i == argc) goto malformedInput; sscanf (argv[i], "%d", &index); trackSet.insert(--index); } else if (!strcmp("-e", argv[i])) { shouldUseMIDIEndpoint = true; } else if (!strcmp("-c", argv[i])) { loadFlags = kMusicSequenceLoadSMF_ChannelsToTracks; } else if (!strcmp ("-i", argv[i])) { if (++i == argc) goto malformedInput; sscanf (argv[i], "%lu", (unsigned long*)(&numFrames)); } else if (!strcmp ("-f", argv[i])) { if (i + 3 >= argc) goto malformedInput; outputFilePath = argv[++i]; StrToOSType (argv[++i], dataFormat); sscanf (argv[++i], "%lf", &srate); } else { malformedInput: fprintf (stderr, "%s\n", usageStr); exit (1); } } if (filePath == 0) { fprintf (stderr, "You have to specify a MIDI file to print or play\n"); fprintf (stderr, "%s\n", usageStr); exit (1); } if (shouldUseMIDIEndpoint && outputFilePath) { printf ("can't write a file when you try to play out to a MIDI Endpoint\n"); exit (1); } MusicSequence sequence; OSStatus result; FailIf ((result = LoadSMF (filePath, sequence, loadFlags)), fail, "LoadSMF"); if (shouldPrint) CAShow (sequence); if (shouldPlay) { AUGraph graph = 0; AudioUnit theSynth = 0; FailIf ((result = MusicSequenceGetAUGraph (sequence, &graph)), fail, "MusicSequenceGetAUGraph"); FailIf ((result = AUGraphOpen (graph)), fail, "AUGraphOpen"); FailIf ((result = GetSynthFromGraph (graph, theSynth)), fail, "GetSynthFromGraph"); FailIf ((result = AudioUnitSetProperty (theSynth, kAudioUnitProperty_CPULoad, kAudioUnitScope_Global, 0, &maxCPULoad, sizeof(maxCPULoad))), fail, "AudioUnitSetProperty: kAudioUnitProperty_CPULoad"); if (shouldUseMIDIEndpoint) { MIDIClientRef theMidiClient; MIDIClientCreate(CFSTR("Play Sequence"), NULL, NULL, &theMidiClient); ItemCount destCount = MIDIGetNumberOfDestinations(); if (destCount == 0) { fprintf (stderr, "No MIDI Endpoints to play to.\n"); exit(1); } FailIf ((result = MusicSequenceSetMIDIEndpoint (sequence, MIDIGetDestination(0))), fail, "MusicSequenceSetMIDIEndpoint"); } else { if (shouldSetBank) { CFURLRef soundBankURL = CFURLCreateFromFileSystemRepresentation(kCFAllocatorDefault, (const UInt8*)bankPath, strlen(bankPath), false); printf ("Setting Sound Bank:%s\n", bankPath); result = AudioUnitSetProperty (theSynth, kMusicDeviceProperty_SoundBankURL, kAudioUnitScope_Global, 0, &soundBankURL, sizeof(soundBankURL)); if (soundBankURL) CFRelease(soundBankURL); FailIf (result, fail, "AudioUnitSetProperty: kMusicDeviceProperty_SoundBankURL"); } if (diskStream) { UInt32 value = diskStream; FailIf ((result = AudioUnitSetProperty (theSynth, kMusicDeviceProperty_StreamFromDisk, kAudioUnitScope_Global, 0, &value, sizeof(value))), fail, "AudioUnitSetProperty: kMusicDeviceProperty_StreamFromDisk"); } if (outputFilePath) { // need to tell synth that is going to render a file. UInt32 value = 1; FailIf ((result = AudioUnitSetProperty (theSynth, kAudioUnitProperty_OfflineRender, kAudioUnitScope_Global, 0, &value, sizeof(value))), fail, "AudioUnitSetProperty: kAudioUnitProperty_OfflineRender"); } FailIf ((result = SetUpGraph (graph, numFrames, srate, (outputFilePath != NULL))), fail, "SetUpGraph"); if (shouldPrint) { printf ("Sample Rate: %.1f \n", srate); printf ("Disk Streaming is enabled: %c\n", (diskStream ? 'T' : 'F')); } FailIf ((result = AUGraphInitialize (graph)), fail, "AUGraphInitialize"); if (shouldPrint) CAShow (graph); } MusicPlayer player; FailIf ((result = NewMusicPlayer (&player)), fail, "NewMusicPlayer"); FailIf ((result = MusicPlayerSetSequence (player, sequence)), fail, "MusicPlayerSetSequence"); // figure out sequence length UInt32 ntracks; FailIf ((MusicSequenceGetTrackCount (sequence, &ntracks)), fail, "MusicSequenceGetTrackCount"); MusicTimeStamp sequenceLength = 0; bool shouldPrintTracks = shouldPrint && !trackSet.empty(); if (shouldPrintTracks) printf ("Only playing specified tracks:\n\t"); for (UInt32 i = 0; i < ntracks; ++i) { MusicTrack track; MusicTimeStamp trackLength; UInt32 propsize = sizeof(MusicTimeStamp); FailIf ((result = MusicSequenceGetIndTrack(sequence, i, &track)), fail, "MusicSequenceGetIndTrack"); FailIf ((result = MusicTrackGetProperty(track, kSequenceTrackProperty_TrackLength, &trackLength, &propsize)), fail, "MusicTrackGetProperty: kSequenceTrackProperty_TrackLength"); if (trackLength > sequenceLength) sequenceLength = trackLength; if (!trackSet.empty() && (trackSet.find(i) == trackSet.end())) { Boolean mute = true; FailIf ((result = MusicTrackSetProperty(track, kSequenceTrackProperty_MuteStatus, &mute, sizeof(mute))), fail, "MusicTrackSetProperty: kSequenceTrackProperty_MuteStatus"); } else if (shouldPrintTracks) { printf ("%d, ", int(i+1)); } } if (shouldPrintTracks) printf ("\n"); // now I'm going to add 8 beats on the end for the reverb/long releases to tail off... sequenceLength += 8; FailIf ((result = MusicPlayerSetTime (player, startTime)), fail, "MusicPlayerSetTime"); FailIf ((result = MusicPlayerPreroll (player)), fail, "MusicPlayerPreroll"); if (shouldPrint) { printf ("Ready to play: %s, %.2f beats long\n\t<Enter> to continue: ", filePath, sequenceLength); getc(stdin); } startRunningTime = CAHostTimeBase::GetTheCurrentTime(); /* if (waitAtEnd && graph) AUGraphStart(graph); */ FailIf ((result = MusicPlayerStart (player)), fail, "MusicPlayerStart"); if (outputFilePath) WriteOutputFile (outputFilePath, dataFormat, srate, sequenceLength, shouldPrint, graph, numFrames, player); else PlayLoop (player, graph, sequenceLength, shouldPrint, waitAtEnd); FailIf ((result = MusicPlayerStop (player)), fail, "MusicPlayerStop"); if (shouldPrint) printf ("finished playing\n"); /* if (waitAtEnd) { CFRunLoopRunInMode(kCFRunLoopDefaultMode, 10, false); if (graph) AUGraphStop(graph); if (shouldPrint) printf ("disposing\n"); } */ // this shows you how you should dispose of everything FailIf ((result = DisposeMusicPlayer (player)), fail, "DisposeMusicPlayer"); FailIf ((result = DisposeMusicSequence(sequence)), fail, "DisposeMusicSequence"); // don't own the graph so don't dispose it (the seq owns it as we never set it ourselves, we just got it....) } else { FailIf ((result = DisposeMusicSequence(sequence)), fail, "DisposeMusicSequence"); } while (waitAtEnd) CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.25, false); return 0; fail: if (shouldPrint) printf ("Error = %ld\n", (long)result); return result; }
MIDIEndpointRef MIDIClient::destAtIndex(CFIndex index) { return MIDIGetDestination(index); }
int main(int argc, char *argv[]) { if (argc >= 2) { // first argument, if present, is the MIDI channel number to echo to (1-16) sscanf(argv[1], "%d", &gChannel); if (gChannel < 1) gChannel = 1; else if (gChannel > 16) gChannel = 16; --gChannel; // convert to 0-15 } // create client and ports MIDIClientRef client = NULL; MIDIClientCreate(CFSTR("MIDI Echo"), NULL, NULL, &client); MIDIPortRef inPort = NULL; MIDIInputPortCreate(client, CFSTR("Input port"), MyReadProc, NULL, &inPort); MIDIOutputPortCreate(client, CFSTR("Output port"), &gOutPort); // enumerate devices (not really related to purpose of the echo program // but shows how to get information about devices) int i, n; CFStringRef pname, pmanuf, pmodel; char name[64], manuf[64], model[64]; n = MIDIGetNumberOfDevices(); for (i = 0; i < n; ++i) { MIDIDeviceRef dev = MIDIGetDevice(i); MIDIObjectGetStringProperty(dev, kMIDIPropertyName, &pname); MIDIObjectGetStringProperty(dev, kMIDIPropertyManufacturer, &pmanuf); MIDIObjectGetStringProperty(dev, kMIDIPropertyModel, &pmodel); CFStringGetCString(pname, name, sizeof(name), 0); CFStringGetCString(pmanuf, manuf, sizeof(manuf), 0); CFStringGetCString(pmodel, model, sizeof(model), 0); CFRelease(pname); CFRelease(pmanuf); CFRelease(pmodel); printf("name=%s, manuf=%s, model=%s\n", name, manuf, model); } // open connections from all sources n = MIDIGetNumberOfSources(); printf("%d sources\n", n); for (i = 0; i < n; ++i) { MIDIEndpointRef src = MIDIGetSource(i); MIDIPortConnectSource(inPort, src, NULL); } // find the first destination n = MIDIGetNumberOfDestinations(); if (n > 0) gDest = MIDIGetDestination(0); if (gDest != NULL) { MIDIObjectGetStringProperty(gDest, kMIDIPropertyName, &pname); CFStringGetCString(pname, name, sizeof(name), 0); CFRelease(pname); printf("Echoing to channel %d of %s\n", gChannel + 1, name); } else { printf("No MIDI destinations present\n"); } CFRunLoopRun(); // run until aborted with control-C return 0; }
int main (int argc, const char * argv[]) { if (argc == 1) { fprintf (stderr, "%s\n", usageStr); exit(0); } char* filePath = 0; bool shouldPlay = false; bool shouldSetBank = false; bool shouldUseMIDIEndpoint = false; bool shouldPrint = true; bool waitAtEnd = false; bool diskStream = false; OSType dataFormat = 0; Float64 srate = 0; const char* outputFilePath = 0; MusicSequenceLoadFlags loadFlags = 0; char* bankPath = 0; Float32 startTime = 0; UInt32 numFrames = 512; for (int i = 1; i < argc; ++i) { if (!strcmp ("-p", argv[i])) { shouldPlay = true; } else if (!strcmp ("-w", argv[i])) { waitAtEnd = true; } else if (!strcmp ("-d", argv[i])) { diskStream = true; } else if (!strcmp ("-b", argv[i])) { shouldSetBank = true; if (++i == argc) goto malformedInput; bankPath = const_cast<char*>(argv[i]); } else if (!strcmp ("-n", argv[i])) { shouldPrint = false; } else if ((filePath == 0) && (argv[i][0] == '/' || argv[i][0] == '~')) { filePath = const_cast<char*>(argv[i]); } else if (!strcmp ("-t", argv[i])) { if (++i == argc) goto malformedInput; sscanf (argv[i], "%f", &startTime); } else if (!strcmp("-e", argv[i])) { shouldUseMIDIEndpoint = true; } else if (!strcmp("-c", argv[i])) { loadFlags = kMusicSequenceLoadSMF_ChannelsToTracks; } else if (!strcmp ("-i", argv[i])) { if (++i == argc) goto malformedInput; sscanf (argv[i], "%ld", &numFrames); } else if (!strcmp ("-f", argv[i])) { if (i + 3 >= argc) goto malformedInput; outputFilePath = argv[++i]; str2OSType (argv[++i], dataFormat); sscanf (argv[++i], "%lf", &srate); } else { malformedInput: fprintf (stderr, "%s\n", usageStr); exit (1); } } if (filePath == 0) { fprintf (stderr, "You have to specify a MIDI file to print or play\n"); fprintf (stderr, "%s\n", usageStr); exit (1); } if (shouldUseMIDIEndpoint && outputFilePath) { printf ("can't write a file when you try to play out to a MIDI Endpoint\n"); exit (1); } MusicSequence sequence; OSStatus result; require_noerr (result = LoadSMF (filePath, sequence, loadFlags), fail); if (shouldPrint) CAShow (sequence); if (shouldPlay) { AUGraph graph = 0; AudioUnit theSynth = 0; require_noerr (result = MusicSequenceGetAUGraph (sequence, &graph), fail); require_noerr (result = AUGraphOpen (graph), fail); require_noerr (result = GetSynthFromGraph (graph, theSynth), fail); require_noerr (result = AudioUnitSetProperty (theSynth, kAudioUnitProperty_CPULoad, kAudioUnitScope_Global, 0, &maxCPULoad, sizeof(maxCPULoad)), fail); if (shouldUseMIDIEndpoint) { MIDIClientRef theMidiClient; MIDIClientCreate(CFSTR("Play Sequence"), NULL, NULL, &theMidiClient); ItemCount destCount = MIDIGetNumberOfDestinations(); if (destCount == 0) { fprintf (stderr, "No MIDI Endpoints to play to.\n"); exit(1); } require_noerr (result = MusicSequenceSetMIDIEndpoint (sequence, MIDIGetDestination(0)), fail); } else { if (shouldSetBank) { FSRef soundBankRef; require_noerr (result = FSPathMakeRef ((const UInt8*)bankPath, &soundBankRef, 0), fail); printf ("Setting Sound Bank:%s\n", bankPath); require_noerr (result = AudioUnitSetProperty (theSynth, kMusicDeviceProperty_SoundBankFSRef, kAudioUnitScope_Global, 0, &soundBankRef, sizeof(soundBankRef)), fail); } if (diskStream) { UInt32 value = diskStream; require_noerr (result = AudioUnitSetProperty (theSynth, kMusicDeviceProperty_StreamFromDisk, kAudioUnitScope_Global, 0, &value, sizeof(value)), fail); } if (outputFilePath) { // need to tell synth that is going to render a file. UInt32 value = 1; require_noerr (result = AudioUnitSetProperty (theSynth, kAudioUnitProperty_OfflineRender, kAudioUnitScope_Global, 0, &value, sizeof(value)), fail); } require_noerr (result = SetUpGraph (graph, numFrames, srate, (outputFilePath != NULL)), fail); if (shouldPrint) { printf ("Sample Rate: %.1f \n", srate); printf ("Disk Streaming is enabled: %c\n", (diskStream ? 'T' : 'F')); } require_noerr (result = AUGraphInitialize (graph), fail); if (shouldPrint) CAShow (graph); } MusicPlayer player; require_noerr (result = NewMusicPlayer (&player), fail); require_noerr (result = MusicPlayerSetSequence (player, sequence), fail); // figure out sequence length UInt32 ntracks; require_noerr(MusicSequenceGetTrackCount (sequence, &ntracks), fail); MusicTimeStamp sequenceLength = 0; for (UInt32 i = 0; i < ntracks; ++i) { MusicTrack track; MusicTimeStamp trackLength; UInt32 propsize = sizeof(MusicTimeStamp); require_noerr (result = MusicSequenceGetIndTrack(sequence, i, &track), fail); require_noerr (result = MusicTrackGetProperty(track, kSequenceTrackProperty_TrackLength, &trackLength, &propsize), fail); if (trackLength > sequenceLength) sequenceLength = trackLength; } // now I'm going to add 8 beats on the end for the reverb/long releases to tail off... sequenceLength += 8; require_noerr (result = MusicPlayerSetTime (player, startTime), fail); require_noerr (result = MusicPlayerPreroll (player), fail); if (shouldPrint) { printf ("Ready to play: %s, %.2f beats long\n\t<Enter> to continue: ", filePath, sequenceLength); getc(stdin); } startRunningTime = AudioGetCurrentHostTime (); require_noerr (result = MusicPlayerStart (player), fail); if (outputFilePath) WriteOutputFile (outputFilePath, dataFormat, srate, sequenceLength, shouldPrint, graph, numFrames, player); else PlayLoop (player, graph, sequenceLength, shouldPrint, waitAtEnd); require_noerr (result = MusicPlayerStop (player), fail); if (shouldPrint) printf ("finished playing\n"); // this shows you how you should dispose of everything require_noerr (result = DisposeMusicPlayer (player), fail); require_noerr (result = DisposeMusicSequence(sequence), fail); // don't own the graph so don't dispose it (the seq owns it as we never set it ourselves, we just got it....) } else { require_noerr (result = DisposeMusicSequence(sequence), fail); } while (waitAtEnd) CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.25, false); return 0; fail: if (shouldPrint) printf ("Error = %ld\n", result); return result; }