home *** CD-ROM | disk | FTP | other *** search
- /********************************************************************************/
- /* MIDI SHARE Application Skeleton */
- /* Version Think C 4.0 */
- /*------------------------------------------------------------------------------*/
- /* MIDISHARE est un module logiciel conçu spécialement pour permettre le fonc- */
- /* tionnement et le développement d'applications Midi dans un contexte multi- */
- /* tâches et temps réel. */
- /* */
- /* MIDISHARE prend en charge la plupart des problèmes spécifiques liés au déve- */
- /* loppement d'applications Midi: gestion des flux Midi, gestion du temps, */
- /* gestion des tâches. En outre, MIDISHARE permet le fonctionnement simultané */
- /* sous Multi-Finder de ces applications, ainsi que l'établissement de connec- */
- /* tions Midi virtuelles entre celles-ci. */
- /* */
- /* SKELETON est un exemple d'application MidiShare minimale qui peut être */
- /* utilisée comme base de développement pour de nouvelles applications. */
- /* Par défaut, l'application renvoie tous les événements qu'elle reçoit, sans */
- /* aucune modification. */
- /* */
- /* Les points qui peuvent être facilement modifiés sont les suivants : */
- /* */
- /* - La constante ApplName : le nom de l'application pour MidiShare */
- /* */
- /* - ReceiveEvents : qui traite tous les événements reçus et qui réalise ici */
- /* un simple MidiThru. */
- /* */
- /* - La constante wantRealTime : quand elle vaut 1, ReceiveEvents est appelée */
- /* sous interruption et fonctionne donc en temps réel, mais ne peut pas */
- /* utiliser les appels à la Toolbox; quand elle vaut 0, ReceiveEvents est */
- /* appelée dans la boucle principale et peut donc utiliser la toolbox. */
- /* */
- /* - La constante wantFilter : quand elle vaut 1, un filtre sur les entrées */
- /* Midi est installé, quand elle vaut 0, aucun filtre n'est installé et */
- /* l'application reçoit tous les événements. */
- /* */
- /* - InstallFilter : qui configure le filtre d'entrée */
- /* */
- /* - La resource de dialogue 128 qui définit la fenêtre de l'application */
- /* */
- /*------------------------------------------------------------------------------*/
- /* © GRAME 1987-92, Yann Orlarey et Hervé Lequay */
- /********************************************************************************/
-
- #include "MIDIShare.h"
-
- #include <Values.h>
- #include <Types.h>
- #include <Resources.h>
- #include <QuickDraw.h>
- #include <Fonts.h>
- #include <Events.h>
- #include <Windows.h>
- #include <Menus.h>
- #include <TextEdit.h>
- #include <Dialogs.h>
- #include <Desk.h>
- #include <ToolUtils.h>
- #include <Memory.h>
- #include <SegLoad.h>
- #include <Files.h>
- #include <OSUtils.h>
- #include <OSEvents.h>
- #include <DiskInit.h>
- #include <Packages.h>
- #include <Traps.h>
-
- /* Quelques constantes Macintosh */
-
- #define nil 0
- #define osEvent app4Evt
- #define resumeMask 1
- #define suspendResumeMessage 1
- #define mouseMovedMessage 0xFA
- #define _Unimplemented 0xA89F /* Unimplemented trap */
- #define _WaitNextEvent 0xA860 /* WaitNextEvent trap */
-
-
- /* Une barre de menus minimale */
-
- #define mBarSize 3
- #define AppleMenu 0
- #define FileMenu 1
- #define EditMenu 2
-
- #define AppleID 128
- #define FileID 129
- #define EditID 130
-
-
- /* Les items du menu Edit */
-
- #define UndoI 1
- #define CutI 3
- #define CopyI 4
- #define PasteI 5
- #define ClearI 6
-
-
- /* La fenêtre de l'application qui est en fait un dialog */
-
- #define WindowID 128
-
-
- /* Pour les erreurs et le About */
-
- #define AboutID 129
- #define AlertID 500
-
-
- /* Constantes pour paramétrer l'application */
-
- #define ApplName "\pSkeleton"
- #define wantRealTime 1
- #define wantFilter 0
-
-
- /* Variables globales pour MidiShare */
-
- short myRefNum; /* numéro d'appl. Midi */
- TFilter myFilter; /* filtre pour les événements Midi */
-
-
- /* Variables globales d'une application Macintosh */
-
- WindowPtr myWindow; /* fenêtre */
-
- Boolean doneFlag; /* flag d'arrêt */
-
- SysEnvRec gMac; /* machine… */
- Boolean hasWNE; /* vrai si WaitNextEvent implémenté */
- Boolean foreGround; /* vrai si en foreGround */
-
- EventRecord myEvent; /* pour la main event loop */
- char theChar; /* pour la gestion des touches */
- Rect dragRect; /* rect de déplacement de fenêtre */
- MenuHandle myMenus[mBarSize]; /* les menus */
-
-
-
-
-
- /********************************************************************************/
- /* Macintosh utilities */
- /*------------------------------------------------------------------------------*/
- /* */
- /********************************************************************************/
-
- void AlertUser (short r) /* Signale une erreur à l'utilisateur */
- {
- Str255 msg;
-
- GetIndString( msg, AlertID, r);
- ParamText( ApplName, msg, "\p", "\p");
- Alert(AlertID,nil);
- ExitToShell();
- }
-
- Boolean TrapAvailable(short trapNum, short tType)
- {
- if ( (tType == ToolTrap) && /* Toolbox trap */
- (gMac.machineType > envMachUnknown) && /* …512KE, Plus, or */
- (gMac.machineType < envMacII) ) { /* …SE */
-
- trapNum &= 0x3FF; /* Traps numbers are 10 bits long */
-
- if (trapNum > 0x1FF) { /* Traps only go up to 0x1FF on */
- return(false); /* these machines */
- }
- }
- return NGetTrapAddress(trapNum, tType) != GetTrapAddress(_Unimplemented);
- }
-
- Boolean IsAppWindow (WindowPtr wind)
- {
- return wind ? ((WindowPeek)wind)->windowKind >= 0 : false ;
- }
-
- Boolean IsDAWindow (WindowPtr wind)
- {
- return wind ? ((WindowPeek)wind)->windowKind < 0 : false ;
- }
-
- void CloseWind (WindowPtr wind)
- {
- if ( IsDAWindow(wind) )
- CloseDeskAcc( ((WindowPeek)wind)->windowKind );
- else if ( IsAppWindow(wind) )
- DisposeWindow(wind);
- }
-
- void CloseAllWinds (WindowPtr wind)
- {
- if (wind) {
- CloseAllWinds( (WindowPtr) (((WindowPeek)wind)->nextWindow) );
- CloseWind(wind);
- }
- }
-
-
-
- /*=============================== MidiShare Part ===============================*/
-
-
- /********************************************************************************/
- /* ReceiveEvents */
- /*------------------------------------------------------------------------------*/
- /* Cette procédure traite tous les événements reçus. Elle peut être appelée */
- /* "manuellement" (wantRealTime 0) dans la boucle principale de l'application */
- /* s'il n'y a pas de contraintes temps réel sur la réception. */
- /* */
- /* Dans le cas contraire (wantRealTime 1), grâce à MidiSetRcvAlarm, la routine */
- /* peut être appelée automatiquement par MidiShare, sous interruptions, chaque */
- /* fois que l'application reçoit de nouveaux événements (voir SetupMidi). */
- /* */
- /* Dans le code ci dessous, ReceiveEvents réalise un simple MidiThru sans */
- /* aucun traitement. */
- /* */
- /* ReceiveEvents doit obligatoirement comporter un paramètre, qui est le */
- /* numéro de référence MidiShare de l'application. */
- /* */
- /* Les paramètres de l'appel : */
- /* --------------------------- */
- /* */
- /* refNum: numéro de référence MidiShare de l'application. */
- /* */
- /********************************************************************************/
-
- pascal void ReceiveEvents (register short r)
- {
- register MidiEvPtr e;
- register long n;
-
- if (n=MidiCountEvs(r)) /* Pour chaque événement reçu : */
- do {
- e = MidiGetEv(r); /* récupérer l'événement */
- /* .... */ /* traiter l'événement */
- MidiSend(r,e); /* renvoyer l'événement */
- }while (--n);
- }
-
-
- /****************************************************************************
- * InstallFilter *
- *---------------------------------------------------------------------------*
- * Cette procédure définit les valeurs du filtre de l'application. Un filtre *
- * est composé de trois parties, qui sont trois tableaux de booléens : *
- * *
- * un tableau de 256 bits pour les ports Midi acceptés *
- * un tableau de 256 bits pour les types d'événements acceptés *
- * un tableau de 16 bits pour les canaux Midi acceptés *
- * *
- * Dans le code ci dessous, le filtre est paramétré pour accepter n'importe *
- * quel type d'événement. *
- * *
- * Les paramètres de l'appel : *
- * --------------------------- *
- * *
- * aucun *
- * *
- *****************************************************************************/
-
- void InstallFilter ()
- {
- register short i;
-
- for (i = 0; i<256; i++)
- {
- AcceptBit(myFilter.evType,i); /* accepte tous les types d'événements */
- AcceptBit(myFilter.port,i); /* en provenance de tous les ports */
- }
-
- for (i = 0; i<16; i++)
- AcceptBit(myFilter.channel,i); /* et sur tous les canaux Midi */
-
- MidiSetFilter( myRefNum, &myFilter ); /* installe le filtre */
- }
-
-
- /********************************************************************************/
- /* SETUP MIDI */
- /*------------------------------------------------------------------------------*/
- /* Vérifie la présence de MidiShare, la possibilité d'ouverture Midi, et */
- /* installe la procédure d'alarme qui sera appelée par MidiShare lors des chan- */
- /* gements de statut des applications ou des ports. */
- /* */
- /* Les paramètres de l'appel : */
- /* --------------------------- */
- /* */
- /* aucun */
- /* */
- /********************************************************************************/
-
- void SetUpMidi()
- {
- if (!MidiShare()) /* Vérifie la présence de MidiShare */
- {
- AlertUser(1);
- }
-
- myRefNum= MidiOpen(ApplName); /* Ouvre l'application pour MidiShare */
- if (myRefNum == MIDIerrSpace) /* Vérifie que tout c'est bien passé */
- {
- AlertUser(2);
- }
-
- if (wantRealTime) /* Installe la routine de réception pour */
- MidiSetRcvAlarm(myRefNum, ReceiveEvents); /* qu'elle soit appelée sous interruptions */
-
- if (wantFilter)
- InstallFilter(); /* Installe le filtre de réception */
-
- MidiConnect(0,myRefNum,true); /* Connecte l'entrée de l'appl. aux entrées physiques */
- MidiConnect(myRefNum,0,true); /* Connecte la sortie de l'appl. aux sorties physiques */
- }
-
-
- /********************************************************************************/
- /* Do Idle */
- /*------------------------------------------------------------------------------*/
- /* Execution des différentes tâches Midi : reception des événements Midi si */
- /* cela n'est pas fait sous interruptions; Exécution des tâches différées en */
- /* attente (tâches crées par MidiDTask). */
- /* */
- /* Les paramètres de l'appel : */
- /* --------------------------- */
- /* */
- /* aucun */
- /* */
- /********************************************************************************/
- void DoIdle()
- {
- register long n;
- register short r;
-
- r = myRefNum;
- if (!wantRealTime) ReceiveEvents(r);
- for (n=MidiCountDTasks(r); n>0; --n) MidiExec1DTask(r);
- /* .... */
- }
-
-
- /********************************************************************************/
- /* Setup windows */
- /*------------------------------------------------------------------------------*/
- /* Ouvre la fenêtre */
- /* */
- /* Les paramètres de l'appel : */
- /* --------------------------- */
- /* */
- /* aucun */
- /* */
- /********************************************************************************/
-
- void SetUpWindows()
- {
- SetRect (&dragRect, qd.screenBits.bounds.left, qd.screenBits.bounds.top,
- qd.screenBits.bounds.right,qd.screenBits.bounds.bottom);
- InsetRect (&dragRect, 4, 4);
-
- myWindow = GetNewDialog (WindowID, nil, (WindowPtr) -1);
- SetPort(myWindow);
- TextFont(monaco); TextSize(9); TextMode(srcCopy); PenNormal();
- ShowWindow(myWindow);
-
- }
-
- /********************************************************************************
- * TrackDialog *
- *------------------------------------------------------------------------------ *
- * Procédure chargée du suivi de la souris. *
- * *
- * Les paramètres de l'appel : *
- * --------------------------- *
- * *
- * w : pointeur sur la fenêtre de dialogue. *
- * p : point où la souris a été cliquée. *
- * *
- ********************************************************************************/
-
- void TrackDialog(WindowPtr w, Point p)
- {
- SetPort(w);
- GlobalToLocal(&p); /* conversion du point en local */
- }
-
-
- /********************************************************************************/
- /* SET UP MENUS */
- /*------------------------------------------------------------------------------*/
- /* Installation de la barre de menus */
- /* */
- /* Les paramètres de l'appel : */
- /* --------------------------- */
- /* */
- /* aucun */
- /* */
- /********************************************************************************/
-
- void SetUpMenus()
- {
- short i;
-
- myMenus[AppleMenu] = GetMenu(AppleID);
- AddResMenu(myMenus[AppleMenu],'DRVR');
- myMenus[FileMenu] = GetMenu(FileID);
- myMenus[EditMenu] = GetMenu(EditID);
- for (i = AppleMenu; i <= EditMenu; i++)
- InsertMenu(myMenus[i], 0);
- DrawMenuBar();
- }
-
- /********************************************************************************/
- /* ADJUST MENUS */
- /*------------------------------------------------------------------------------*/
- /* Ajustement de la barre de menus suivant la fenêtre de premier plan, juste */
- /* lors d'un click dans la barre des menus */
- /* */
- /* Les paramètres de l'appel : */
- /* --------------------------- */
- /* */
- /* aucun */
- /* */
- /********************************************************************************/
-
- void AdjustMenus()
- {
- if ( IsAppWindow( FrontWindow() ) )
- {
- DisableItem( myMenus[EditMenu], UndoI );
- DisableItem( myMenus[EditMenu], CutI );
- DisableItem( myMenus[EditMenu], CopyI );
- DisableItem( myMenus[EditMenu], PasteI );
- DisableItem( myMenus[EditMenu], ClearI );
- }
- else if ( IsDAWindow( FrontWindow() ) )
- {
- EnableItem( myMenus[EditMenu], UndoI );
- EnableItem( myMenus[EditMenu], CutI );
- EnableItem( myMenus[EditMenu], CopyI );
- EnableItem( myMenus[EditMenu], PasteI );
- EnableItem( myMenus[EditMenu], ClearI );
- }
- }
-
- /********************************************************************************
- * Show About *
- *------------------------------------------------------------------------------ *
- * Affiche la fenêtre de About. *
- * *
- * Les paramètres de l'appel : *
- * --------------------------- *
- * *
- * aucun *
- * *
- ********************************************************************************/
- void ShowAbout()
- {
- DialogPtr myDialog;
- short Hit;
-
- myDialog = GetNewDialog(AboutID,nil,(WindowPtr) -1);
- if (myDialog) {
- ModalDialog(nil,&Hit);
- DisposDialog(myDialog);
- } else {
- SysBeep(0);
- }
- }
-
- /********************************************************************************
- * DO COMMAND *
- *------------------------------------------------------------------------------ *
- * Execution des commandes du menu. Ici on se contente de gérer les accessoires *
- * le About et la commande Quit. *
- * *
- * Les paramètres de l'appel : *
- * --------------------------- *
- * *
- * mResult : le menu et l'item sélectionnés *
- * *
- ********************************************************************************/
- void DoCommand(long mResult)
- {
- short theItem;
- short theMenu;
- Str255 name;
-
- theItem = LoWord(mResult);
- theMenu = HiWord(mResult);
-
- switch ( theMenu )
- {
- case AppleID:
- if (theItem != 1)
- {
- GetItem(myMenus[AppleMenu], theItem, name);
- theItem = OpenDeskAcc(name);
- } else {
- ShowAbout();
- }
- break;
- case EditID:
- SystemEdit( theItem-1 );
- break;
- case FileID:
- doneFlag = true;
- break;
- }
- HiliteMenu(0);
- }
-
- /********************************************************************************/
- /* DO MOUSE DOWN */
- /*------------------------------------------------------------------------------*/
- /* Gère les clicks souris */
- /* */
- /* Les paramètres de l'appel : */
- /* --------------------------- */
- /* */
- /* aucun */
- /* */
- /********************************************************************************/
-
- void DoMouseDown()
- {
- WindowPtr whichWindow;
-
- switch ( FindWindow( myEvent.where, &whichWindow ) )
- {
- case inMenuBar:
- AdjustMenus();
- DoCommand(MenuSelect(myEvent.where));
- break;
- case inSysWindow:
- SystemClick(&myEvent, whichWindow);
- break;
- case inGoAway:
- doneFlag = TrackGoAway(whichWindow, myEvent.where);
- break;
- case inDrag:
- DragWindow(whichWindow, myEvent.where, &dragRect);
- break;
- case inContent:
- if (whichWindow != FrontWindow())
- SelectWindow(whichWindow);
- else if (whichWindow == myWindow)
- TrackDialog(myWindow, myEvent.where);
- break;
- }
- }
-
-
- /********************************************************************************/
- /* ADJUST CURSOR */
- /*------------------------------------------------------------------------------*/
- /* Ajuste le curseur suivant région et fenêtre */
- /* */
- /********************************************************************************/
-
- void AdjustCursor()
- {
- if (foreGround && IsAppWindow(FrontWindow()))
- SetCursor(&qd.arrow);
- }
-
-
- /********************************************************************************/
- /* INITIALIZE */
- /*------------------------------------------------------------------------------*/
- /* Initialisations générales (hasWNE, foreGround, managers, fenêtre, Midi) */
- /* */
- /* Les paramètres de l'appel : */
- /* --------------------------- */
- /* */
- /* aucun */
- /* */
- /********************************************************************************/
-
- void Initialize()
- {
- OSErr err;
-
- err = SysEnvirons(1, &gMac);
- if (gMac.machineType < 0) AlertUser(3);
- hasWNE = TrapAvailable(_WaitNextEvent, ToolTrap);
- foreGround = true;
-
- InitGraf(&qd.thePort); /* initialise QuickDraw */
- InitFonts(); /* initialise le Font Manager */
- InitWindows(); /* initialise le Window Manager */
- InitDialogs(nil); /* initialise le Dialog Manager */
- InitMenus(); /* initialise le Menu Manager */
- TEInit(); /* initialise le Text Edit Manager */
- InitCursor(); /* initialise le curseur de la souris */
-
- FlushEvents(everyEvent, 0); /* efface événements Mac en attente */
-
- SetUpMenus(); /* mise en place menus */
- SetUpMidi(); /* ouverture MidiShare */
- SetUpWindows(); /* initialisations fenêtre et listes */
- }
-
- /********************************************************************************/
- /* Corps Principal */
- /*------------------------------------------------------------------------------*/
- /* Initialisation des managers, ouverture fenêtre, initialisations diverses et */
- /* tutti quanti, boucle principale. */
- /* */
- /********************************************************************************/
-
- void main()
- {
- Boolean b;
-
- MaxApplZone();
- Initialize();
-
- doneFlag = false;
- while (!doneFlag) { /* Main Loop */
- if (hasWNE)
- b = WaitNextEvent(everyEvent, &myEvent, 0, nil); /* no sleep, no mouseRgn */
- else {
- SystemTask();
- b = GetNextEvent(everyEvent, &myEvent);
- }
- AdjustCursor();
- switch( myEvent.what ) {
- case nullEvent:
- DoIdle();
- break;
- case osEvent:
- switch (myEvent.message >> 24) {
- case suspendResumeMessage:
- foreGround = myEvent.message & resumeMask;
- break;
- case mouseMovedMessage:
- DoIdle();
- break;
- }
- break;
- case keyDown:
- case autoKey:
- theChar = myEvent.message & charCodeMask;
- if (myEvent.modifiers & cmdKey ) {
- AdjustMenus();
- DoCommand(MenuKey(theChar));
- }
- break;
- case mouseDown:
- DoMouseDown();
- break;
- case updateEvt:
- if ( IsAppWindow( (WindowPtr)myEvent.message ) ) {
- BeginUpdate( (WindowPtr)myEvent.message );
- if ( !EmptyRgn( ((WindowPtr)myEvent.message)->visRgn ) ) {
- SetPort( (WindowPtr)myEvent.message );
- DrawDialog( (WindowPtr)myEvent.message );
- }
- EndUpdate( (WindowPtr)myEvent.message );
- }
- break;
- }
- }
- MidiClose(myRefNum);
- CloseAllWinds( FrontWindow() );
- }
-