-- 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 Computer.MIDI.Porttime;
with System;
with Interfaces.C;
use Interfaces;
with System.Address_To_Access_Conversions;

package Computer.Midi.Portmidi is
   type Address_Access is access all System.Address;
   
   type PmError is (pmNoError,
                    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_OpenInput(PortMidiStream : access System.address;
                         PmDeviceID : Integer;
                         InputDriverInfo : access DeviceInfo;
                         BufferSize : Integer;
                         PmTimeProcPtr : Porttime.Time_access;
                         time_info : System.address) return PmError;
   pragma Import (C, Pm_OpenInput, "Pm_OpenInput");


   function Pm_OpenOutput(PortMidiStream : access System.Address;
                          OutputDevice : Integer;
                          outputDriverInfo : access DeviceInfo;
                          BufferSize : Integer;
                          Time_Proc : Porttime.Time_access;
                          Time_Info : System.address;
                          latency : Long_integer) return PmError;
   pragma Import (C, Pm_OpenOutput, "Pm_OpenOutput");
   
      
   --   /* Filter bit-mask definitions */
   --/** filter active sensing messages (0xFE): */
   function PM_FILT_ACTIVE return Unsigned_32; --(1 << 0x0E)
					       --/** filter system exclusive messages (0xF0): */
   function PM_FILT_SYSEX return Unsigned_32; --(1 << 0x00)
					      --/** filter MIDI clock message (0xF8) */
   function PM_FILT_CLOCK return Unsigned_32; --(1 << 0x08)
					      --/** filter play messages (start 0xFA, stop 0xFC, continue 0xFB) */
   function PM_FILT_PLAY return Unsigned_32; --((1 << 0x0A) | (1 << 0x0C) | (1 << 0x0B))
					     --/** filter tick messages (0xF9) */
   function PM_FILT_TICK return Unsigned_32; --(1 << 0x09)
					     --/** filter undefined FD messages */
   function PM_FILT_FD return Unsigned_32; --(1 << 0x0D)
					   --/** filter undefined real-time messages */
   function PM_FILT_UNDEFINED return Unsigned_32; --PM_FILT_FD
						  --/** filter reset messages (0xFF) */
   function PM_FILT_RESET return Unsigned_32; --(1 << 0x0F)
					      --/** filter all real-time messages */
   function PM_FILT_REALTIME return Unsigned_32; --(PM_FILT_ACTIVE | PM_FILT_SYSEX | PM_FILT_CLOCK | \
						 --    PM_FILT_PLAY | PM_FILT_UNDEFINED | PM_FILT_RESET | PM_FILT_TICK)
						 --/** filter note-on and note-off (0x90-0x9F and 0x80-0x8F */
   function PM_FILT_NOTE return Unsigned_32; --((1 << 0x19) | (1 << 0x18))
					     --/** filter channel aftertouch (most midi controllers use this) (0xD0-0xDF)*/
   function PM_FILT_CHANNEL_AFTERTOUCH return Unsigned_32; --(1 << 0x1D)
							   --/** per-note aftertouch (0xA0-0xAF) */
   function PM_FILT_POLY_AFTERTOUCH return Unsigned_32; --(1 << 0x1A)
							--/** filter both channel and poly aftertouch */
   function PM_FILT_AFTERTOUCH return Unsigned_32; --(PM_FILT_CHANNEL_AFTERTOUCH | PM_FILT_POLY_AFTERTOUCH)
						   --/** Program changes (0xC0-0xCF) */
   function PM_FILT_PROGRAM return Unsigned_32; --(1 << 0x1C)
						--/** Control Changes (CC's) (0xB0-0xBF)*/
   function PM_FILT_CONTROL return Unsigned_32; --(1 << 0x1B)
						--/** Pitch Bender (0xE0-0xEF*/
   function PM_FILT_PITCHBEND return Unsigned_32; --(1 << 0x1E)
						  --/** MIDI Time Code (0xF1)*/
   function PM_FILT_MTC return Unsigned_32; --(1 << 0x01)
					    --/** Song Position (0xF2) */
   function PM_FILT_SONG_POSITION return Unsigned_32; --(1 << 0x02)
						      --/** Song Select (0xF3)*/
   function PM_FILT_SONG_SELECT return Unsigned_32; --(1 << 0x03)
						    --/** Tuning request (0xF6)*/
   function PM_FILT_TUNE return Unsigned_32; --(1 << 0x06)
					     --/** All System Common messages (mtc, song position, song select, tune request) */
   function PM_FILT_SYSTEMCOMMON return Unsigned_32; --(PM_FILT_MTC | PM_FILT_SONG_POSITION | PM_FILT_SONG_SELECT | PM_FILT_TUNE)
		    
   function Pm_SetFilter(PortMidiStream : System.Address;
                         filters : Unsigned_32) 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");

   
   
   
   
   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;
      
   
   type Pmevent_Access is access all Pmevent;
   Function Pm_Read(PortMidiStream : System.Address;		    
		    Pm_Event : access PmEvent;
		    length : Interfaces.C.Long) return PmError ;

   pragma Import (C, Pm_Read, "Pm_Read");
   
   function Pm_Poll( PortMidiStream : System.Address) return PmError;
   pragma Import (C, Pm_Poll, "Pm_Poll");
   
   
   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");
   
   
   -- for testing because bug.
   
   function Read_handler(Device_Id : System.address) return Interfaces.C.long;
   pragma Import (C, Read_Handler, "Read_Handler");

end Computer.Midi.Portmidi ;