This is next-2-0-midi.c in view mode; [Download] [Up]
/* * this code is adapted from sources written by Boynton * and Massie in /NextDeveloper/Examples/MidiDriver. * if in Franz on next, compile by: cc -DEXCL next-2-0-midi.c -c -O */ #ifndef EXCL #ifndef AKCL #error "missing compilation flags: need AKCL or EXCL !" #endif #endif #import <mach.h> #import <stdio.h> #import <stdlib.h> #import <fcntl.h> #import <mach_error.h> #import <servers/netname.h> #import <strings.h> #import <midi/midi_server.h> #import <midi/midi_reply_handler.h> #import <midi/midi_timer.h> #import <midi/midi_timer_reply_handler.h> #import <midi/midi_error.h> #import <midi/midi_timer_error.h> typedef struct { int quanta; unsigned int metaevent:1; unsigned int ndata:7; unsigned char data[3]; } midievent_t; port_t midiPort; port_t ownerPort; port_t negotiationPort; port_t timerPort; port_t timerReplyPort; port_t xmitPort; port_t xmitReplyPort; port_t recvPort; port_t recvReplyPort; port_set_name_t portSet; u_int quantaTime = 0; u_int quantaSize = 1000; int midiopen(int port); int midiclose(); int midistarttimer(); int midistoptimer(); int midisetquantasize(int usec); int midisettime(int qtime); int midigettime(int *databuf); int midireadmessages(); int midiwritemessage(int msg, int qtime); int midihush(); int midiflush(); kern_return_t myTimerReplyHandler ( void *arg, timeval_t timeval, u_int quanta, u_int quantumSize, u_int realUsecPerQuantum, boolean_t timerExpired, boolean_t timerStopped, boolean_t timerForward ); midi_timer_reply_t midiTimerReply = { myTimerReplyHandler, 0, 0 }; kern_return_t myRecvRawDataHandler( void * arg, midi_raw_t rawData, u_int rawDataCnt ); kern_return_t myRecvCookedDataHandler( void *arg, midi_cooked_t cookedData, u_int cookedDataCnt ); kern_return_t myRecvPackedDataHandler( void * arg, u_int quanta, midi_packed_t packedData, u_int packedDataCnt ); kern_return_t myQueueNotifyHandler( void * arg, u_int queueSize ); midi_reply_t midiReply = { myRecvRawDataHandler, myRecvCookedDataHandler, myRecvPackedDataHandler, myQueueNotifyHandler, 0, 0 }; #define max(a, b) ((a) > (b) ? (a) : (b)) u_int queue_max = max(MIDI_COOKED_DATA_MAX, MIDI_RAW_DATA_MAX)*2; int midiopen(int port) { kern_return_t r; char *midiPortName; if (port==0) midiPortName="midi0"; else if (port==1) midiPortName="midi1"; else return KERN_FAILURE; r = netname_look_up(NameServerPort, "", midiPortName, &midiPort); if (r != KERN_SUCCESS) { mach_error("timer_track: netname_look_up error", r); return r; } r = port_allocate(task_self(), &ownerPort); if (r != KERN_SUCCESS) { mach_error("allocate owner port", r); return r; } negotiationPort = PORT_NULL; r = midi_set_owner(midiPort, ownerPort, &negotiationPort); if (r != KERN_SUCCESS) { midi_error("become owner", r); return r; } r = midi_get_out_timer_port(midiPort, &timerPort); if (r != KERN_SUCCESS) { midi_error("output timer port", r); return r; } r = midi_get_xmit(midiPort, ownerPort, &xmitPort); if (r != KERN_SUCCESS) { midi_error("xmit port", r); return r; } r = midi_get_recv(midiPort, ownerPort, &recvPort); if (r != KERN_SUCCESS) { midi_error("recv port", r); return r; } r = port_allocate(task_self(), &timerReplyPort); if (r != KERN_SUCCESS) { mach_error("allocate timer reply port", r); return r; } r = port_allocate(task_self(), &xmitReplyPort); if (r != KERN_SUCCESS) { mach_error("allocate xmit reply port", r); return r; } r = port_allocate(task_self(), &recvReplyPort); if (r != KERN_SUCCESS) { mach_error("allocate recv reply port", r); return r; } r = midi_set_proto(xmitPort, MIDI_PROTO_COOKED, FALSE, MIDI_PROTO_SYNC_SYS, 10, 2, queue_max); if (r != KERN_SUCCESS) { mach_error("midi_set_proto", r); return r; } r = midi_set_sys_ignores(recvPort, (MIDI_IGNORE_ACTIVE_SENS | MIDI_IGNORE_TIMING_CLCK | MIDI_IGNORE_START | MIDI_IGNORE_CONTINUE | MIDI_IGNORE_STOP | MIDI_IGNORE_SONG_POS_P)); if (r != KERN_SUCCESS) { mach_error("midi_set_sys_ignores", r); return r; } r = midi_set_proto(recvPort, MIDI_PROTO_COOKED, FALSE, MIDI_PROTO_SYNC_SYS, 10, 2, 8192); if (r != KERN_SUCCESS) { mach_error("midi_set_proto", r); return r; } r = midi_get_data(recvPort, recvReplyPort); if (r != KERN_SUCCESS) { midi_timer_error("midi_get_data", r); return r; } r = port_set_allocate(task_self(), &portSet); if (r != KERN_SUCCESS) { mach_error("allocate port set", r); return r; } r = port_set_add(task_self(), portSet, timerReplyPort); if (r != KERN_SUCCESS) { mach_error("add timer_reply_port to set", r); return r; } r = port_set_add(task_self(), portSet, xmitReplyPort); if (r != KERN_SUCCESS) { mach_error("add xmit_reply_port to set", r); return r; } r = port_set_add(task_self(), portSet, recvReplyPort); if (r != KERN_SUCCESS) { mach_error("add recv_reply_port to set", r); return r; } r = timer_start(timerPort, ownerPort); if (r != KERN_SUCCESS) { midi_error("timer start", r); return r; } return KERN_SUCCESS; } int midiclose() { kern_return_t r; r = port_set_deallocate(task_self(), portSet); if (r != KERN_SUCCESS) { mach_error("deallocate port set", r); return r; } r = port_deallocate(task_self(), xmitReplyPort); if (r != KERN_SUCCESS) { mach_error("deallocate xmit reply port", r); return r; } r = port_deallocate(task_self(), recvReplyPort); if (r != KERN_SUCCESS) { mach_error("deallocate recv reply port", r); return r; } r = port_deallocate(task_self(), timerReplyPort); if (r != KERN_SUCCESS) { mach_error("deallocate timer reply port", r); return r; } r = port_deallocate(task_self(), ownerPort); if (r != KERN_SUCCESS) { mach_error("deallocate owner port", r); return r; } return KERN_SUCCESS; } int midistarttimer() { kern_return_t r; r = timer_start(timerPort, ownerPort); if (r != KERN_SUCCESS) { midi_error("timer start", r); return r; } return KERN_SUCCESS; } int midistoptimer() { kern_return_t r; r = timer_stop(timerPort, ownerPort); if (r != KERN_SUCCESS) { midi_error("timer stop", r); return r; } return KERN_SUCCESS; } int midisetquantasize(int usec) { kern_return_t r; r = timer_set_quantum(timerPort,ownerPort,(u_int)usec); if (r != KERN_SUCCESS) { midi_error("timer set quantum", r); return r; } quantaSize=(u_int)usec; return KERN_SUCCESS; } int midisettime(int qtime) /* time in quanta */ { kern_return_t r; long utim = qtime*quantaSize; timeval_t time; time.tv_sec=utim/1000000; time.tv_usec=utim-(time.tv_sec*1000000); r = timer_set(timerPort, ownerPort, time); if (r != KERN_SUCCESS) { midi_error("timer set time", r); return r; } return KERN_SUCCESS; } int midigettime(int *databuf) { msg_header_t *msg; kern_return_t r; int keepGoing; msg = (msg_header_t *)malloc(MSG_SIZE_MAX); r = timer_quanta_req(timerPort, timerReplyPort, 0, FALSE); if (r != KERN_SUCCESS) { free((char *)msg); return r; } keepGoing = TRUE; while (keepGoing) { msg->msg_size = MSG_SIZE_MAX; msg->msg_local_port = portSet; r = msg_receive(msg, MSG_OPTION_NONE, 0); if (r != KERN_SUCCESS) { free((char *)msg); return r; } else keepGoing = FALSE; } if (msg->msg_local_port == timerReplyPort) { r = midi_timer_reply_handler(msg, &midiTimerReply); if (r != KERN_SUCCESS) { free((char *)msg); return r; } } else { free((char *)msg); return r; } free((char *)msg); databuf[0]=(int)quantaTime; databuf[1]=(int)quantaSize; return KERN_SUCCESS; } int midiwritemessage(int msg, int qtime) { midi_cooked_data_t cookedData; kern_return_t r; cookedData.quanta = qtime; cookedData.ndata = (char)((msg & 0x03000000) >> 24); cookedData.data[0]=(char)((msg & 0x00ff0000) >> 16); if (cookedData.ndata > 1) cookedData.data[1]=(char)((msg & 0x0000ff00) >> 8); if (cookedData.ndata > 2) cookedData.data[2]=(char)(msg & 0x000000ff); r = midi_send_cooked_data(xmitPort, &cookedData, 1, TRUE); if (r == MIDI_WILL_BLOCK) { return r; } else if (r != KERN_SUCCESS) { midi_error("midi_send_cooked_data", r); return r; } return KERN_SUCCESS; } int midiflushrecv() { return (int)midi_clear_queue(recvPort); } int midiflushxmit() { return (int)midi_clear_queue(xmitPort); } int midiallnotesoff(int time) { int chan, note; midi_cooked_data_t off; kern_return_t r; for (chan = 0; chan < 16; chan++) { for (note = 0; note < 128; note++) { off.quanta = time; off.ndata = 3; off.data[0]=(char)(0x80 | chan); off.data[1]=(char)note; off.data[2]=127; midi_send_cooked_data(xmitPort, &off, 1, TRUE); } } return KERN_SUCCESS; } int midihush () { midiallnotesoff(0); } int midireadmessages() { msg_header_t *msg; kern_return_t r = KERN_SUCCESS; int keepGoing = TRUE; /* * Receive midi events in a loop until no more events * are available. This loop should not be necessary, * but this driver does not return all the current events * at once, ie it takes several calls to midi_get_data to * receive all the current messages from the driver. */ msg = (msg_header_t *)malloc(MSG_SIZE_MAX); while (keepGoing) { r = midi_get_data(recvPort, recvReplyPort); if (r != KERN_SUCCESS) { midi_timer_error("midi_get_data", r); break; } msg->msg_size = MSG_SIZE_MAX; msg->msg_local_port = portSet; r = msg_receive(msg, (RCV_TIMEOUT | RCV_INTERRUPT), 1); switch (r) { case RCV_SUCCESS: if (msg->msg_local_port == recvReplyPort) r = midi_reply_handler(msg, &midiReply); break; case RCV_TIMED_OUT: r = KERN_SUCCESS; keepGoing=FALSE; break; default: r = KERN_FAILURE; keepGoing=FALSE; break; } } free((char *)msg); return r; } /* * Handlers */ kern_return_t myTimerReplyHandler ( void *arg, timeval_t timeval, u_int quanta, u_int usecPerQuantum, u_int realUsecPerQuantum, boolean_t timerExpired, boolean_t timerStopped, boolean_t timerForward) { quantaTime = quanta; quantaSize = usecPerQuantum; return KERN_SUCCESS; } kern_return_t myRecvRawDataHandler(void * arg, midi_raw_t rawData, u_int rawDataCnt) { } #ifdef EXCL #define MIDI_INPUT_HOOK 0 #endif kern_return_t myRecvCookedDataHandler(void * arg, midi_cooked_t cookedData, u_int cookedDataCnt) { #ifdef EXCL long lisp_call(int index, unsigned tim, unsigned msg); #endif #ifdef AKCL void MIDI_INPUT_HOOK(int msg, int tim); #endif unsigned message, quanta; while (cookedDataCnt--) { quanta=(unsigned)cookedData->quanta; /* message type */ if ((cookedData->data[0] & 0xf0) == 0xf0) message = (1 << 27) & 0xc000000; else message = (1 << 26) & 0xc000000; /* message size */ message = message | ((cookedData->ndata << 24) & 0x03000000); /* message data */ message = message | ((cookedData->data[0] << 16) & 0xff0000); message = message | ((cookedData->data[1] << 8) & 0xff00); message = message | (cookedData->data[2] & 0xff); #ifdef EXCL lisp_call(MIDI_INPUT_HOOK, message, quanta); #endif #ifdef AKCL MIDI_INPUT_HOOK((int)message,(int)quanta); #endif cookedData++; } } kern_return_t myRecvPackedDataHandler(void * arg, u_int quanta, midi_packed_t packedData, u_int packedDataCnt) { } kern_return_t myQueueNotifyHandler(void * arg, u_int queueSize) { }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.