⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 midimgr.c

📁 Audacity是一款用於錄音和編輯聲音的、免費的開放源碼軟體。它可以執行於Mac OS X、Microsoft Windows、GNU/Linux和其它作業系統
💻 C
📖 第 1 页 / 共 2 页
字号:
/* midimgr.c -- this file contains interface code to support use of Apple Midi Manager *//* * This code is based on code supplied with the Apple Midi Manager. * Copyright 1991, Carnegie Mellon University */ /* BUGS:  *     If exclusive() is called to turn exclusive messages on or off DURING the * receipt of an exclusive message, incoming data will be garbled.  The correct * handling would be to record when receipt of an exclusive message is in * progress, then properly remove any partial message when exclusive is turned * off, and ignore any remaining message part when exclusive is turned on. * The present code does neither. */ #include "cext.h"#undef round#ifdef THINK_C#include <pascal.h> /* for ThinkC 7 */#endif#include "stdio.h"#include "userio.h"#include "MIDI.h"#include "midifns.h"#include "midibuff.h"#include "midierr.h"#include "midimgr.h"#include "midicode.h"#include "cmdline.h"/* Needed for KillEverybody */#include <toolutils.h>#include <AppleEvents.h>#include <EPPC.h>#include <Gestalt.h>#include <PPCToolbox.h> #include <Processes.h>#include <Sound.h>#define CMTclientID             'CMT '/* note the following are in alphabetical order for Patcher display */#define timePortID              'Atim'#define inputPortID             'Bin '#define outputPortID    'Cout'#define noClient                '    '#define noTimeBaseRefNum        0#define noReadHook                      0L#define zeroTime                        0L#define timePortBuffSize        0L#define inputPortBuffSize       2048#define outputPortBuffSize      0L#define refCon0 0Lpascal short CMTreader(MIDIPacket *ThePacketPtr, long TheRefCon);/* "patch" switch from command line.  This switch is cached in patch_flag and tells   whether to look in the resource fork for a patch, or just hook up to midi in and   out.  If the resource fork is used, the patch will be saved upon exit. */private boolean patch_flag; extern boolean ctrlFilter;extern boolean exclFilter;extern boolean realFilter;private midi_read_lock = false;	/* used to stop input during data structure manipulation */private void set_error(int bit);#ifndef NYQUISTvoid PatchPorts(void);void SavePatch(OSType PortID, short PortInfoResID, char *PortInfoResName);#endif/* exported:  */public short InputRefNum;                       /* Input port reference number. */public short OutputRefNum;                      /* Output port reference number. */public short TimeRefNum;                        /* Time base port reference number. */Boolean         GManualPatch;   /* True if not launched by a PatchBay Config. File. *//******************************************************************************       variables shared with other modules*****************************************************************************//* midi input buffer */long buff[BUFF_SIZE/4]; /* data buffer, declared long to get 32-bit alignment */int buffhead = 0;               /* buffer head and tail pointers */int bufftail = 0;/* user supplied system exclusive buffer */byte *xbuff = NULL;     /* address of the user-supplied buffer */public long xbufmask;    /* mask for circular buffer address calculation */long xbufhead = 0;       /* buffer head and tail pointers */long xbuftail = 0;boolean xbuf_flush = true;	/* says to flush remainder of sysex message */#ifdef SYSEXDEBUGint sysexcount = 0;	/* for debugging */int sysexdone = 0;int sysexheadcount = 0;byte sysexfirst = 0;int sysexsysex = 0;#endif/* midi_flush -- empty out buffers *//**/void midi_flush(){    midi_read_lock = true;    buffhead = 0;    bufftail = 0;    xbufhead = 0;    xbuftail = 0;    xbuf_flush = true;	/* in case sysex continuation messages are still coming */    midi_read_lock = false;}/* Nyquist only uses CMT for Midi and Adagio file IO */#ifndef NYQUIST/* Get String representation of MIDI Mgr Version Num.*//* See Mac Tech Note #189 for details. */char *StdMacVerNumToStr(long VerNum, char *VerStr){        char    *RetVal;        char    MajVer, MinVer, VerStage, VerRev, BugFixVer = 0;                if (VerNum == 0)        {                RetVal = NULL;        }        else        {                MajVer          = (VerNum & 0xFF000000) >> 24;                MinVer          = (VerNum & 0x00FF0000) >> 16;                VerStage        = (VerNum & 0x0000FF00) >> 8;                VerRev          = (VerNum & 0x000000FF) >> 0;                BugFixVer       =  MinVer & 0x0F;                                switch (VerStage)                {                        case 0x20:                                    VerStage = 'd';                                    break;                        case 0x40:                                    VerStage = 'a';                                    break;                        case 0x60:                                    VerStage = 'b';                                    break;                        case 0x80:                                    VerStage = ' ';                                    break;                        default:                                    VerStage = '?';                                    break;                }                                if (BugFixVer == 0)                {                        sprintf(VerStr,"%X.%X%c%X",                                     MajVer, MinVer>>4, VerStage, VerRev);                }                else                {                        sprintf(VerStr,"%X.%X.%X%c%X",                                     MajVer, MinVer >> 4, MinVer & 0x0F, VerStage, VerRev);                }                                RetVal = VerStr;        }                        return(RetVal);}/* C2PStrCpy -- Convert a C String (from Cstr) into a Pascal string *//* * NOTE: this is not the same code as shipped with midi manager example */char *C2PStrCpy(char *Cstr, Str255 Pstr){        char *c = Cstr;        char *p = ((char *) Pstr) + 1;                while (*c) *p++ = *c++;        *Pstr = c - Cstr;        return( (char *) Pstr );}/* This checks to see if THINK C is running under System 7,   and ONLY WORKS UNDER SYSTEM 7!  Don't use unless you check! */boolean ThinkCRunning(void){     ProcessSerialNumber processSN;    OSErr myErr;    ProcessInfoRec infoRec;        processSN.lowLongOfPSN = kNoProcess;    processSN.highLongOfPSN = kNoProcess;    do {        myErr = GetNextProcess(&processSN);                infoRec.processInfoLength = sizeof(ProcessInfoRec);        infoRec.processName = 0L;        infoRec.processAppSpec = 0L;        myErr = GetProcessInformation(&processSN, &infoRec);        if (!myErr) {                if (infoRec.processSignature == 'KAHL') {                    return(true);                }        }    } while (myErr == noErr);    return(false);}/* This kills off all the other running processes...    ONLY WORKS UNDER SYSTEM 7!  Don't use unless you check! */void KillEverybody(void){    ProcessSerialNumber myProc, processSN;    ProcessSerialNumber finderPSN;    ProcessInfoRec infoRec;    Str31 processName;    FSSpec procSpec;        OSErr myErr = noErr;    OSErr otherError;    AppleEvent theEvent;    AEDesc theAddress;    Boolean ourFlag, notFinder;    Boolean finderFound = false;        GetCurrentProcess(&myProc);    /* Preset the PSN to no PSN, see IM VI, the Process Manager */    processSN.lowLongOfPSN = kNoProcess;    processSN.highLongOfPSN = kNoProcess;    finderPSN.lowLongOfPSN = 0UL; /* brk: was nil */    finderPSN.highLongOfPSN = 0UL; /* brk: was nil */        do {        myErr = GetNextProcess(&processSN);        /* See if it's us first */        notFinder = true;        SameProcess(&myProc, &processSN, &ourFlag);            infoRec.processInfoLength = sizeof(ProcessInfoRec);            infoRec.processName = (StringPtr) &processName;            infoRec.processAppSpec = &procSpec;            GetProcessInformation(&processSN, &infoRec);        if (!ourFlag && !finderFound) {            /* see if it's the Finder, we have to kill the finder LAST */            /* or else non-sys 7 apps won't get killed */            /* since the Finder must be there to convert the AppleEvent to Puppet Strings */            /* if the app is not APpleEvent aware */            /* Also, FileShare HAS to be killed before the Finder */            /* or your life will be unpleasant */            if (infoRec.processSignature == 'MACS' && infoRec.processType == 'FNDR') {                /* save this number for later  */                finderPSN = processSN;                notFinder = false;                finderFound = true;                        } else {                notFinder = true;            }        }        if (!myErr && !ourFlag && notFinder) {            otherError = AECreateDesc(typeProcessSerialNumber, (Ptr)&processSN, sizeof(processSN), &theAddress);            if (!otherError)                otherError = AECreateAppleEvent(kCoreEventClass, kAEQuitApplication, &theAddress, kAutoGenerateReturnID,                                                                    kAnyTransactionID, &theEvent);            if (!otherError)                AEDisposeDesc(&theAddress);            /* Again, the Finder will convert the AppleEvent to puppetstrings if */            /* the application is a System 6 or non-AE aware app.  This ONLY  */            /* happens for the 4 required (oapp,odoc,pdoc, and quit) AppleEvents  */            /* and ONLY if you use the PSN for the address */            if (!otherError)                AESend(&theEvent, 0L, kAENoReply + kAEAlwaysInteract + kAECanSwitchLayer, kAENormalPriority, kAEDefaultTimeout,                       0L, 0L);            AEDisposeDesc(&theEvent);        }    } while (!myErr);        /* Now, if the finder was running, it's safe to kill it */    if (finderPSN.lowLongOfPSN || finderPSN.highLongOfPSN) {        otherError = AECreateDesc(typeProcessSerialNumber, (Ptr)&finderPSN, sizeof(processSN), &theAddress);        if (!otherError)            otherError = AECreateAppleEvent(kCoreEventClass, kAEQuitApplication, &theAddress, kAutoGenerateReturnID,                                                            kAnyTransactionID, &theEvent);        if (!otherError)            AEDisposeDesc(&theAddress);        if (!otherError)            AESend(&theEvent, 0L, kAENoReply + kAEAlwaysInteract + kAECanSwitchLayer, kAENormalPriority, kAEDefaultTimeout, 0L,                   0L);        AEDisposeDesc(&theEvent);    }}/* Sign into the MIDI Manager. *//* Set up time, input, and output ports. *//* Start our time base clock. */void setup_midimgr(void){    MIDIPortParams  Init;   /* MIDI Mgr Init data structure */     Handle                  TheIconHndl;    OSErr                   TheErr;    long                    MIDIMgrVerNum;  /* MIDI Manager Ver (Std Mac Ver #) */    Str255 name = "\pCMU MIDI Toolkit";    char MIDIMgrVerStr[256]; /* MIDI Manager Ver (Std Mac Ver # String) */    long vers;    EventRecord theEvent;        Gestalt(gestaltSystemVersion, &vers);    vers = (vers >> 8) & 0xf;                               /* shift result over and mask out major version number */    if ((vers >= 7) && (!cl_switch("keep"))  && (!ThinkCRunning()))  {        gprintf(TRANS,"Killing other processes...\n");        KillEverybody();        for (vers=0; vers<100; ++vers) {            while (WaitNextEvent(everyEvent, &theEvent, 0L, 0L)) ;        }    }            /* Make sure MIDIMgr is installed and save version num. */    MIDIMgrVerNum = SndDispVersion(midiToolNum);    if (MIDIMgrVerNum == 0) {        gprintf(ERROR, "The MIDI Manager is not installed! Exiting...\n");        EXIT(1);    } else {                StdMacVerNumToStr(MIDIMgrVerNum, MIDIMgrVerStr);        gprintf(TRANS,"MIDI Manager Version %s\n", MIDIMgrVerStr);    }            /* Sign in to the MIDI Manager. */    TheIconHndl = GetResource('ICN#', 1);    TheErr = MIDISignIn(CMTclientID,                        0L,                         TheIconHndl,                        name);    if (TheErr) {            gprintf(ERROR, "Trouble signing into MIDI Manager!  Aborting...");            EXIT(1);    }    /* Assume not a Patchbay configuration. */    GManualPatch = true;        /* Add time port. */    Init.portID = timePortID;    Init.portType = midiPortTypeTime;    Init.timeBase = noTimeBaseRefNum;    Init.readHook = noReadHook;    Init.initClock.syncType = midiInternalSync;    Init.initClock.curTime = zeroTime;    Init.initClock.format = midiFormatMSec;    Init.refCon = SetCurrentA5();    C2PStrCpy("TimeBase", Init.name);    TheErr = MIDIAddPort(CMTclientID, timePortBuffSize, &TimeRefNum, &Init);    /* Has a PatchBay connection been resolved? */    if (TheErr == midiVConnectMade) {        GManualPatch = false;    } else if (TheErr == memFullErr) {        gprintf(ERROR, "Not enough room in heap zone to add time port!  Aborting...");        MIDISignOut(CMTclientID);               EXIT(1);    }            /* Add an input port. */    Init.portID = inputPortID;    Init.portType = midiPortTypeInput;    Init.timeBase = TimeRefNum;    Init.offsetTime = midiGetCurrent;    Init.readHook = NewMIDIReadHookProc(CMTreader);    Init.refCon = SetCurrentA5();    C2PStrCpy("InputPort", Init.name);    TheErr = MIDIAddPort(CMTclientID, inputPortBuffSize, &InputRefNum, &Init);    /* Has a PatchBay connection been resolved? */    if (TheErr == midiVConnectMade) {        GManualPatch = false;    } else if (TheErr == memFullErr) {        gprintf(ERROR, "Not enough room in heap zone to add input port!  Aborting...");        MIDISignOut(CMTclientID);               EXIT(1);    }            /* Add an output port. */    Init.portID = outputPortID;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -