[C/Ada] Traduction de C avec Ada de la bibliothèque portmidi.

Traduction de C avec Ada de la bibliothèque portmidi. [C/Ada] - Ada - Programmation

Marsh Posté le 04-10-2012 à 07:58:07    

Bonjour,  
 
j'ai fait un binding de la bibliothèque portmidi pour Ada mais je me heurte à la fonction Pm_Read.
Pm_Read, est une fonction non bloquante, ce qui me pose problème à la lecture des évènements.
En effet, je ne reçois jamais le message, et je reçois un PmHostError.
 
 
J'avais néanmoins ce code C (je ne sais plus d'où je le tire)  que j'essaie de traduire.

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


 
Voici mon bout de code Ada :
 

Code :
  1. task type Input_Driver_Type(Addr : Address_Access) is
  2.      entry Send(Message : out C.Long);
  3.   end Input_Driver_Type;
  4.      
  5.   task body Input_Driver_Type is
  6.      
  7.      Pm_Error : PmError;
  8.   begin
  9.      Pm_Error := Pm_SetFilter(Addr.all, PM_FILT_ACTIVE or PM_FILT_CLOCK);
  10.      loop    
  11.     
  12.     
  13.      declare          
  14.         
  15.         Event : access PmEvent := new PmEvent;
  16.      begin                        
  17.         loop
  18.            Pm_Error := Pm_Poll(Addr.all);
  19.            case Pm_Error is
  20.           when PmNoError =>            
  21.              exit;
  22.             
  23.           when others =>
  24.              Pm_Error := Pm_Read(Addr.all, Event, 1);            
  25.  
  26.            end case;
  27.         end loop;
  28.         Pm_Error := Pm_Poll(Addr.all);
  29.         case Pm_Error is
  30.            when PmNoError =>
  31.           
  32.           Text_Io.Put_Line("Reading message :" & C.Long'Image(Event.Message));
  33.           Pm_Error := Pm_Read(Addr.all,
  34.                       Event,
  35.                       1);                     
  36.           case Pm_Error is
  37.              when PmNoError =>
  38.             accept Send(Message : out C.Long) do
  39.                Message := Event.Message;            
  40.             end Send;
  41.              when others =>
  42.             Text_Io.Put(PmError'Image(Pm_Error));
  43.           end case;
  44.            when others =>
  45.           null;
  46.         end case;      
  47.      end;
  48.      end loop;
  49.      
  50.   end Input_Driver_Type;


 
Code qui ne transmet jamais rien par l'entrée "Send".
 
 
Voici mon binding de portmidi avec Ada.

Code :
  1. - Description : Ada binding to C library "portmidi".
  2. -----------------------------------------------------
  3.  
  4. with Porttime;
  5. with System;
  6. with Interfaces.C;
  7. use Interfaces;
  8. with System.Address_To_Access_Conversions;
  9. package Portmidi is
  10.  
  11.      
  12.   type PmError is (pmNoError,
  13.                    PmHostError,
  14.                    pmInvalidDeviceId,
  15.                    pmInsufficientMemory,
  16.                    pmBufferTooSmall,
  17.                    pmBufferOverflow,
  18.                    pmBadPtr,
  19.                    pmBadData,
  20.                    pmInternalError,
  21.                    PmBufferMaxSize);
  22.  
  23.   function Pm_Initialize return PmError;
  24.   pragma Import (C, Pm_Initialize, "Pm_Initialize" );
  25.  
  26.   function Pm_Terminate return PmError;
  27.   pragma Import (C, Pm_Terminate, "Pm_Terminate" );
  28.  
  29.   function Pm_HasHostError( PortMidiStream : System.address) return Interfaces.C.Int;
  30.   pragma Import (C, Pm_HasHostError, "Pm_HasHostError" );
  31.  
  32.  
  33.   subtype T_ErrorText is Interfaces.C.Char_Array(0..256);  
  34.   function Pm_GetErrorText( Errnum : PmError  ) return T_ErrorText;
  35.   pragma Import (C, Pm_GetErrorText, "Pm_GetErrorText" );
  36.   package ErrorText_Conversion is new System.Address_To_Access_Conversions
  37.     (T_ErrorText);
  38.   use ErrorText_Conversion;
  39.  
  40.      
  41.   type DeviceInfo is
  42.      record
  43.         StructVersion : Integer;
  44.         Interf : System.address;
  45.         Name : System.Address;
  46.         Input : Integer;
  47.         Output : Integer;
  48.         Opened : integer;
  49.      end record;
  50.  
  51.  
  52.   function Pm_CountDevices return Integer;
  53.   pragma Import (C, Pm_CountDevices, "Pm_CountDevices" );
  54.        
  55.   function Pm_GetDefaultInputDeviceID return Interfaces.C.int;
  56.   pragma Import (C, Pm_GetDefaultInputDeviceID, "Pm_GetDefaultInputDeviceID" );
  57.  
  58.   function Pm_GetDefaultOutputDeviceID return Interfaces.C.Int;
  59.   pragma Import (C, Pm_GetDefaultOutputDeviceID, "Pm_GetDefaultOutputDeviceID" );
  60.  
  61.   function Pm_GetDeviceInfo(PmDeviceID : Integer) return System.Address;
  62.   pragma Import (C, Pm_GetDeviceInfo, "Pm_GetDeviceInfo" );
  63.  
  64.   package DeviceInfo_Conversion is new System.Address_To_Access_Conversions(DeviceInfo);
  65.   use DeviceInfo_Conversion;
  66.  
  67.   function Pm_OpenInput(PortMidiStream : access System.address;
  68.                         PmDeviceID : Integer;
  69.                         InputDriverInfo : access DeviceInfo;
  70.                         BufferSize : Long_Integer;
  71.                         PmTimeProcPtr : Porttime.Time_access;
  72.                         time_info : System.address) return PmError;
  73.   pragma Import (C, Pm_OpenInput, "Pm_OpenInput" );
  74.  
  75.  
  76.   function Pm_OpenOutput(PortMidiStream : access System.Address;
  77.                          OutputDevice : Integer;
  78.                          outputDriverInfo : access DeviceInfo;
  79.                          BufferSize : Long_Integer;
  80.                          Time_Proc : Porttime.Time_access;
  81.                          Time_Info : System.address;
  82.                          latency : Long_integer) return PmError;
  83.   pragma Import (C, Pm_OpenOutput, "Pm_OpenOutput" );
  84.  
  85.  
  86.   --   /* Filter bit-mask definitions */
  87.   --/** filter active sensing messages (0xFE): */
  88.   function PM_FILT_ACTIVE return Unsigned_32; --(1 << 0x0E)
  89.                            --/** filter system exclusive messages (0xF0): */
  90.   function PM_FILT_SYSEX return Unsigned_32; --(1 << 0x00)
  91.                           --/** filter MIDI clock message (0xF8) */
  92.   function PM_FILT_CLOCK return Unsigned_32; --(1 << 0x08)
  93.                           --/** filter play messages (start 0xFA, stop 0xFC, continue 0xFB) */
  94.   function PM_FILT_PLAY return Unsigned_32; --((1 << 0x0A) | (1 << 0x0C) | (1 << 0x0B))
  95.                          --/** filter tick messages (0xF9) */
  96.   function PM_FILT_TICK return Unsigned_32; --(1 << 0x09)
  97.                          --/** filter undefined FD messages */
  98.   function PM_FILT_FD return Unsigned_32; --(1 << 0x0D)
  99.                        --/** filter undefined real-time messages */
  100.   function PM_FILT_UNDEFINED return Unsigned_32; --PM_FILT_FD
  101.                           --/** filter reset messages (0xFF) */
  102.   function PM_FILT_RESET return Unsigned_32; --(1 << 0x0F)
  103.                           --/** filter all real-time messages */
  104.   function PM_FILT_REALTIME return Unsigned_32; --(PM_FILT_ACTIVE | PM_FILT_SYSEX | PM_FILT_CLOCK | \
  105.                          --    PM_FILT_PLAY | PM_FILT_UNDEFINED | PM_FILT_RESET | PM_FILT_TICK)
  106.                          --/** filter note-on and note-off (0x90-0x9F and 0x80-0x8F */
  107.   function PM_FILT_NOTE return Unsigned_32; --((1 << 0x19) | (1 << 0x18))
  108.                          --/** filter channel aftertouch (most midi controllers use this) (0xD0-0xDF)*/
  109.   function PM_FILT_CHANNEL_AFTERTOUCH return Unsigned_32; --(1 << 0x1D)
  110.                                --/** per-note aftertouch (0xA0-0xAF) */
  111.   function PM_FILT_POLY_AFTERTOUCH return Unsigned_32; --(1 << 0x1A)
  112.                             --/** filter both channel and poly aftertouch */
  113.   function PM_FILT_AFTERTOUCH return Unsigned_32; --(PM_FILT_CHANNEL_AFTERTOUCH | PM_FILT_POLY_AFTERTOUCH)
  114.                            --/** Program changes (0xC0-0xCF) */
  115.   function PM_FILT_PROGRAM return Unsigned_32; --(1 << 0x1C)
  116.                         --/** Control Changes (CC's) (0xB0-0xBF)*/
  117.   function PM_FILT_CONTROL return Unsigned_32; --(1 << 0x1B)
  118.                         --/** Pitch Bender (0xE0-0xEF*/
  119.   function PM_FILT_PITCHBEND return Unsigned_32; --(1 << 0x1E)
  120.                           --/** MIDI Time Code (0xF1)*/
  121.   function PM_FILT_MTC return Unsigned_32; --(1 << 0x01)
  122.                         --/** Song Position (0xF2) */
  123.   function PM_FILT_SONG_POSITION return Unsigned_32; --(1 << 0x02)
  124.                               --/** Song Select (0xF3)*/
  125.   function PM_FILT_SONG_SELECT return Unsigned_32; --(1 << 0x03)
  126.                             --/** Tuning request (0xF6)*/
  127.   function PM_FILT_TUNE return Unsigned_32; --(1 << 0x06)
  128.                          --/** All System Common messages (mtc, song position, song select, tune request) */
  129.   function PM_FILT_SYSTEMCOMMON return Unsigned_32; --(PM_FILT_MTC | PM_FILT_SONG_POSITION | PM_FILT_SONG_SELECT | PM_FILT_TUNE)
  130.             
  131.   function Pm_SetFilter(PortMidiStream : System.Address;
  132.                         filters : Unsigned_32) return PmError;
  133.   pragma Import (C, Pm_SetFilter, "Pm_SetFilter" );
  134.  
  135.   function Pm_SetChannelMask(PortMidiStream : System.Address;
  136.                              Mask : integer) return PmError;
  137.   pragma Import (C, Pm_SetChannelMask, "Pm_SetChannelMask" );
  138.  
  139.   function Pm_Abort( PortMidiStream : System.Address) return PmError;
  140.   pragma Import (C, Pm_Abort, "Pm_Abort" );
  141.  
  142.   function Pm_Close( PortMidiStream : System.Address) return PmError;
  143.   pragma Import (C, Pm_Close, "Pm_Close" );
  144.  
  145.  
  146.  
  147.  
  148.  
  149.   function Pm_Message(Status, Data1, Data2 : Interfaces.C.Long) return Interfaces.C.Long;
  150.   function Status(Message : Interfaces.C.long) return Interfaces.C.Long;
  151.   function data1(Message : Interfaces.C.long) return Interfaces.C.Long;
  152.   function Channel(Message : Interfaces.C.Long) return Interfaces.C.Long;
  153.   function data2(Message : Interfaces.C.long) return Interfaces.C.Long;
  154.  
  155.  
  156.  
  157.   type PmEvent is
  158.      record
  159.         Message : Interfaces.C.Long := 0;
  160.         PmTimestamp : Interfaces.C.Long := 0;
  161.      end record;
  162.      
  163.  
  164.   Function Pm_Read(PortMidiStream : System.Address;            
  165.             Pm_Event : access PmEvent;
  166.             length : Interfaces.C.Long) return PmError ;
  167.   pragma Import (C, Pm_Read, "Pm_Read" );
  168.  
  169.   function Pm_Poll( PortMidiStream : System.Address) return PmError;
  170.   pragma Import (C, Pm_Poll, "Pm_Poll" );
  171.  
  172.  
  173.   function Pm_Write( PortMidiStream : System.address;
  174.                      Pm_Event : PmEvent;
  175.                      length : Interfaces.C.Long) return PmError ;
  176.   pragma Import (C, Pm_Write, "Pm_Write" );
  177.  
  178.  
  179.   function Pm_WriteShort( PortMidiStream : System.address;
  180.                           PmTimestamp : Interfaces.C.long;
  181.                           Msg : Interfaces.C.long) return PmError;
  182.   pragma Import (C, Pm_WriteShort, "Pm_WriteShort" );
  183.  
  184.   function Pm_WriteSysEx( PortMidiStream : System.Address;
  185.                           PmTimestamp : Float;
  186.                           Msg : integer) return PmError;
  187.   pragma Import (C, Pm_WriteSysEx, "Pm_WriteSysEx" );
  188.  
  189.  
  190.  
  191. end Portmidi;


 

Reply

Marsh Posté le 04-10-2012 à 07:58:07   

Reply

Marsh Posté le 04-10-2012 à 10:42:40    

j'en suit là à cette heure.
 

Code :
  1. task type Input_Driver_Type(Addr : Address_Access) is
  2.      entry Send(Message : out C.Long);
  3.   end Input_Driver_Type;
  4.      
  5.   task body Input_Driver_Type is
  6.      
  7.      Pm_Error : PmError;
  8.   begin
  9.      
  10.      Pm_Error := Pm_SetFilter(Addr.all, PM_FILT_ACTIVE or PM_FILT_CLOCK);
  11.      loop             
  12.      declare          
  13.         
  14.         Event : aliased PmEvent;
  15.      begin                        
  16.         
  17.         Pm_Error := Pm_Read(Addr.all, Event'access, 1);
  18.           
  19.         if C."/="(Event.Message,0) then
  20.            select
  21.           accept Send(Message : out C.Long) do
  22.              Text_Io.Put_Line("Reading message :" & C.Long'Image(Event.Message));
  23.              Message := Event.Message;                       
  24.           end Send;          
  25.            or delay 1.0;
  26.            end select;
  27.         else
  28.            delay 0.001;
  29.         end if;
  30.      end;
  31.      end loop;      
  32.   end Input_Driver_Type;


 
Ce qui me convient à peut près, le délay limitant l'utilisateur du CPU et malgré le fait que j'ai un HostError au Pm_Read, je récupère bien ma valeur.
Mais ce delay arbitraire me gène quand même, alors si vous avez une soluce....
Merci.


Message édité par Profil supprimé le 04-10-2012 à 10:43:23
Reply

Marsh Posté le 09-10-2012 à 22:40:07    

Je crois que j'ai un problème avec la fonction Channel correspondant à Pm_Channel.
Si quelqu'un peut jeter un oeil.... Merci
 
J'ai 288 après alors que j'ai fait un note_on sur le canal 0


Message édité par Profil supprimé le 09-10-2012 à 22:47:45
Reply

Marsh Posté le 09-10-2012 à 23:10:00    

Je crois que j'attribue une autre fonction à PM_Channel.
 
 
En fait je veux le channel à partir du message en C long ou du status.
 
Help !  :D

Reply

Marsh Posté le 10-10-2012 à 00:23:30    


 
 
J'aii trouvé, je fait un & entre le status et 16#40#, je viens de piger ce qu'est un mask en exa. Ahaha.  [:chownkey]

Reply

Marsh Posté le 10-10-2012 à 00:39:49    

Avec 16#4F# c'est mieux quand même.

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed