• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: General CoreMIDI Newbie-Questions
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: General CoreMIDI Newbie-Questions


  • Subject: Re: General CoreMIDI Newbie-Questions
  • From: Oliver Jaun <email@hidden>
  • Date: Sun, 29 Dec 2002 01:04:35 +0100

Thanks a lot for your response. I know now that I have to do it
myself... :-(

I have to do some reading it seems... Well ok, I already have an idea:

I create an IPC Pipe. After sending the Sysex Message I do a read() on
the pipe. This will block until I read a response...let's say
"deviceInquiryResponse". Additionally I could use a select() system
call to specify a timeout. I guess that should work.

But I have yet another question...It's more a general C/C++ Question:
How can I pass function pointer of a non static function in C++? I'm
asking this regarding the MIDIResponseProc. I attached the source code
of my "application" (very short). Unfortunately I get the following
message if I try to compile it with

g++ -framework CoreAudio -framework CoreMIDI -framework CoreFoundation
-o scuba DataProvider.cpp

DataProvider.cpp:71: invalid use of member
`DataProvider::fileDescriptor' in
static member function

If MyReadProc wasn't static I would not get this message but then I
don't know how to pass a function pointer.

Thanks for your help.

Kind Regards

Oliver Jaun
#include <CoreAudio/HostTime.h>
#include <CoreMIDI/MIDIServices.h>
#include <CoreFoundation/CFRunLoop.h>

#include <stdio.h>
#include <unistd.h>

#include <sys/ipc.h>

#include "DataProvider.h"

DataProvider::DataProvider(int deviceId, int inPort, int outPort, int destination) {
_deviceId = deviceId;
_inPort = inPort;
_outPort = outPort;
_destination = destination;

if(pipe(fileDescriptor) < 0)
printf("pipe error\n");

MIDIClientRef client = NULL;
MIDIPortRef inputPortRef = NULL;
MIDIPortRef outputPortRef = NULL;
_destEndpointRef = MIDIGetDestination(_destination);
Byte buffer[1024];

MIDIClientCreate(CFSTR("Scuba"), NULL, NULL, &client);

MIDIInputPortCreate(client, CFSTR("Input port"),
&MyReadProc, NULL, &inputPortRef);
MIDIOutputPortCreate(client, CFSTR("Output port"), &outputPortRef);

MIDIEndpointRef src = MIDIGetSource(_inPort);
MIDIPortConnectSource(inputPortRef, src, NULL);
}

void DataProvider::getDeviceInquiryMessage() {
Byte data[] = { _SYSEX_MSG, 0x7E, _deviceId, 0x06, 0x01, _EOX };
MIDISysexSendRequest sysx = getSysexStruct(data, 6);
OSStatus status = MIDISendSysex(&sysx);
waitForResponse("deviceInquiryMessage");
printf("fertig\n");
}

void DataProvider::waitForResponse(char* commandName) {
// I'll use select() here later
read(fileDescriptor[0], _line, MAXLINE);
}

MIDISysexSendRequest DataProvider::getSysexStruct(Byte* data, int bytesToSend) {
MIDISysexSendRequest sysx;
sysx.destination = _destEndpointRef;
sysx.data = data;
sysx.bytesToSend = bytesToSend;
sysx.complete = false;
sysx.completionProc = NULL;
sysx.completionRefCon = NULL;
return sysx;
}

void DataProvider::MyReadProc(const MIDIPacketList *pktlist,
void *refCon, void *connRefCon) {
MIDIPacket *packet = (MIDIPacket *)pktlist->packet;
for (unsigned int j = 0; j < pktlist->numPackets; ++j) {
for (int i = 0; i < packet->length; ++i) {
printf("X %c\n", packet->data[i], packet->data[i]);
}
packet = MIDIPacketNext(packet);
}
// later I'll send the respective command name
write(fileDescriptor[1], "blabla\n", 7);
}

int main(int argc, char *argv[]) {
DataProvider* dp = new DataProvider(0, 0, 0, 0);
dp->getDeviceInquiryMessage();
return 0;
}
#ifndef DataProvider_h
#define DataProvider_h

#define MAXLINE 10

class DataProvider {
public:
static const int _SYSEX_MSG = 0xF0;
static const int _EMU_ID = 0x18;
static const int _E4_ID = 0x21;
static const int _EDITOR_BYTE = 0x55;
static const int _EOX = 0xF7; // EOX = End of Sysex

// Commands
static const int _CMD_PARAMETER_MIN_MAX_DEFAULT = 0x04;
static const int _CMD_ASCII_PRESET_NAME = 0x05;

DataProvider(int deviceId, int inPort, int outPort, int destination);
void getDeviceInquiryMessage();

protected:
int _deviceId;
int _inPort;
int _outPort;
int _destination;
int fileDescriptor[2];
char _line[MAXLINE];
MIDIEndpointRef _destEndpointRef;
MIDISysexSendRequest getSysexStruct(Byte* data, int bytesToSend);
static void MyReadProc(
const MIDIPacketList *pktlist, void *refCon, void *connRefCon);
void waitForResponse(char* command);
};

#endif
On Saturday, December 28, 2002, at 10:30 PM, Kurt Revis wrote:

> On Saturday, December 28, 2002, at 08:49 AM, Oliver Jaun wrote:
>
>> It is not a problem to send a sysex message. But then how do I get
>> the response? I know that I can specify a completionProc in the
>> MIDISysexSendRequest struct. But then how do I wait for the answer?
>
> The completionProc just tells you about the status of *sending* the
> sysex message. It doesn't have anything to do with a response. In
> general the CoreMIDI API provides one-way communication; it's up to
> you to write code to manage a two-way conversation.
>
> In order to receive MIDI data, you need to create a MIDI input port
> and hook it up to one (or more) source endpoints. See
> /Developer/Examples/CoreAudio/MIDI/SampleTools/Echo.cpp for a brief
> example.
>
>> DeviceInquiryMessage DataProvider::getDeviceInquiryMessage() {
>>
>> Byte data[] = { _SYSEX_MSG, 0x7E, _deviceId, 0x06, 0x01, _EOX };
>> // create MIDISysexSendRequest struct here.
>> OSStatus status = MIDISendSysex(&sysx);
>>
>> // wait for completion... but how? while(sysx.complete == false);
>> ???
>> // get the result... but how????
>> // create DeviceInquiryMessage Object
>>
>> return DeviceInquiryMessage;
>> }
>>
>
> One problem here is that this method must block forever, waiting for a
> response. However, a response may never come. What if the MIDI device
> is unplugged or turned off? These are both pretty common cases, and
> it would be bad for your whole program to hang while it waits.
>
> Basically, your program needs to implement a state machine. (Google
> for "finite state machine", or look in a programming textbook, for
> more details.) Your program would start with its state set to 'idle'.
> When you send a sysex message, you would set the state to 'listening'.
> Then, when you get a response, your MIDIReadProc will be called; you
> should have it check the state, do the appropriate thing, and then
> update the state. How you design this state machine is up to you.
>
> Also, you will probably want to have a timeout. If no response happens
> after a while (perhaps 1 second) then you should assume that something
> has gone wrong with the MIDI device you're trying to talk to. Both
> Carbon and Cocoa provide timers you can use.
>
> You do *not* want to sit in a loop waiting for a flag to be set. This
> will use a lot of CPU time for no benefit. Instead, think of things in
> terms of events: when an event happens, some function in your program
> will be called. (There are separate functions for receiving MIDI,
> timeouts firing, and so on.) Each function should look at the current
> state, figure out what to do, do it, and update the state.
>
> I'm omitting a lot of details here, but I hope you get the general
> idea.
>
> --
> Kurt Revis
> email@hidden
> _______________________________________________
> coreaudio-api mailing list | email@hidden
> Help/Unsubscribe/Archives:
> http://www.lists.apple.com/mailman/listinfo/coreaudio-api
> Do not post admin requests to the list. They will be ignored.
_______________________________________________
coreaudio-api mailing list | email@hidden
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/coreaudio-api
Do not post admin requests to the list. They will be ignored.

  • Follow-Ups:
    • Re: General CoreMIDI Newbie-Questions
      • From: Kurt Revis <email@hidden>
References: 
 >Re: General CoreMIDI Newbie-Questions (From: Kurt Revis <email@hidden>)

  • Prev by Date: Re: General CoreMIDI Newbie-Questions
  • Next by Date: Re: General CoreMIDI Newbie-Questions
  • Previous by thread: Re: General CoreMIDI Newbie-Questions
  • Next by thread: Re: General CoreMIDI Newbie-Questions
  • Index(es):
    • Date
    • Thread