MidiMain.c++ 5.16 KB
/******************************************************************************
 *
 *    midiMain.c++ 
 *    Main function for the midi thread
 * 
 *****************************************************************************/

#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <strings.h>
#include <dmedia/midi.h>

#include "MidiMain.h"
#include "n64.h"
#include "AeN64Driver.h"


extern AeN64Driver *	n64Driver;


// int             gCurChanInst[MAX_SEQ_CHANNELS];
int             numPorts;
MDport          midiInPort[MAX_MIDI_PORTS];
MDevent         midiEvents[MAX_MIDI_MSGS];
int             midiFds[MAX_MIDI_PORTS];
fd_set          inports;
int             highfd;

int             midiVerbose;
extern char	verbose;

void ReceiveMidi(MDport inPort);
int  initMidi(void);

void midiMain(void * arg)
{
    int   nfds, c;

    if(initMidi() == MIDI_OK)
    {
	while(1)
	{
	    nfds = select(highfd,&inports,0,0,0);
	    for (c = 0; c < numPorts; c++)
	    {
		if (FD_ISSET(midiFds[c],&inports))
		    ReceiveMidi(midiInPort[c]);
		else
		    FD_SET(midiFds[c],&inports);
	    }
	}
    }

// if you get here, there is no midi, don't quit or that will cause
// a child died signal. Instead just go to sleep forever.
    while(1)
	sleep(0xFFFFFFFF);
}

int initMidi(void)
{
    int             c;
    char            *portname;

    numPorts=mdInit();  /* start midi lib stuff, and open in port */
    if (numPorts<1)
    {
	if (verbose)
	    fprintf (stdout, "warning: no ports configured for midi.\n"); 

	return(NO_MIDI);
    }
    if(numPorts>MAX_MIDI_PORTS)
    {
        fprintf(stdout,"warning:\tmore than %d ports configured for midi.\n",
		MAX_MIDI_PORTS);
        fprintf(stdout,"\t\tWill use only the first %d ports.\n",
		MAX_MIDI_PORTS);
        numPorts=MAX_MIDI_PORTS;
    }

    for(c=0;c<numPorts;c++)
    {
        portname=mdGetName(c);

        if(portname==NULL)
	{
            fprintf(stdout,"error: port %d is not correctly set for midi.\n",c+1);
	    return(MIDI_INIT_ERR);
	}
        midiInPort[c]=mdOpenInPort(portname);
        if(midiInPort[c]==NULL)
	{
	    fprintf(stdout,"error: failure opening midi in port for %s\n",
		    portname);
	    return(MIDI_INIT_ERR);
	}
        mdSetStampMode(midiInPort[c],MD_NOSTAMP);
        midiFds[c]=mdGetFd(midiInPort[c]);
        FD_SET(midiFds[c],&inports);
        highfd = midiFds[c] + 1; 

	if (verbose)
	    fprintf(stdout, "debug: %s successfully opened for MIDI receive\n",
		    portname);
    }
    return(MIDI_OK);
}
/********************************************************************
 *
 *  Receive Midi.  Primary midi receiving routine.  Upon receiving
 *  midi, seperate out system exclusive, from regular status mesgs.
 *  Send regular messages in one block, for each system exclusive,
 *  Handle one at a time, by calling ProcessSysEx
 *
 *********************************************************************/

void ReceiveMidi(MDport inPort)
{
    int             validMsgs = 0;
    int             numMsgs,ct,msgType;
    char            chan;
    unsigned char   status;
    CommPckt        commPckt;


#ifdef TIMING_DEBUG
    unsigned long long deltaTime,gioTime;
    float              deltaFlt;
#endif
    
    numMsgs=mdReceive(inPort,midiEvents,MAX_MIDI_MSGS);
    if(numMsgs < 0)
    {
	if (verbose)
	    fprintf(stdout,"error: received corrupt midi data\n");
        return;
    }
    else if(numMsgs > 0)
    {
        for(ct=0;ct<numMsgs;ct++)
        {
#ifdef TIMING_DEBUG
	    syssgi(SGI_GET_UST,&deltaTime,0);
	    deltaTime -= gMidiEvents[ct].stamp;
	    deltaFlt = deltaTime;
	    deltaFlt /= 1000; /* nanoseconds to microseconds */
#endif
            
            status = midiEvents[ct].msg[0] & 0xF0;

            if(status) /* status has a value */
            {
                switch(status)
                {
                    case 0x80: /* note off         */
                    case 0x90: /* note on          */
                    case 0xA0: /* poly pressure    */
                    case 0xB0: /* controller       */
                    case 0xC0: /* program change */
                    case 0xD0: /* channel pressure */
                    case 0xE0: /* pitch bend       */
                        commPckt.d.mb.mess[validMsgs].midiByte[0]=midiEvents[ct].msg[0];
                        commPckt.d.mb.mess[validMsgs].midiByte[1]=midiEvents[ct].msg[1];
                        commPckt.d.mb.mess[validMsgs].midiByte[2]=midiEvents[ct].msg[2];
                        validMsgs++;
                        break;
                    case 0xF0:
			if(midiEvents[ct].msg[0] == 0xFF) 
			{
			    commPckt.d.mb.mess[validMsgs].midiByte[0]=midiEvents[ct].msg[0];
			    commPckt.d.mb.mess[validMsgs].midiByte[1]=midiEvents[ct].msg[1];
			    commPckt.d.mb.mess[validMsgs].midiByte[2]=midiEvents[ct].msg[2];
			    validMsgs++;
			}
                        break;
                }
		if(midiVerbose)
		    fprintf(stdout, "midi data: %x %x %x\n",midiEvents[ct].msg[0],
			   midiEvents[ct].msg[1],midiEvents[ct].msg[2]);
            }
        }
        
        if(validMsgs)
        {
            commPckt.pcktType = STATUS_TYPE;
            commPckt.d.mb.numEvts = validMsgs;

	    if (n64Driver)
		n64Driver->SendMidiBlock(&commPckt);
        }
    }
}