-- computerman is multiway user tools.
-- Computerman is Copyright (C) 2024 Manuel De Girardi ; 
--
--   This program is free software; you can redistribute it and/or modify
--   it under the terms of the GNU General Public License as published by
--   the Free Software Foundation; either version 2 of the License, or
--   (at your option) any later version.
--
--   This program is distributed in the hope that it will be useful,
--   but WITHOUT ANY WARRANTY; without even the implied warranty of
--   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
--   GNU General Public License for more details.
--
--   You should have received a copy of the GNU General Public License
--   along with this program; if not, write to the Free Software
--   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
--
-- Date := "2024-05-10 09:03:04"
-- Version := "0.0.0r"
with Interfaces.C;
use Interfaces.C;
with Computer.MIDI.Devices;              use Computer.MIDI.Devices;
with Computer.MIDI.Messages;             use Computer.MIDI.Messages;

with Ada.Finalization;                  use Ada.Finalization;

with Ada.Unchecked_Deallocation;
package Computer.Midi.Drivers is
   function Hex_Image(Num : Interfaces.C.Long) return String;
   
   
   type Device_Info_Type is
      record
	 Name : access String;
	 Id   : Natural := 0;
      end record;
   
   Null_Device_Info : constant Device_Info_Type := (Name => null, Id => 0);
   
   type Devices_List_Type is array (Positive range <>) of Device_Info_Type;
   
   type Devices_List_Access is access Devices_List_Type;
   
   
   function Inputs_List return Devices_List_Access;
   function Outputs_List return Devices_List_Access;   
   
   
   
   type Control_Type is (Null_Item, Note_On, Note_Off, 
			 Eq, Osc1, Osc2, Filters, Fx1, Fx2, MstFx, 
			 Control, Program_Change, Channel_Pressure, Pitchbend, Mod_wheel);
   -- Définit la classe des messages reçus.
         
   function Control_of(Message : Interfaces.C.Long) return Control_Type ;
   -- Renvoie le type du message reçu sous forme de Long.
      
   function Channel_Of(Message : in Long) return Channel_Type;
   -- Renvoie le cannal sur lequel a été émit le message.
   
   
   type Bank_Geometry_Type is
      record
	 MSB_Bank_Max : Bank_Type := 0;
	 LSB_Bank_Max : Bank_Type := 127;
      end record;      
   
   subtype Timbre_Id_Type is Natural range 0..15;
   
   type Map_Geometry_Type is
      record
	 Num_Timbre    : Timbre_Id_Type := 0;	 
	 Bank_Geometry : Bank_Geometry_Type := (Bank_Type'first, Bank_Type'First);
      end record;      	 
   
   type Output_Device_Driver_Type;
   
   protected type OutputDriver_Type(Device_Driver : access Output_Device_Driver_Type) is
      entry Receive(Message : in Long);   
   end OutputDriver_Type;
   
   type Output_Device_Driver_Type is limited
      record	 
	 Device_Info : Device_Info_Type;
	 Output : Device_Access;
	 Output_Driver : aliased OutputDriver_Type(Output_Device_Driver_Type'Access);	 
      end record;            
   
   type Output_Device_Driver_Access is access Output_Device_Driver_Type;
   
   procedure Output_Driver_Free is new Ada.Unchecked_Deallocation(Output_Device_Driver_Type, Output_Device_Driver_Access);
   
   
   type Input_Device_Driver_Type;
   task type InputDriver_Type(Device_Driver : access Input_Device_Driver_Type) is
      entry Start;
      entry Stop;
      entry Halt;
      entry Send(Message : out Long);
   end InputDriver_Type;   
                  
   type Input_Device_Driver_Type is limited
      record
	 Device_Info   : Device_Info_Type;
	 Input         : Device_Access;
	 Input_Driver  : aliased InputDriver_Type(Input_Device_Driver_Type'Access);	 	 
      end record;      
   
   type Input_Device_Driver_Access is access Input_Device_Driver_Type;
   
   procedure Input_Driver_Free is new Ada.Unchecked_Deallocation(Input_Device_Driver_Type, Input_Device_Driver_Access);
   
   procedure Initialize_Input(Input_Device_Driver : in out Input_Device_Driver_Type; 
			      Device_Info : in Device_Info_Type);
   
   procedure Initialize_Output(Output_Device_Driver : in out Output_Device_Driver_Type;
			       Device_Info : in Device_Info_Type);
      
   
   type Device_Driver_Record is new Limited_Controlled with
      record
	 Output_Device_Driver : Output_Device_Driver_Access;
	 Input_Device_Driver : Input_Device_Driver_Access;
	 Map_Geometry   : Map_Geometry_Type;
	 Sync       : Boolean := True;
      end record;

end Computer.Midi.Drivers ;