Obligement - L'Amiga au maximum

Samedi 16 novembre 2019 - 22:18  

Translate

En De Nl Nl
Es Pt It Nl


Rubriques

 · Actualité (récente)
 · Actualité (archive)
 · Comparatifs
 · Dossiers
 · Entrevues
 · Matériel (tests)
 · Matériel (bidouilles)
 · Points de vue
 · En pratique
 · Programmation
 · Reportages
 · Quizz
 · Tests de jeux
 · Tests de logiciels
 · Tests de compilations
 · Trucs et astuces
 · Articles divers

 · Articles in english
 · Articles en d'autres langues


Twitter

Suivez-nous sur Twitter




Liste des jeux Amiga

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z


Trucs et astuces

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z


Glossaire

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z


Galeries

 · Menu des galeries

 · BD d'Amiga Spécial
 · Caricatures Dudai
 · Caricatures Jet d'ail
 · Diagrammes de Jay Miner
 · Images insolites
 · Fin de jeux (de A à E)
 · Fin de Jeux (de F à O)
 · Fin de jeux (de P à Z)
 · Galerie de Mike Dafunk
 · Logos d'Obligement
 · Systèmes d'exploitation
 · Trombinoscope Alchimie 7
 · Vidéos


Téléchargement

 · Documents
 · Jeux
 · Logiciels
 · Magazines
 · Divers


Liens

 · Sites de téléchargements
 · Associations
 · Pages Personnelles
 · Matériel
 · Réparateurs
 · Revendeurs
 · Presse et médias
 · Programmation
 · Logiciels
 · Jeux
 · Scène démo
 · Divers


Partenaires

Annuaire Amiga

Amedia Computer

Relec

Hit Parade


A Propos

A propos d'Obligement

A Propos


Contact

David Brunet

Courriel

 


Programmation : C - Fenêtres Intuition et timer.device
(Article écrit par Denis Genot et extrait d'Amiga News Tech - août 1992)


L'inconvénient des fenêtres d'Intuition est qu'elles ne permettent pas de faire autre chose, par exemple une animation, pendant que l'on attend une réaction de l'utilisateur. En tout cas, pas directement...

Typiquement, un programme ouvre sa ou ses fenêtre(s), dessine un titre et quelques gadgets, puis attend patiemment que l'utilisateur veuille bien se décider à lui faire part de ses désirata. Cette attente s'effectue généralement par l'une des deux méthodes suivantes (qui sont d'ailleurs parfaitement équivalentes) :

WaitPort(Window->UserPort);

Ou

Wait(1L << Win->UserPort->mp_SigBit);

L'ennui, c'est que l'on n'a plus la main car le programme est gelé tant qu'un évènement n'a pas lieu... Impossible donc de faire, par exemple, une animation pendant ce temps.

Première solution

La première solution consiste à mettre le drapeau IDCMP INTUITICKS dans la structure NewWindow de la fenêtre à ouvrir : il demande à Intuition d'envoyer un message au propriétaire de la fenêtre tous les (en gros) 1/50e de seconde.

Avantage de la méthode : elle est très simple à mettre en oeuvre (l'intuition.library suffit amplement).

Inconvénient : le message INTUITICKS n'est envoyé qu'à une seule fenêtre, celle active au moment de l'évènement. Si l'utilisateur délaisse votre programme quelques instants, plus de messages, donc plus d'animation.

Seconde solution

La seconde solution utilise le timer.device pour demander au système d'être prévenu quand un certain délai s'est écoulé.

Avantage : cela fonctionne tout le temps, que notre fenêtre soit active ou pas.

Inconvénient : c'est un peu plus difficile à mettre en oeuvre. On n'a rien sans rien !

Pour utiliser le timer.device, on aura pris soin :
  • D'initialiser une structure "timerequest" pour envoyer la demande au système.
  • D'initialiser une structure "timeval" avec le délai voulu.
  • D'initialiser une structure "msgPort" pour obtenir la réponse.
  • D'ouvrir le timer.device, bien sûr !
L'envoi de la demande, qui peut se traduire par "préviens-moi quand le délai sera écoulé", se fait avec la fonction SendIO(), qui présente, contrairement à DoIO(), l'avantage d'être asynchrone (keskidi ?).

Avec DoIO(), le programme est interrompu tant que la demande n'est pas satisfaite, ce qui dans notre exemple empêcherait de gérer les gadgets en attendant le délai (requête synchrone). Avec SendIO(), le programme continue tranquillement d'être exécuté, ce qui permet de tester les gadgets, le clavier, l'arrivée de sa belle-mère... (requête asynchrone, vous l'aviez compris).

Quand le délai s'est écoulé (toutes les demi-secondes dans l'exemple), on reçoit un signal et la demande est interrompue, puisque le travail du timer.device est fini. Ce qui signifie que pour récidiver, il faudra envoyer une nouvelle demande par la même méthode. Ceci sera fait après avoir changé l'image si l'on veut faire une animation, ou après avoir affiché le nombre de secondes dans le cas de l'exemple.

