Précédent   Forum du club des développeurs et IT Pro > Autres langages > Autres langages > Ada
Ada Forum d'entraide sur la programmation en langage Ada
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse
 
Outils de la discussion
Publicité
'
Vieux 11/07/2012, 16h23   #1
jovalise
Membre éclairé
 
Inscription : juin 2006
Messages : 767
Détails du profil
Informations personnelles :
Âge : 43

Informations forums :
Inscription : juin 2006
Messages : 767
Points : 328
Points : 328
Par défaut Binding de la bibliothèque portmidi

Bonjour,

Je n'ai pas beaucoup cherché, un temps pour tout, alors, j'avais écrit un bout de code pour interfacer la bibliothèque "portmidi" qui permet d'exploiter les périphérique MIDI.

Je rencontre quelque difficultés et j'ai une question pour le moment : est-il possible de transposer une macro telle que :
Code C :
1
2
3
4
5
 
#define Pm_Message(status, data1, data2) \
         ((((data2) << 16) & 0xFF0000) | \
          (((data1) << 8) & 0xFF00) | \
          ((status) & 0xFF))

Mes difficulté sont liée à la déclaration du type PmMessage et PmEvent :
Code C :
1
2
3
4
5
6
7
 
typedef int32_t PmMessage; /**< see PmEvent */
 
typedef struct {
    PmMessage      message;
    PmTimestamp    timestamp;
} PmEvent;
Comment traduire ceci ?

Etant donné que Je voudrais si c'est possible, me passer de corps de paquetage.

