midiDmon.c 7.3 KB

#include <dmedia/midi.h>

#include <sys/types.h>
#include <sys/prctl.h>
#include <sys/ipc.h>

#include <ultratypes.h>
#include <libaudio.h> 
#include <audiotools.h>
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <poll.h> 
#include <unistd.h>
#include <fcntl.h>

#include <ramrom.h>
#include <u64gio.h>
#include "midiApp.h"


char        gAppName[]="midiDmon";
int         gGIOfd;
int         verbose;
 
MDevent     gMidiEvents[MAX_MSGS];
MDport      gMidiOutPort[MAX_PORTS];
MDport      gMidiInPort[MAX_PORTS];
int         gNumPorts;
u32         gBankOffset;



/********************************************************************
 *
 *  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;

    unsigned char   status;
    midiBlock       midiBlk;
    u64_write_arg_t writeHdr;


    numMsgs=mdReceive(inPort,gMidiEvents,MAX_MSGS);
    if(numMsgs<0)
        fprintf(stdout,"%s: ERROR receiving midi data!\n",gAppName);
                
    else if(numMsgs>0)
    {
        if(verbose)
            fprintf(stdout,"%d midi messages received\n",numMsgs);

        for(ct=0;ct<numMsgs;ct++)
        {
            status = gMidiEvents[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 0xC0: /* program change */
                    case 0xE0: /* pitch bend     */
                        midiBlk.mess[validMsgs].midiByte[0]=gMidiEvents[ct].msg[0];
                        midiBlk.mess[validMsgs].midiByte[1]=gMidiEvents[ct].msg[1];
                        midiBlk.mess[validMsgs].midiByte[2]=gMidiEvents[ct].msg[2];
                        validMsgs++;
                        break;
                    case 0xB0:
                        switch(gMidiEvents[ct].msg[1])
                        {
                            case 7:
                            case 10:
                            case 64:
                            case 91:
                                midiBlk.mess[validMsgs].midiByte[0]=gMidiEvents[ct].msg[0];
                                midiBlk.mess[validMsgs].midiByte[1]=gMidiEvents[ct].msg[1];
                                midiBlk.mess[validMsgs].midiByte[2]=gMidiEvents[ct].msg[2];
                                validMsgs++;
                                break;
                            default:
                                if(verbose)
                                fprintf(stdout,"Unhandled controller %d\n",
                                        gMidiEvents[ct].msg[1]);
                                break;
                        }
                        break;
                    default:
                        if(verbose)
                            fprintf(stdout,"Unhandled midi 0x%X\n",gMidiEvents[ct].msg[0]);
                        break;
                }
            }
        }
        
        if(validMsgs)
        {
            midiBlk.pcktType = STATUS_TYPE;
            midiBlk.numEvts = validMsgs;
            writeHdr.buffer = &midiBlk;
            writeHdr.ramrom_addr = RAMROM_APP_READ_ADDR;
            writeHdr.nbytes =  sizeof(midiBlock);
            writeHdr.value = HOST_APP_CMD_READY;

            ioctl(gGIOfd, U64_SAFE_WRITE, &writeHdr); 
            if(verbose)
                printf("Back from IOCTL\n"); 


            if(verbose)
                for(ct=0;ct<validMsgs;ct++)
                    fprintf(stdout,"midiDmon: 0x%X 0x%X 0x%X\n",
                        midiBlk.mess[ct].midiByte[0],
                        midiBlk.mess[ct].midiByte[1],
                        midiBlk.mess[ct].midiByte[2]);

        }
    }
}


/*****************************************************************
 *
 *  Midi Daemon.  Initialize midi connections, poll each one in turn
 *  if you receive any midi data, call handling routine.
 *
 *******************************************************************/
void MidiDaemon(void *arg)
{
    int             c;
    char            *portname;
    MDport          midiInPort[MAX_PORTS];
    struct pollfd   midiFdSet[MAX_PORTS];
    int             numBytes,dummyBuf;
    
    gNumPorts=mdInit();  /* start midi lib stuff, and open in port */

    if(verbose)
        fprintf(stdout,"%d ports for midi\n",gNumPorts);

    if (gNumPorts<1)
    {
        fprintf(stdout,"%s: No ports configured for midi. Exiting\n",gAppName); 
        exit(-1);
    }
    if(gNumPorts>MAX_PORTS)
    {
        fprintf(stdout,"%s: More than %d ports configured for midi.\n",gAppName,MAX_PORTS);
        fprintf(stdout,"%s: Will use only the first %d ports.\n",gAppName,MAX_PORTS);
        gNumPorts=MAX_PORTS;
    }

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

        if(portname==NULL)
            fprintf(stdout,"%s: Port %d is not correctly set for midi.\n",gAppName,c+1);
        if(verbose)
            fprintf(stdout,"%s signed in for midi input\n", portname);
        
        midiInPort[c]=mdOpenInPort(portname);
        if(midiInPort[c]==NULL)
            fprintf(stdout,"%s: Failure opening midi in port for %s\n",gAppName,portname);

        midiFdSet[c].fd=mdGetFd(midiInPort[c]);
        midiFdSet[c].events=POLLIN; 

        gMidiOutPort[c]=mdOpenOutPort(portname);
        if(gMidiOutPort[c]==NULL)
            fprintf(stdout,"%s: Failure opening midi in port for %s\n",gAppName,portname);
        if(verbose)
            fprintf(stdout,"%s signed in for midi output\n", portname);

        mdSetStampMode(gMidiOutPort[c],MD_NOSTAMP);
    }

    gGIOfd = open(DEV_U64, O_RDWR);
    if (gGIOfd == -1)
    {
        fprintf(stderr, "%s: Unable to open %s, Exiting\n",gAppName, DEV_U64);
        exit(-1);
    }
    ioctl(gGIOfd, U64_LISTEN, GAME_APP_DATA_READY);
    numBytes=read(gGIOfd,&dummyBuf,1);

    if(verbose)
        fprintf(stdout,"%s and Ultra64 in synch\n",gAppName);


/*  Continually poll midi ports, and if you get some data, handle it. */

    while(1)
    {
        for(c=0;c<gNumPorts;c++)
        {
            if(poll(&midiFdSet[c],1,0))  /* see if there is midi data waiting to be read */
                ReceiveMidi(midiInPort[c]);

        }        
    }
}


/*******************************************************************************
 *
 *  main()  Parse the arguments and lauch the midi processing daemon
 *
 *******************************************************************************/

int main(int argc, char **argv)
{
    int     c,newPID;
    extern char *optarg;

    while ((c = getopt(argc, argv, "vmhs:")) != EOF)
    {
        switch (c) 
        {
            case 'v':
                verbose = TRUE;
                break;
            case '?':
                printf("midiDmon: Usage -v(erbose)\n");
                break;
        }
    }
    newPID = sproc(MidiDaemon, PR_SALL, NULL);
    if (newPID < 0)
    {
        fprintf(stderr, "%s: AACK! Unable to start midi processing daemon!\n", argv[0]);
        exit(-1);
    }
}