Note : le délai peut être précisé à la microseconde près, mais il ne doit en aucun cas être inférieur à 3 microsecondes sous peine de l'Amiga... rou !

Quand on arrête ce cycle infernal (parce que la belle-mère est arrivée ?), il faut prendre soin de vérifier que le timer.device a fini son travail avec AbortIO() ("abandonne la demande"), puis waitIO() ("attends que tout soit OK").

Remarque : notre fenêtre comporte ici le drapeau "RMBTRAP", qui évite la gestion des menus déroulants, car sinon, tant que le bouton droit de la souris est maintenu enfoncé, le compteur de secondes est gelé.

Pour en savoir plus

Le timer.device mesure le temps de deux façons, soit avec l'interruption de balayage écran (UNIT_VBLANK), soit à l'aide d'un CIA 8520 (UNIT_MICROHZ).

Le chronomètre VBLANK est assez fiable pour de longues périodes (20 secondes par exemple) et sa précision est de l'ordre de 17 millisecondes (17 000 microsecondes), ce qui le rend peu efficace sur de courtes périodes.

Le chronomètre MICROHZ, quant à lui, est d'une grande précision sur de courtes périodes, mais moins fiable sur de grandes périodes, surtout si plusieurs tâches tournent en même temps.

Dans les deux cas, le délai est compté à partir de l'instant où la demande est reçue par le périphérique logique, le nombre de microsecondes devant être inférieur à 1 million (1 million de microsecondes = 1 seconde !).

/***************************************************
*   fenêtre Intuition et timer.device              *
*        par D. GENOT                              *
*   opt : -L                                       *
***************************************************/

#include <exec/types.h>
#include <exec/memory.h>
#include <intuition/intuition.h>
#include <graphics/text.h>
#include <graphics/gfxbase.h>
#include <graphics/rastport.h>
#include <devices/timer.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

/**********************
*     define          *
**********************/
#define WLARG 640
#define WHAUT 240

#define RP Window->RPort

/*********************
*   structures       *
*********************/
struct IntuitionBase *IntuitionBase=NULL;
struct GfxBase *GfxBase=NULL;
struct Screen *Screen=NULL;
struct Window *Window=NULL;
struct IntuiMessage *msg;

struct timerequest *tr=NULL;  /* timer Request   */
struct timeval *time;   /* délai d'attente */
struct MsgPort *tport;  /* pour signaux    */

LONG T_Dev;             /* device ouvert ? */

extern struct Window *OpenWindow();  
extern struct Screen *OpenScreen();

/********************
*  declarations     *
********************/
void openall();
void cleanexit();
void PrintIT(struct IntuiText *,int,int);

void attente();

/*********************************
* variables : nombres et chaines *
*********************************/

ULONG classe;       /* IDCMP */
USHORT code;        /* keys  */

char s[201];       /* pour 'storage' des messages */

/*********************************
*  structures                    *
*********************************/

struct TextAttr Font=
	{
	"topaz.font",8,	/* nom + hauteur */
	0,0				/* style + flags */
	};

struct NewScreen NewScreen=    /* def. et init. immediate */
  	{
	0,0,           /*  sommet gche , haut */
	640,256,       /* largeur et hauteur */
	3,             /* nbre de bitplanes  */
	0,1,           /*    couleurs        */ 
	HIRES,         /*      mode          */
	CUSTOMSCREEN,  /*      type          */
	&Font,          /*  fontes perso      */
	"   @ D. G. SoftWare 1991 , Programmation d'une ANIM...  ",/* titre */
	NULL,          /*   gadgets          */
	NULL          /*     bitmap         */
	}; 

struct NewWindow NewWindow=
{
0,				/* LeftEdge */
12,				/* TopEdge  */
WLARG,			/* Width    */
WHAUT,			/* Height   */
4,6,				/* DetailPen,BlockPen */
CLOSEWINDOW | VANILLAKEY ,/* IDCMPFflags */
SMART_REFRESH | ACTIVATE |
 NOCAREREFRESH | WINDOWCLOSE | BORDERLESS |
 SIZEBRIGHT |
 RMBTRAP ,		/* flags    */
 
 /******** RMBTRAP est nécessaire pour timer.device qui bloque 
           sinon à l'appui de R Mouse ...       *************/
           
NULL,			/* first gadget       */
NULL,			/* check mark         */
NULL,			 /* titre */
NULL,			  /* pteur ecran perso ouvert */
NULL,			/* bitmap   */
80,25,			/* MinWidth , MinHeight */
640,256,			/* MaxWidth , MaxHeight */
CUSTOMSCREEN		/* type */
};

struct IntuiText bleu=
{6,0,JAM2,0,0,0,&s[0],NULL};		/* en bleu pale */

struct IntuiText rouge=
{3,0,JAM2,0,0,0,&s[0],NULL};		/* en rouge */

