Developpez.com - Delphi
X

Choisissez d'abord la catégorieensuite la rubrique :


La vidéo sous Linux

Date de publication : 01/01/2001 , Date de mise à jour : 01/11/2005

Par Paul Toth (Site)
 

La vidéo sous Linux.



J'ai réalisé une version Linux du PhantomCyberspace de Jacco Bikker

Sa démo (qui ne date pas d'hier) était réalisée sous DOS en Borland Pascal 7. Pour la version Windows, j'ai utilisé des DIB (Device Independant Bitmaps), mais sous Linux je voulais faire mieux que DirectX, je voulais utiliser directement la carte VGA !

Il existe en standard (?) sous Linux la svgalib qui propose le support du mode VGA 320x200 (utilisé par Jacco), mais également différents modes SVGA ou VESA...comme cette lib est sous GPL j'ai pu étudier les sources :)

Je vous propose donc une étude de mon unité VGA qui gère le mode 320x200 sous Linux.

Tout d'abord, nous allons voir comment allouer un nouvel écran (comme xinit le fait pour XWindow).
 ...
 Implementation

 Uses Libc; // nous avons besoin des API Linux

 const
  VT_OPENQRY=$5600; // $56 = ord('V')

 procedure TForm1Button1Click(Sender: TObject);
 var
  f:integer;
  i:integer;
  s:string;
  m:string;
 begin
// ouverture de la console pour lui faire une requête
  f:=open('/dev/console',O_WRONLY);
// demande d'un numéro de tty disponible
  ioctl(f,VT_OPENQRY,@i);
  __close(f);
// déterminer le nom de la console disponible
  s:='/dev/tty'+IntToStr(i);
// l'ouvrir
  f:=open(pchar(s),O_RDWR);
// envoyer le message de retour...
  m:='Vous êtes sur '+s+#10'Appuyez sur Alt+F7 pour revenir à XWindow';
  __write(f,m[1],length(m));
  __close(f);
// ... avant de proposer de basculer vers la console
 ShowMessage('pressez ctrl+atl+F'+intToStr(i)+' pour afficher '+s);
 end;
NB : pour faire plus court, les exemples donnés ici ne font aucun test de validiter, dans un cas réel il faudra vérifier que chaque API retourne une valeur valide...moi je travaille sous root, si vous avez un profil utilisateur plus commun, ce programme risque de ne pas fonctionner.

On peut ajouter l'activation automatique de la console dès son ouverture :
Const
  VT_ACTIVATE=$5606; // on trouve toutes ces constantes dans 'sys/vt.h'
 begin
  ...
   __write(f,m[1],length(m));
   ioctl(f,VT_ACTIVATE,pointer(i));
   __close(f);
  ...
 end;
Le problème maintenant, c'est de déterminer si la console possède ou non le focus (pour reprendre un terme windows :). Linux utilise un système de signal assez proche des interruptions du DOS pour notifier le programme d'un évènement. Voici une fonction à utiliser pour contrôler le "switching" d'une console :
const
 VT_GETMODE=$5601;
 VT_SETMODE=$5602;
 VT_PROCESS=1;
 VT_RELDISP=$5605;
 VT_ACKACQ =2;
  // svgalib suppose that SIGUSR1/2 are free...
  // Kylix probably use them...the focus never occurs under Kylix
  // SIGUNUSED+1 seems to be used under KDE...switching doesn't work
  // SIGNUNSED+2,+3 work under Kylix and KDE (Mandrake 7.0)
 OnLeave=SIGUNUSED+2;
 OnEnter=SIGUNUSED+3;
 
type
 vt_mode=packed record
  mode  :byte; // vt mode
  waitv :char; // if set, hang on writes if not active
  relsig:word; // signal to raise on release req
  acqsig:word; // signal to raise on acquisition
  frsig :word; // unused (set to 0)
 end;

var
 tty:integer;
 focus:boolean=false;

procedure error(msg:string);
 begin
  writeln(msg);
  halt;
 end;

// procédure appelée à chaque changement d'écran
procedure OnSwitch(signal:integer); cdecl;
 begin
  case signal of
   OnEnter: begin
    ioctl(vc, VT_RELDISP, pointer(VT_ACKACQ)); // got focus
    focus:=true;
   end;
   OnLeave: begin
    ioctl(vc, VT_RELDISP, pointer(1)); // or "nil" if can't leave
    focus:=false;
   end;
  end;
 end;

// procédure appelée en cas d'erreur
procedure OnBreak(signal:integer); cdecl;
 begin
  case signal of
   SIGINT :error('User break');
   SIGHUP :error('console hangup ?!');
   SIGQUIT:error('Quit received');
   SIGTERM:error('Termination ?');
   SIGSEGV:error('There''s a bad pointer somewhere !');
  else
   error('program aborted cause of signal #'+IntToStr(signal));
  end;
 end;

procedure ControlSwitching(atty:integer);
 var
  mode:vt_mode;
 begin
  tty:=atty;
  ioctl(tty,VT_GETMODE, @mode);

  mode.mode  :=VT_PROCESS; // prise en charge du switching
  mode.acqsig:=OnEnter;    // numéro de signal d'activation
  mode.relsig:=OnLeave;    // numéro de signal de désactivation
// mise en place des gestionnaires de signal
  signal(OnEnter,OnSwitch);
  signal(OnLeave,OnSwitch);
// on en profite pour gérer les erreurs les plus courantes
  signal(SIGINT ,OnBreak);
  signal(SIGHUP ,OnBreak);
  signal(SIGQUIT,OnBreak);
  signal(SIGTERM,OnBreak);
  signal(SIGSEGV,OnBreak);

  ioctl(tty,VT_SETMODE,@mode); // mettre en place tout le système
 end;
Pour utiliser cette exemple, ne fermez pas la console sur Button1Click, activez le contrôle du switching, et ajouter une trace visuel des changements...
procedure OnSwitch(signal:integer); cdecl;
 begin
  case signal of
   OnEnter: begin
    ioctl(tty, VT_RELDISP, pointer(VT_ACKACQ)); // got focus
    focus:=true;
    Form1.Caption:=Form1.Caption+'0';
   end;
   OnLeave: begin
    ioctl(tty, VT_RELDISP, pointer(1)); // or "nil" if can't leave
    focus:=false;
    Form1.Caption:=Form1.Caption+'1';
   end;
  end;
 end;
...
  __write(f,m[1],length(m));
  ioctl(f,VT_ACTIVATE,pointer(i));
//  __close(f);
 ControlSwitching(f);
end;
Voir la suite : le mode graphique



Valid XHTML 1.1!Valid CSS!

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2005 Paul Toth. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Responsables bénévoles de la rubrique Delphi : Gilles Vasseur - Alcatîz -