Pour vous donner de quoi corriger, je vous poste mon code actuelle (l'ancien en voie de normalisation) :

Porttime : binding Ada
Code Ada :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
with Interfaces.C;
with System;

package Porttime is

   type PtError is(PtNoError,
                   PtHostError,
                   ptAlreadyStarted,
                   ptAlreadyStopped,
                   PtInsufficientMemory);


   function Pt_Start(Resolution : Integer;
                     PtCallback : System.Address;
                     UserData : System.address) return PtError;
   pragma Import (C, Pt_Start, "Pt_Start");

   function Pt_Time return Interfaces.C.Long;
   pragma Import (C, Pt_Time, "Pt_Time");

   type Time_Access is access function return Interfaces.C.Long;
   pragma Convention(C, Time_Access);
end Porttime;


Portmidi binding Ada
Code Ada :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
with Porttime;
with System;
with Interfaces.C;
use Interfaces.C;
with System.Address_To_Access_Conversions;
package Portmidi is
   
      
   type PmError is (pmNoErro,
                    PmHostError,
                    pmInvalidDeviceId,
                    pmInsufficientMemory,
                    pmBufferTooSmall,
                    pmBufferOverflow,
                    pmBadPtr,
                    pmBadData,
                    pmInternalError,
                    PmBufferMaxSize);
   
   function Pm_Initialize return PmError;
   pragma Import (C, Pm_Initialize, "Pm_Initialize");

   function Pm_Terminate return PmError;
   pragma Import (C, Pm_Terminate, "Pm_Terminate");
   
   function Pm_HasHostError( PortMidiStream : System.address) return Interfaces.C.Int;
   pragma Import (C, Pm_HasHostError, "Pm_HasHostError");
   
   
   subtype T_ErrorText is Interfaces.C.Char_Array(0..64);   
   function Pm_GetErrorText( Errnum : PmError  ) return T_ErrorText;
   Pragma Import (C, Pm_GetErrorText, "Pm_GetErrorText");
   package ErrorText_Conversion is new System.Address_To_Access_Conversions
     (T_ErrorText);
   use ErrorText_Conversion;
   
   -- void Pm_GetHostErrorText(char * msg, unsigned int len);
      
   type DeviceInfo is
      record
         StructVersion : Integer;
         Interf : System.address;
         Name : System.Address;
         Input : Integer;
         Output : Integer;
         Opened : integer;
      end record;
   
   
   function Pm_CountDevices return Integer;
   pragma Import (C, Pm_CountDevices, "Pm_CountDevices");
         
   function Pm_GetDefaultInputDeviceID return Interfaces.C.int;
   pragma Import (C, Pm_GetDefaultInputDeviceID, "Pm_GetDefaultInputDeviceID");

   function Pm_GetDefaultOutputDeviceID return Interfaces.C.Int;
   pragma Import (C, Pm_GetDefaultOutputDeviceID, "Pm_GetDefaultOutputDeviceID");
   
   function Pm_GetDeviceInfo(PmDeviceID : Integer) return System.Address;
   pragma Import (C, Pm_GetDeviceInfo, "Pm_GetDeviceInfo");
   
   package DeviceInfo_Conversion is new System.Address_To_Access_Conversions(DeviceInfo);
   use DeviceInfo_Conversion;

function Pm_OpenInput(PortMidiStream : System.address;
                         PmDeviceID : Integer;
                         InputDriverInfo : Integer;
                         BufferSize : Long_Integer;
                         PmTimeProcPtr : Porttime.Time_access;
                         time_info : System.address) return PmError;
   pragma Import (C, Pm_OpenInput, "Pm_OpenInput");


   function Pm_OpenOutput(PortMidiStream : System.Address;
                          OutputDevice : Integer;
                          outputDriverInfo : System.address;
                          BufferSize : Long_Integer;
                          Time_Proc : Porttime.Time_access;
                          Time_Info : System.address;
                          latency : Long_integer) return PmError;
   pragma Import (C, Pm_OpenOutput, "Pm_OpenOutput");
   
   
   function Pm_SetFilter(PortMidiStream : System.Address;
                         filters : Long_Integer) return PmError;
   pragma Import (C, Pm_SetFilter, "Pm_SetFilter");

   function Pm_SetChannelMask(PortMidiStream : System.Address;
                              Mask : integer) return PmError;
   pragma Import (C, Pm_SetChannelMask, "Pm_SetChannelMask");

   function Pm_Abort( PortMidiStream : System.Address) return PmError;
   pragma Import (C, Pm_Abort, "Pm_Abort");

   function Pm_Close( PortMidiStream : System.Address) return PmError;
   pragma Import (C, Pm_Close, "Pm_Close");

end Portmidi;

Je n'ai jamais testé Pm_OpenInput ni Pm_Openoutput. J'avais fais des function perso.

S'il vous plaît ? Merci pour vos réponses.
__________________
Mon développement
jovalise est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 13/07/2012, 15h42   #2
jovalise
Membre éclairé
 
Inscription : juin 2006
Messages : 767
Détails du profil
Informations personnelles :
Âge : 43

Informations forums :
Inscription : juin 2006
Messages : 767
Points : 328
Points : 328
Pour le moment j'ai fait un corps de bibliothèque avec Pm_Message, Status, Data1, Data2 et Channel.

Voici à quoi ressemble Pm_message qui utilise la fonction Shift_Left de interfaces.

Code ada :
1
2
3
4
5
6
7
8
9
10
11
12
13
 function Pm_Message(Status, Data1, Data2 : Interfaces.C.Long) return Interfaces.C.Long is

      Message : Unsigned_32 := 0;
      Low     : Unsigned_32 := Unsigned_32(Data2);
      Middle  : Unsigned_32 := Unsigned_32(Data1);
      High    : Unsigned_32 := Unsigned_32(status);
   begin
      Message := ((Shift_Left(Low, 16) and 16#FF0000#) or
                     (Shift_Left(middle, 8) and 16#FF00#) or
                     (high and 16#FF#));

      return Interfaces.C.Long(Message);
   end Pm_Message;


J'ai regarder aussi les fonction Pm_Open, je vous reposte la spécification...
Faut que je test la fonction Read aussi.
(j'ai peut-être pas terminé encore, mais j'ai une excuse)

Code ada :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
with Porttime;
with System;
with Interfaces.C;
use Interfaces.C;
with System.Address_To_Access_Conversions;
package Portmidi is


   type PmError is (pmNoErro,
                    PmHostError,
                    pmInvalidDeviceId,
                    pmInsufficientMemory,
                    pmBufferTooSmall,
                    pmBufferOverflow,
                    pmBadPtr,
                    pmBadData,
                    pmInternalError,
                    PmBufferMaxSize);

   function Pm_Initialize return PmError;
   pragma Import (C, Pm_Initialize, "Pm_Initialize");

   function Pm_Terminate return PmError;
   pragma Import (C, Pm_Terminate, "Pm_Terminate");

   function Pm_HasHostError( PortMidiStream : System.address) return Interfaces.C.Int;
   pragma Import (C, Pm_HasHostError, "Pm_HasHostError");


   subtype T_ErrorText is Interfaces.C.Char_Array(0..256);
   function Pm_GetErrorText( Errnum : PmError  ) return T_ErrorText;
   pragma Import (C, Pm_GetErrorText, "Pm_GetErrorText");
   package ErrorText_Conversion is new System.Address_To_Access_Conversions
     (T_ErrorText);
   use ErrorText_Conversion;


   type DeviceInfo is
      record
         StructVersion : Integer;
         Interf : System.address;
         Name : System.Address;
         Input : Integer;
         Output : Integer;
         Opened : integer;
      end record;


   function Pm_CountDevices return Integer;
   pragma Import (C, Pm_CountDevices, "Pm_CountDevices");

   function Pm_GetDefaultInputDeviceID return Interfaces.C.int;
   pragma Import (C, Pm_GetDefaultInputDeviceID, "Pm_GetDefaultInputDeviceID");

   function Pm_GetDefaultOutputDeviceID return Interfaces.C.Int;
   pragma Import (C, Pm_GetDefaultOutputDeviceID, "Pm_GetDefaultOutputDeviceID");

   function Pm_GetDeviceInfo(PmDeviceID : Integer) return System.Address;
   pragma Import (C, Pm_GetDeviceInfo, "Pm_GetDeviceInfo");

   package DeviceInfo_Conversion is new System.Address_To_Access_Conversions(DeviceInfo);
   use DeviceInfo_Conversion;

 function Pm_Poll( PortMidiStream : System.Address) return PmError;
   pragma Import (C, Pm_Poll, "Pm_Poll");



   function Pm_Message(Status, Data1, Data2 : Interfaces.C.Long) return Interfaces.C.Long;
   function Status(Message : Interfaces.C.long) return Interfaces.C.Long;
   function data1(Message : Interfaces.C.long) return Interfaces.C.Long;
   function Channel(Message : Interfaces.C.Long) return Interfaces.C.Long;
   function data2(Message : Interfaces.C.long) return Interfaces.C.Long;



   type PmEvent is
      record
         Message : Interfaces.C.Long := 0;
         PmTimestamp : Interfaces.C.Long := 0;
      end record;


   function Pm_Write( PortMidiStream : System.address;
                      Pm_Event : PmEvent;
                      length : Interfaces.C.Long) return PmError ;
   pragma Import (C, Pm_Write, "Pm_Write");


   function Pm_WriteShort( PortMidiStream : System.address;
                           PmTimestamp : Interfaces.C.long;
                           Msg : Interfaces.C.long) return PmError;
   pragma Import (C, Pm_WriteShort, "Pm_WriteShort");

   function Pm_WriteSysEx( PortMidiStream : System.Address;
                           PmTimestamp : Float;
                           Msg : integer) return PmError;
   pragma Import (C, Pm_WriteSysEx, "Pm_WriteSysEx");



end Portmidi;

Je vous laisse donc le plaisir d'implémenter les fonctions manquantes.
__________________
Mon développement
jovalise est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 24/07/2012, 18h13   #3
jovalise
Membre éclairé
 
Inscription : juin 2006
Messages : 767
Détails du profil
Informations personnelles :
Âge : 43

Informations forums :
Inscription : juin 2006
Messages : 767
Points : 328
Points : 328
Par défaut Import de Pm_Read

Evidemment, j'avais oublié l'import de Pm_Read, et qui malheureusement me pose problème.

Voici mon import :
Code ada :
1
2
3
4
5
Function Pm_Read(PortMidiStream : System.Address;		    
		    Pm_Event : access PmEvent;
		    length : Interfaces.C.Long) return PmError ;
pragma Import (C, Pm_Read, "Pm_Read");

Mais d'abord, il semble que la fonction Pm_Read ne soit pas bloquante ce qui me pose un premier problème, ça tourne dans le vide. ; Mais j'obtiens une erreur HostError dès la réception de message.

Mon appel est le suivant :
Code ada :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
task body Input is

	 Event : access PmEvent := new PmEvent;
      begin
	 loop	
	    declare	       
	       Pm_Error : PmError;
	    begin
	       
	         Text_Io.Put_Line("message :" & Long'Image(Event.Message));
	         Pm_Error := Pm_Read(Address.all, 
	         			   Event,
                                           1);	       
	       
	         case Pm_Error is
	         	  when PmNoError =>
		     accept Send(Message : out Long) do
			Message := Event.Message;			
		     end Send;
	         	  when others =>
	         	         Text_Io.Put(PmError'Image(Pm_Error));
	         end case;
	    end;
	 end loop;
	 
      end Input;


Alors, j' ai une implémentation un truc que j'ai tiré d'un code C dont je faisais l'import avant.
Code C :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
 
#include "unistd.h"
#include "portmidi.h"
#include "porttime.h"
#include "stdio.h"
 
#define INPUT_BUFFER_SIZE 100
#define OUTPUT_BUFFER_SIZE 0
#define DRIVER_INFO NULL
#define TIME_PROC ((long (*)(void *)) Pt_Time)
#define TIME_INFO NULL
#define TIME_START Pt_Start(1, 0, 0) /* timer started w/millisecond accuracy */
 
 
 
long Read_Handler(PortMidiStream *midi) {
  PmError status, length;
  PmEvent buffer[1];
  int i = 0;
  int num = 1;
    /* It is recommended to start timer before Midi; otherwise, PortMidi may
       start the timer with its (default) parameters
     */
  /*TIME_START;*/
 
  /* open input device
    Pm_OpenInput(, 
                 i,
                 DRIVER_INFO, 
                 INPUT_BUFFER_SIZE, 
                 TIME_PROC, 
                 TIME_INFO);*/
 
    /*printf("Midi Input opened. Reading %d Midi messages...\n",num);*/
    Pm_SetFilter(midi, PM_FILT_ACTIVE | PM_FILT_CLOCK);
    /* empty the buffer after setting filter, just in case anything
       got through */
    while (Pm_Poll(midi)) {
        Pm_Read(midi, buffer, 1);
    }
    /* now start paying attention to messages */
    i = 0; /* count messages as they arrive */
    buffer[0].message = 0;
    while (i < num) {
        status = Pm_Poll(midi);
        if (status == TRUE) {
	  length = Pm_Read(midi,buffer, 1);
	  if (length > 0)
	    i++;            	            	      
	}        
	usleep(50);
    }
 
    /* close device (this not explicitly needed in most implementations) */
    /*printf("ready to close...");*/
 
    /*Pm_Close(midi);*/
    /*printf("done closing...");*/
    return buffer[0].message;
}
Dans ce code je lie et renvoie 1 seul message normalement, de mémoire.


Mais je suis paumé, parce que ça n'a rien à voir avec un simple appel à Pm_Read.


A votre avis, ou est mon erreur ?
Merci
__________________
Mon développement
jovalise est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 29/11/2012, 04h22   #4
jovalise
Membre éclairé
 
Inscription : juin 2006
Messages : 767
Détails du profil
Informations personnelles :
Âge : 43

Informations forums :
Inscription : juin 2006
Messages : 767
Points : 328
Points : 328
Par défaut Traduction de la fonction C Read_Handler avec Ada

Bonjour, j'ai donc transposé la fonction Read_Handler, mais elle me pose encore problème.
A vrai dire je nais pas testé tous les état de sortie de Pm_Read.
Donc, tout ce que je sais, c'est que parfois elle plante.

Voici le code.

Code ada :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
procedure Read       (Device : in     Device_Type; Message : out C.Long) is
      Pm_Error : PmError := PmNoError;
      Pm_Event : PmEvent_Access := new PmEvent;
      
   begin     
      if not Device.Initialized then
         raise Not_Initialized;
      end if;
      if Device.Mode /= MIDI_In then
         raise MODE_Error;
      end if;
      Message := 0;
      loop
	 
	 Pm_Error := Pm_Poll(Device.Addr.all);      	 
	 if Pm_Error /= PmNoError then
	    Pm_Error := Pm_Read(Device.Addr.All, Pm_Event, 1);            	    		  	       		  	 
	    
	 else
	    exit;
	 end if;
      end loop;	   
      loop
	 Pm_Error := Pm_Poll(Device.Addr.all);                  
	 if Pm_Error /= Pmnoerror  then	    	    	    
	    Pm_Error := Pm_Read(Device.Addr.All, Pm_Event, 1);           
	    if Pm_Error /= Pmnoerror then
	       Message := Pm_Event.Message;	    	    	       	 
	       return;
	    end if;	 
	 end if;      
	 delay 0.005;
      end loop;
   end Read;
Alors, je sais combien ça fais 50 micro seconde, mais ça fonctionne un poil mieux avec 500.

Le code est relativement bizarre sémantiquemant parlant, mais c'est le reflet du code C simplement.

J'appelle ce code en boucle pour lire un message MIDI sur un périphérique MIDI.
__________________
Mon développement
jovalise est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse
Outils de la discussion

Navigation rapide


Fuseau horaire GMT +2. Il est actuellement 23h52.


 
 
 
 
Partenaires

Hébergement Web