USHORT couleurs[8]=
{0x334,0xfff,0x000,0xf80,0x00f,0x0f0,0x0ff,0xf5f};
/* gris,blanc,noir,orange,bleu f,vert,bleu c,rose */
/*  0  ,  1  ,  2  ,  3  ,  4   ,  5 ,  6   ,  7  */

/******* routines ***********************/

void PrintIT(texte,ab,or)
struct IntuiText *texte;
int ab,or;
{
	PrintIText(RP,texte,(SHORT)ab,(SHORT)or);
}

void cleanexit()
{
if( !T_Dev )
   CloseDevice((struct IORequest *)tr);
if( tr )
   DeleteExtIO(tr);
if( tport )
   DeletePort(tport);
if( time )
   FreeMem(time,sizeof(struct timeval));
if(Window)
	CloseWindow(Window);
if(Screen)
	CloseScreen(Screen);
if(IntuitionBase)
	CloseLibrary((struct Library *)IntuitionBase);
if(GfxBase)
	CloseLibrary((struct Library *)GfxBase);
exit(0);
}

void openall()
{
   
 IntuitionBase=(struct IntuitionBase *)
	OpenLibrary("intuition.library",0);
 if (IntuitionBase==NULL)
 	exit(0);

 if((GfxBase=(struct GfxBase *)
	OpenLibrary("graphics.library",0))==NULL)
	cleanexit();

 if ((Screen=OpenScreen(&NewScreen))==NULL)
 	cleanexit();

 NewWindow.Screen=Screen;
 if ((Window=OpenWindow(&NewWindow))==NULL)          
	cleanexit();               /*  si raté !! */

 LoadRGB4(&Screen->ViewPort,couleurs,8);

 time=(struct timeval *)AllocMem(sizeof(struct timeval),MEMF_PUBLIC | MEMF_CLEAR);
 if( !time )
   cleanexit();
 time->tv_secs =0;
 time->tv_micro=500000; /* 0,5 seconde */

 tport=(struct MsgPort *)CreatePort(0,0);
 if( !tport )
 {
   T_Dev=NULL;
   cleanexit();
 }
   
 tr=(struct timerequest *)CreateExtIO(tport,sizeof(struct timerequest));
 if( !tr )
 {
   T_Dev=NULL;
   cleanexit();
 } 
 tr->tr_time=*time;

 T_Dev=OpenDevice(TIMERNAME,UNIT_MICROHZ,(struct IORequest *)tr,0L);
 if( T_Dev )    /*   0   si OK  */
  cleanexit();
   
}

void attente()
{

   BOOL fini=FALSE;
   ULONG Wmask=1L << Window->UserPort->mp_SigBit;
   ULONG Tmask=1L << tport->mp_SigBit;
   ULONG Signal_recu;
   ULONG sec=0;
   ULONG dix=0; /* secondes et dixièmes */

   time->tv_secs =0;
   time->tv_micro=500000; /* 0,5 seconde */
   tr->tr_time=*time;
   tr->tr_node.io_Command=TR_ADDREQUEST;
   SendIO( (struct IORequest *)tr );   /* 1er envoi */
         
   do
	{
	   Signal_recu=Wait( Wmask | Tmask );
      
      if( Signal_recu & Wmask ) /* dans FENETRE */
      {
	     while(msg=(struct IntuiMessage *)GetMsg(Window->UserPort))
        { 
	       classe=msg->Class;                      
          code=msg->Code;
	      
          ReplyMsg((struct Message *)msg);
         
          switch(classe)
          {
            case VANILLAKEY:
               switch(code)
               {
                  case 'Q':
                  case 'q':
                    fini=TRUE;
                    break;
                  default:
                    sprintf(s,"dernière touche : '%c'",code);
                    PrintIT(&bleu,50,150);
                    break;
               }
               break;
            case CLOSEWINDOW:
               fini=TRUE;
               break;
            default:
               break;
          }
        } /* end while( msg ) */
      } /* end if( Wmask ) */

      if( Signal_recu & Tmask ) /* DELAI ecoulé */
      {
         dix+=5;
         if( dix==10 )
         {
            dix=0;
            sec++;
         }
         sprintf(s,"secondes : %3d,%d",sec,dix);
         PrintIT(&rouge,50,50);

         time->tv_secs =0;
         time->tv_micro=500000; /* 0,5 seconde */
         tr->tr_time=*time;
         tr->tr_node.io_Command=TR_ADDREQUEST;
         SendIO( (struct IORequest *)tr );   /* remettez-nous ça ! ! */
      } /* end if( Tmask ) */

	}while( !fini );	   
   
   if( !CheckIO(tr) )
      AbortIO(tr);   /* stoppe demande en cours */
   WaitIO(tr);       /* attend t_request OK     */
}

/***********  MAIN  ********************/

void main()
{
   openall();
   
   attente();
   
   cleanexit();
}


[Retour en haut] / [Retour aux articles]