+ Répondre à la discussion
Affichage des résultats 1 à 5 sur 5
  1. #1
    Membre éprouvé
    Homme Profil pro
    Inscrit en
    juin 2006
    Messages
    933
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44

    Informations forums :
    Inscription : juin 2006
    Messages : 933
    Points : 413
    Points
    413
    Billets dans le blog
    1

    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.

  2. #2
    Membre éprouvé
    Homme Profil pro
    Inscrit en
    juin 2006
    Messages
    933
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44

    Informations forums :
    Inscription : juin 2006
    Messages : 933
    Points : 413
    Points
    413
    Billets dans le blog
    1

    Par défaut

    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.

  3. #3
    Membre éprouvé
    Homme Profil pro
    Inscrit en
    juin 2006
    Messages
    933
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44

    Informations forums :
    Inscription : juin 2006
    Messages : 933
    Points : 413
    Points
    413
    Billets dans le blog
    1

    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

  4. #4
    Membre éprouvé
    Homme Profil pro
    Inscrit en
    juin 2006
    Messages
    933
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44

    Informations forums :
    Inscription : juin 2006
    Messages : 933
    Points : 413
    Points
    413
    Billets dans le blog
    1

    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.

  5. #5
    Membre éprouvé
    Homme Profil pro
    Inscrit en
    juin 2006
    Messages
    933
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44

    Informations forums :
    Inscription : juin 2006
    Messages : 933
    Points : 413
    Points
    413
    Billets dans le blog
    1

    Par défaut

    Bonjour,

    Je viens ici, parce que je rencontre un problème avec mon binding Ada de portmidi.

    En effet, il m'est actuellement impossible d'utilisé plusieurs instrument simultanément.

    J'obtiens depuis Ada un message d'erreur :
    PortMidi found host error...
    Opération non permise
    type ENTER...PortMidi found host error...
    Opération non permise
    type ENTER...
    Vous trouverez les dernières sources qui n'ont guère changé, à 88.189.147.62/musicals/

    Je sèche complètement sur ce problème depuis 2 semaines.

    Si vous avec un tuyau, Merci.

Liens sociaux

Règles de messages

  • Vous ne pouvez pas créer de nouvelles discussions
  • Vous ne pouvez pas envoyer des réponses
  • Vous ne pouvez pas envoyer des pièces jointes
  • Vous ne pouvez pas modifier vos messages
  •