struct

(**

Descripton

La fonction detect sert à déterminer quel est le modèle de clavier MIDI qui envoie des données. Il faut manipuler suffisamment de boutons-poussoirs, boutons rotatifs et curseurs pour que le type de clavier soit déterminé soit par un numéro de contrôleur particulier au fabricant soit par éliminations successives.

Copyright Stéphane Grognet
IREM des Pays de la Loire - Université de Nantes
Laboratoire de mathématiques Jean Leray UMR 6629 CNRS
version 0.7
@version 0.7 @author Stéphane Grognet @since 2014 *)


type fabricant =
| Inconnu
| Alesis
| Arturia
| M_audio
| Roland ;;

let tout = [ Alesis ; Arturia ; M_audio ; Roland ] ;;

let cmp = fun (x:fabricant) (y:fabricant) ->
 match x with
 | Inconnu ->
  begin
   match y with
   | Inconnu -> 0
   | _ -> -1
  end
 | Alesis ->
  begin
   match y with
   | Inconnu -> 1
   | Alesis -> 0
   | _ -> -1
  end
 | Arturia ->
  begin
   match y with
   | Inconnu | Alesis -> 1
   | Arturia -> 0
   | _ -> -1
  end
 | M_audio ->
  begin
   match y with
   | M_audio -> 0
   | Roland -> -1
   | _ -> 1
  end
 | Roland ->
  begin
   match y with
   | Roland -> 0
   | _ -> -1
  end ;;

let trad = function (x:fabricant) ->
 let chaine = match x with
  | Alesis -> "alesis"
  | Arturia -> "arturia"
  | M_audio -> "m_audio"
  | Roland -> "roland"
  | _ -> "" in
  print_string chaine ;
  print_newline () ;;

let rec ajoute = fun (x:fabricant list) (y:fabricant list) ->
 match x with
 | [] -> y
 | z :: q ->
  begin
   if List.exists ( function w -> cmp w z = 0 ) y then
    ajoute q y
   else
    z :: ( ajoute q y )
  end ;;

let detect = function ic ->
 let continue = ref true
 and masque_entete = 0xF0
 and mode = 0xB0
 and instru = 0xC0
 and c = ref 0
 and entete = ref 0
 and controleur = ref 0
 and pas_fab = ref [ ]
 and fab = ref Inconnu in
  while !continue do
   c := input_byte ic ;
   entete := !c land masque_entete ;
   match !entete with
   | x when x land mode = mode ->
    begin
     controleur := input_byte ic ;
     begin
      fab := match !controleur with
      | 0x0E | 0x0F | 0x14 -> ( continue := false ; Alesis )
      | 0x1E | 0x1F | 0x32 | 0x33 | 0x34 | 0x35 | 0x36 | 0x37 | 0x55 -> ( continue := false ; Arturia )
      | 0x00 | 0x20 | 0x54 | 0x6E | 0x6F | 0x71 | 0xBF -> ( continue := false ; M_audio )
      | 0x02 | 0x0B | 0x41 | 0x5E -> ( continue := false ; Roland )
      | _ -> Inconnu ;
     end ;
     if !continue then
      begin
       begin
        pas_fab := match !controleur with
        | 0x07 | 0x47 | 0x48 | 0x49 | 0x4A | 0x4B | 0x4C | 0x4D | 0x5B | 0x5D -> ajoute [Alesis] !pas_fab
        | 0x16 | 0x17 | 0x18 | 0x19 | 0x1A | 0x1B | 0x1C -> ajoute [M_audio] !pas_fab
        | 0x76 -> ajoute [Roland] !pas_fab
        | 0x05 | 0x0A | 0x4E | 0x5C | 0x5F -> ajoute [Alesis ; Arturia] !pas_fab
        | 0x50 | 0x51 | 0x52 | 0x53 -> ajoute [Alesis ; M_audio] !pas_fab
        | 0x4F -> ajoute [Alesis ; Roland] !pas_fab
        | 0x15 -> ajoute [Arturia ; M_audio] !pas_fab
        | 0x72 | 0x73 | 0x74 | 0x75 -> ajoute [Arturia ; Roland] !pas_fab
        | 0x10 | 0x11 | 0x12 | 0x13 | 0x1D | 0x77 -> ajoute [M_audio ; Roland] !pas_fab
        | _ -> !pas_fab
       end ;
       if List.length !pas_fab = 3 then
        begin
         let test = ref tout
         and x = ref Inconnu
         and poursuis = ref true in
          while !poursuis do
           x := List.hd !test ;
           test := List.tl !test ;
           if List.for_all ( function y -> cmp !x y <> 0 ) !pas_fab then
            poursuis := false ;
          done ;
          fab := !x ;
          continue := false ;
        end ;
       ignore ( input_byte ic ) ;
      end
    end
   | x when x land instru = instru ->
    begin
     ignore ( input_byte ic ) ;
     fab := M_audio ;
     continue := false ;
    end
   | _ -> () ;
  done ;
  trad !fab ;;

detect stdin ;;



end