From 74af58587359206ef92249d18e4830c40cac0bc5 Mon Sep 17 00:00:00 2001 From: Jedidiah Barber Date: Mon, 19 Jun 2023 22:15:44 +1200 Subject: Initial commit --- src/c_aao.c | 136 +++++++++++ src/c_aao.h | 50 ++++ src/libao.adb | 746 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/libao.ads | 319 +++++++++++++++++++++++++ 4 files changed, 1251 insertions(+) create mode 100644 src/c_aao.c create mode 100644 src/c_aao.h create mode 100644 src/libao.adb create mode 100644 src/libao.ads (limited to 'src') diff --git a/src/c_aao.c b/src/c_aao.c new file mode 100644 index 0000000..731792d --- /dev/null +++ b/src/c_aao.c @@ -0,0 +1,136 @@ + + +// Programmed by Jedidiah Barber +// Released into the public domain + + +#include +#include "c_aao.h" + + + +int type_live() { + return AO_TYPE_LIVE; +} + +int type_file() { + return AO_TYPE_FILE; +} + + + +int sample_little_endian() { + return AO_FMT_LITTLE; +} + +int sample_big_endian() { + return AO_FMT_BIG; +} + +int sample_native_endian() { + return AO_FMT_NATIVE; +} + + + +int error_no_driver() { + return AO_ENODRIVER; +} + +int error_not_file() { + return AO_ENOTFILE; +} + +int error_not_live() { + return AO_ENOTLIVE; +} + +int error_bad_option() { + return AO_EBADOPTION; +} + +int error_open_device() { + return AO_EOPENDEVICE; +} + +int error_open_file() { + return AO_EOPENFILE; +} + +int error_file_exists() { + return AO_EFILEEXISTS; +} + +int error_bad_format() { + return AO_EBADFORMAT; +} + +int error_fail() { + return AO_EFAIL; +} + + + +ao_info * info_item_get(ao_info ** items, int n) { + return items[n]; +} + + + +int info_kind_get(ao_info * item) { + return item->type; +} + +char * info_name_get(ao_info * item) { + return item->name; +} + +char * info_short_name_get(ao_info * item) { + return item->short_name; +} + +int info_preferred_byte_format_get(ao_info * item) { + return item->preferred_byte_format; +} + +int info_priority_get(ao_info * item) { + return item->priority; +} + +char * info_comment_get(ao_info * item) { + return item->comment; +} + +int info_option_count_get(ao_info * item) { + return item->option_count; +} + +char * info_option_key_get(ao_info * item, int n) { + return item->options[n]; +} + + + +int get_errno() { + return errno; +} + + + +char * option_key(ao_option * item) { + return item->key; +} + +char * option_value(ao_option * item) { + return item->value; +} + +ao_option * option_next(ao_option * item) { + if (item == NULL) { + return NULL; + } else { + return item->next; + } +} + + diff --git a/src/c_aao.h b/src/c_aao.h new file mode 100644 index 0000000..d0a23a4 --- /dev/null +++ b/src/c_aao.h @@ -0,0 +1,50 @@ + + +// Programmed by Jedidiah Barber +// Released into the public domain + + +#ifndef AAO_GUARD +#define AAO_GUARD + +#include + + +int type_live(); +int type_file(); + +int sample_little_endian(); +int sample_big_endian(); +int sample_native_endian(); + +int error_no_driver(); +int error_not_file(); +int error_not_live(); +int error_bad_option(); +int error_open_device(); +int error_open_file(); +int error_file_exists(); +int error_bad_format(); +int error_fail(); + +ao_info * info_item_get(ao_info ** items, int n); + +int info_kind_get(ao_info * item); +char * info_name_get(ao_info * item); +char * info_short_name_get(ao_info * item); +int info_preferred_byte_format_get(ao_info * item); +int info_priority_get(ao_info * item); +char * info_comment_get(ao_info * item); +int info_option_count_get(ao_info * item); +char * info_option_key_get(ao_info * item, int n); + +int get_errno(); + +char * option_key(ao_option * item); +char * option_value(ao_option * item); +ao_option * option_next(ao_option * item); + + +#endif + + diff --git a/src/libao.adb b/src/libao.adb new file mode 100644 index 0000000..c1491c2 --- /dev/null +++ b/src/libao.adb @@ -0,0 +1,746 @@ + + +-- Programmed by Jedidiah Barber +-- Released into the public domain + + +with + + Interfaces.C.Strings, + System; + +use type + + Interfaces.C.int, + Interfaces.C.Strings.chars_ptr, + System.Address; + + +package body Libao is + + + procedure ao_initialize; + pragma Import (C, ao_initialize, "ao_initialize"); + pragma Inline (ao_initialize); + + procedure ao_shutdown; + pragma Import (C, ao_shutdown, "ao_shutdown"); + pragma Inline (ao_shutdown); + + + + + function ao_append_option + (Options : in out System.Address; + Key : in Interfaces.C.char_array; + Value : in Interfaces.C.char_array) + return Interfaces.C.int; + pragma Import (C, ao_append_option, "ao_append_option"); + pragma Inline (ao_append_option); + + function ao_append_global_option + (Key : in Interfaces.C.char_array; + Value : in Interfaces.C.char_array) + return Interfaces.C.int; + pragma Import (C, ao_append_global_option, "ao_append_global_option"); + pragma Inline (ao_append_global_option); + + procedure ao_free_options + (Options : in System.Address); + pragma Import (C, ao_free_options, "ao_free_options"); + pragma Inline (ao_free_options); + + function ao_open_live + (Driver_ID : in Interfaces.C.int; + Format : in System.Address; + Options : in System.Address) + return System.Address; + pragma Import (C, ao_open_live, "ao_open_live"); + pragma Inline (ao_open_live); + + function ao_open_file + (Driver_ID : in Interfaces.C.int; + Filename : in Interfaces.C.char_array; + Overwrite : in Interfaces.C.int; + Format : in System.Address; + Options : in System.Address) + return System.Address; + pragma Import (C, ao_open_file, "ao_open_file"); + pragma Inline (ao_open_file); + + function ao_play + (Output_Device : in System.Address; + Samples : in Interfaces.C.char_array; + Num_Bytes : in Interfaces.Unsigned_32) + return Interfaces.C.int; + pragma Import (C, ao_play, "ao_play"); + pragma Inline (ao_play); + + function ao_close + (Output_Device : in System.Address) + return Interfaces.C.int; + pragma Import (C, ao_close, "ao_close"); + pragma Inline (ao_close); + + + + + function ao_driver_id + (Short_Name : in Interfaces.C.char_array) + return Interfaces.C.int; + pragma Import (C, ao_driver_id, "ao_driver_id"); + pragma Inline (ao_driver_id); + + function ao_default_driver_id + return Interfaces.C.int; + pragma Import (C, ao_default_driver_id, "ao_default_driver_id"); + pragma Inline (ao_default_driver_id); + + function ao_driver_info + (Ident : in Interfaces.C.int) + return System.Address; + pragma Import (C, ao_driver_info, "ao_driver_info"); + pragma Inline (ao_driver_info); + + function ao_driver_info_list + (Count : out Interfaces.C.int) + return System.Address; + pragma Import (C, ao_driver_info_list, "ao_driver_info_list"); + pragma Inline (ao_driver_info_list); + + function ao_file_extension + (Ident : in Interfaces.C.int) + return Interfaces.C.Strings.chars_ptr; + pragma Import (C, ao_file_extension, "ao_file_extension"); + pragma Inline (ao_file_extension); + + + + + function ao_is_big_endian + return Interfaces.C.int; + pragma Import (C, ao_is_big_endian, "ao_is_big_endian"); + pragma Inline (ao_is_big_endian); + + + + + function type_live + return Interfaces.C.int; + pragma Import (C, type_live, "type_live"); + pragma Inline (type_live); + + function type_file + return Interfaces.C.int; + pragma Import (C, type_file, "type_file"); + pragma Inline (type_file); + + + + + function sample_little_endian + return Interfaces.C.int; + pragma Import (C, sample_little_endian, "sample_little_endian"); + pragma Inline (sample_little_endian); + + function sample_big_endian + return Interfaces.C.int; + pragma Import (C, sample_big_endian, "sample_big_endian"); + pragma Inline (sample_big_endian); + + function sample_native_endian + return Interfaces.C.int; + pragma Import (C, sample_native_endian, "sample_native_endian"); + pragma Inline (sample_native_endian); + + + + + function error_no_driver + return Interfaces.C.int; + pragma Import (C, error_no_driver, "error_no_driver"); + pragma Inline (error_no_driver); + + function error_not_file + return Interfaces.C.int; + pragma Import (C, error_not_file, "error_not_file"); + pragma Inline (error_not_file); + + function error_not_live + return Interfaces.C.int; + pragma Import (C, error_not_live, "error_not_live"); + pragma Inline (error_not_live); + + function error_bad_option + return Interfaces.C.int; + pragma Import (C, error_bad_option, "error_bad_option"); + pragma Inline (error_bad_option); + + function error_open_device + return Interfaces.C.int; + pragma Import (C, error_open_device, "error_open_device"); + pragma Inline (error_open_device); + + function error_open_file + return Interfaces.C.int; + pragma Import (C, error_open_file, "error_open_file"); + pragma Inline (error_open_file); + + function error_file_exists + return Interfaces.C.int; + pragma Import (C, error_file_exists, "error_file_exists"); + pragma Inline (error_file_exists); + + function error_bad_format + return Interfaces.C.int; + pragma Import (C, error_bad_format, "error_bad_format"); + pragma Inline (error_bad_format); + + function error_fail + return Interfaces.C.int; + pragma Import (C, error_fail, "error_fail"); + pragma Inline (error_fail); + + + + + function info_item_get + (Infos : in System.Address; + Index : in Interfaces.C.int) + return System.Address; + pragma Import (C, info_item_get, "info_item_get"); + pragma Inline (info_item_get); + + + + + function info_kind_get + (Item : in System.Address) + return Interfaces.C.int; + pragma Import (C, info_kind_get, "info_kind_get"); + pragma Inline (info_kind_get); + + function info_name_get + (Item : in System.Address) + return Interfaces.C.Strings.chars_ptr; + pragma Import (C, info_name_get, "info_name_get"); + pragma Inline (info_name_get); + + function info_short_name_get + (Item : in System.Address) + return Interfaces.C.Strings.chars_ptr; + pragma Import (C, info_short_name_get, "info_short_name_get"); + pragma Inline (info_short_name_get); + + function info_preferred_byte_format_get + (Item : in System.Address) + return Interfaces.C.int; + pragma Import (C, info_preferred_byte_format_get, "info_preferred_byte_format_get"); + pragma Inline (info_preferred_byte_format_get); + + function info_priority_get + (Item : in System.Address) + return Interfaces.C.int; + pragma Import (C, info_priority_get, "info_priority_get"); + pragma Inline (info_priority_get); + + function info_comment_get + (Item : in System.Address) + return Interfaces.C.Strings.chars_ptr; + pragma Import (C, info_comment_get, "info_comment_get"); + pragma Inline (info_comment_get); + + function info_option_count_get + (Item : in System.Address) + return Interfaces.C.int; + pragma Import (C, info_option_count_get, "info_option_count_get"); + pragma Inline (info_option_count_get); + + function info_option_key_get + (Item : in System.Address; + Index : in Interfaces.C.int) + return Interfaces.C.Strings.chars_ptr; + pragma Import (C, info_option_key_get, "info_option_key_get"); + pragma Inline (info_option_key_get); + + + + + function get_errno + return Interfaces.C.int; + pragma Import (C, get_errno, "get_errno"); + pragma Inline (get_errno); + + + + + function option_key + (Item : in System.Address) + return Interfaces.C.Strings.chars_ptr; + pragma Import (C, option_key, "option_key"); + pragma Inline (option_key); + + function option_value + (Item : in System.Address) + return Interfaces.C.Strings.chars_ptr; + pragma Import (C, option_value, "option_value"); + pragma Inline (option_value); + + function option_next + (Item : in System.Address) + return System.Address; + pragma Import (C, option_next, "option_next"); + pragma Inline (option_next); + + + + + procedure Adjust + (This : in out Option_List) + is + Old : System.Address := This.Ptr; + begin + This.Ptr := System.Null_Address; + while Old /= System.Null_Address loop + Do_Append + (This.Ptr, + Interfaces.C.Strings.Value (option_key (This.Ptr)), + Interfaces.C.Strings.Value (option_value (This.Ptr))); + Old := option_next (Old); + end loop; + end Adjust; + + procedure Finalize + (This : in out Option_List) is + begin + ao_free_options (This.Ptr); + end Finalize; + + procedure Adjust + (This : in out Sample_Format) is + begin + This.C_Struct.Matrix := Interfaces.C.Strings.New_String + (Interfaces.C.Strings.Value (This.C_Struct.Matrix)); + end Adjust; + + procedure Finalize + (This : in out Sample_Format) is + begin + Interfaces.C.Strings.Free (This.C_Struct.Matrix); + end Finalize; + + + + + function Kind + (Attributes : in Info) + return Output_Kind + is + Value : Interfaces.C.int := info_kind_get (Attributes.Ptr); + begin + if Value = type_live then + return Live_Output; + elsif Value = type_file then + return File_Output; + else + raise Program_Error; + end if; + end Kind; + + function Name + (Attributes : in Info) + return String is + begin + return Interfaces.C.Strings.Value (info_name_get (Attributes.Ptr)); + end Name; + + function Short_Name + (Attributes : in Info) + return String is + begin + return Interfaces.C.Strings.Value (info_short_name_get (Attributes.Ptr)); + end Short_Name; + + function Preferred_Byte_Format + (Attributes : in Info) + return Endianness + is + Value : Interfaces.C.int := info_preferred_byte_format_get (Attributes.Ptr); + begin + if Value = sample_little_endian then + return Little_Endian; + elsif Value = sample_big_endian then + return Big_Endian; + elsif Value = sample_native_endian then + return Machine_Native; + else + raise Program_Error; -- libao would be doing weird shit to get here + end if; + end Preferred_Byte_Format; + + function Priority_Level + (Attributes : in Info) + return Positive is + begin + return Positive (info_priority_get (Attributes.Ptr)); + end Priority_Level; + + function Comment + (Attributes : in Info) + return String is + begin + return Interfaces.C.Strings.Value (info_comment_get (Attributes.Ptr)); + end Comment; + + function Option_Count + (Attributes : in Info) + return Natural is + begin + return Natural (info_option_count_get (Attributes.Ptr)); + end Option_Count; + + function Option_Key + (Attributes : in Info; + Index : in Positive) + return String is + begin + return Interfaces.C.Strings.Value + (info_option_key_get (Attributes.Ptr, Interfaces.C.int (Index))); + end Option_Key; + + + + + function Image_Length + (Channel : in Channel_Mnemonic) + return Positive is + begin + case Channel is + when L | R | C | M | X => + return 1; + when CL | CR | BL | BR | BC | SL | SR | A1 | A2 | A3 | A4 => + return 2; + when LFE => + return 3; + end case; + end Image_Length; + + function Image_Length + (Channel_Matrix : in Mnemonic_Array) + return Natural + is + Result : Integer := Channel_Matrix'Length - 1; + begin + if Channel_Matrix'Length = 0 then + return 0; + end if; + for Channel of Channel_Matrix loop + Result := Result + Image_Length (Channel); + end loop; + return Result; + end Image_Length; + + function Image + (Channel_Matrix : in Mnemonic_Array) + return String + is + Result : String (1 .. Image_Length (Channel_Matrix)); + Position : Integer := 1; + begin + for Index in Integer range Channel_Matrix'First .. Channel_Matrix'Last - 1 loop + Result (Position .. Position + Image_Length (Channel_Matrix (Index))) := + Channel_Matrix (Index)'Image & ","; + Position := Position + Image_Length (Channel_Matrix (Index)) + 1; + end loop; + Result (Position .. Result'Last) := Channel_Matrix (Channel_Matrix'Last)'Image; + return Result; + end Image; + + function Create + (Bits, Rate, Channels : in Positive; + Byte_Format : in Endianness; + Channel_Matrix : in Mnemonic_Array) + return Sample_Format is + begin + return This : Sample_Format := (Ada.Finalization.Controlled with + C_Struct => + (Bits => Interfaces.C.int (Bits), + Rate => Interfaces.C.int (Rate), + Channels => Interfaces.C.int (Channels), + Byte_Format => (case Byte_Format is + when Little_Endian => sample_little_endian, + when Big_Endian => sample_big_endian, + when Machine_Native => sample_native_endian), + Matrix => Interfaces.C.Strings.New_String (Image (Channel_Matrix)))); + end Create; + + + + + function Is_Alive + return Boolean is + begin + return Alive_Status; + end Is_Alive; + + procedure Startup is + begin + ao_initialize; + Device_List.Clear; + Alive_Status := True; + end Startup; + + procedure Shutdown is + begin + for Addy of Device_List loop + Do_Close (Addy); + end loop; + ao_shutdown; + Alive_Status := False; + end Shutdown; + + + + + procedure Do_Append + (Ptr : in out System.Address; + Key : in Interfaces.C.char_array; + Value : in Interfaces.C.char_array) + is + Result : Interfaces.C.int; + begin + Result := ao_append_option (Ptr, Key, Value); + if Result = 0 then + raise Storage_Error; + elsif Result /= 1 then + raise Program_Error; + end if; + end Do_Append; + + procedure Append + (This : in out Option_List; + Key : in String; + Value : in String) is + begin + Do_Append (This.Ptr, Interfaces.C.To_C (Key), Interfaces.C.To_C (Value)); + end Append; + + procedure Append_Global_Option + (Key : in String; + Value : in String) + is + Result : Interfaces.C.int; + begin + Result := ao_append_global_option + (Interfaces.C.To_C (Key), + Interfaces.C.To_C (Value)); + if Result = 0 then + raise Storage_Error; + elsif Result /= 1 then + raise Program_Error; + end if; + end Append_Global_Option; + + function Open_Live + (Driver_ID : in Driver_ID_Number; + Format : in Sample_Format; + Options : in Option_List'Class) + return Device + is + Result : System.Address := ao_open_live + (Driver_ID => Interfaces.C.int (Driver_ID), + Format => Format.C_Struct'Address, + Options => Options.Ptr); + My_Errno : Interfaces.C.int; + begin + if Result = System.Null_Address then + My_Errno := get_errno; + if My_Errno = error_no_driver then + raise No_Driver_Error; + elsif My_Errno = error_not_live then + raise Not_Live_Error; + elsif My_Errno = error_bad_option then + raise Bad_Option_Error; + elsif My_Errno = error_open_device then + raise Open_Device_Error; + elsif My_Errno = error_bad_format then + raise Bad_Format_Error; + elsif My_Errno = error_fail then + raise General_Failure; + else + raise Program_Error; + end if; + else + Device_List.Append (Result); + return (Ptr => Result); + end if; + end Open_Live; + + function Open_File + (Driver_ID : in Driver_ID_Number; + Filename : in String; + Format : in Sample_Format; + Options : in Option_List'Class; + Overwrite : in Boolean := False) + return Device + is + Result : System.Address := ao_open_file + (Driver_ID => Interfaces.C.int (Driver_ID), + Filename => Interfaces.C.To_C (Filename), + Overwrite => Boolean'Pos (Overwrite), + Format => Format.C_Struct'Address, + Options => Options.Ptr); + My_Errno : Interfaces.C.int; + begin + if Result = System.Null_Address then + My_Errno := get_errno; + if My_Errno = error_no_driver then + raise No_Driver_Error; + elsif My_Errno = error_not_file then + raise Not_File_Error; + elsif My_Errno = error_bad_option then + raise Bad_Option_Error; + elsif My_Errno = error_open_file then + raise Open_File_Error; + elsif My_Errno = error_file_exists then + raise File_Exists_Error; + elsif My_Errno = error_bad_format then + raise Bad_Format_Error; + elsif My_Errno = error_fail then + raise General_Failure; + else + raise Program_Error; + end if; + else + Device_List.Append (Result); + return (Ptr => Result); + end if; + end Open_File; + + procedure Play + (Output_Device : in Device; + Samples : in Data_Buffer) + is + Result : Interfaces.C.int := ao_play + (Output_Device => Output_Device.Ptr, + Samples => Interfaces.C.To_C (Item => String (Samples), Append_Nul => False), + Num_Bytes => Interfaces.Unsigned_32 (Samples'Length)); + begin + if Result = 0 then + raise General_Failure; + end if; + end Play; + + procedure Do_Close + (Ptr : in System.Address) + is + Result : Interfaces.C.int := ao_close (Ptr); + begin + if Result = 0 then + raise Close_Device_Error; + elsif Result /= 1 then + raise Program_Error; + end if; + end Do_Close; + + procedure Close + (Output_Device : in out Device) is + begin + for Index in reverse Integer range Device_List.First_Index .. Device_List.Last_Index loop + if Device_List.Element (Index) = Output_Device.Ptr then + Device_List.Delete (Index); + end if; + end loop; + Do_Close (Output_Device.Ptr); + end Close; + + + + + function Driver_ID + (Short_Name : in String) + return Driver_ID_Number + is + Result : Interfaces.C.int; + begin + Result := ao_driver_id (Interfaces.C.To_C (Short_Name)); + if Result = -1 then + raise No_Driver_Error; + elsif Result < 0 then + raise Program_Error; + end if; + return Driver_ID_Number (Result); + end Driver_ID; + + function Default_Driver_ID + return Driver_ID_Number + is + Result : Interfaces.C.int; + begin + Result := ao_default_driver_id; + if Result = -1 then + raise No_Device_Error; + elsif Result < 0 then + raise Program_Error; + end if; + return Driver_ID_Number (Result); + end Default_Driver_ID; + + function Driver_Info + (Ident : in Driver_ID_Number) + return Info + is + Result : System.Address; + begin + Result := ao_driver_info (Interfaces.C.int (Ident)); + if Result = System.Null_Address then + raise No_Driver_Error; + else + return (Ptr => Result); + end if; + end Driver_Info; + + function Driver_Info_List + return Info_Array + is + Count : Interfaces.C.int; + Carr : System.Address; + begin + Carr := ao_driver_info_list (Count); + return Actual : Info_Array (1 .. Positive (Count)) do + for N in Integer range Actual'First .. Actual'Last loop + Actual (N) := (Ptr => info_item_get (Carr, Interfaces.C.int (N))); + end loop; + end return; + end Driver_Info_List; + + function File_Extension + (Ident : in Driver_ID_Number) + return String + is + Result : Interfaces.C.Strings.chars_ptr := ao_file_extension (Interfaces.C.int (Ident)); + begin + if Result = Interfaces.C.Strings.Null_Ptr then + return ""; + else + return Interfaces.C.Strings.Value (Result); + end if; + end File_Extension; + + + + + function Is_Big_Endian + return Boolean is + begin + case ao_is_big_endian is + when 1 => return True; + when 0 => return False; + when others => raise Program_Error; + end case; + end Is_Big_Endian; + + +end Libao; + + diff --git a/src/libao.ads b/src/libao.ads new file mode 100644 index 0000000..1bdb142 --- /dev/null +++ b/src/libao.ads @@ -0,0 +1,319 @@ + + +-- Programmed by Jedidiah Barber +-- Released into the public domain + + +private with + + Ada.Finalization, + Ada.Containers.Vectors, + Interfaces.C.Strings, + System; + + +package Libao is + + + ----------------------- + -- Data Structures -- + ----------------------- + + type Driver_ID_Number is new Natural; + + + type Data_Buffer is new String; + + + type Device is private; + + + type Info is tagged private; + type Info_Array is array (Positive range <>) of Info; + type Output_Kind is (Live_Output, File_Output); + type Endianness is (Little_Endian, Big_Endian, Machine_Native); + + function Kind + (Attributes : in Info) + return Output_Kind + with Pre => Is_Alive; + + function Name + (Attributes : in Info) + return String + with Pre => Is_Alive; + + function Short_Name + (Attributes : in Info) + return String + with Pre => Is_Alive; + + function Preferred_Byte_Format + (Attributes : in Info) + return Endianness + with Pre => Is_Alive; + + function Priority_Level + (Attributes : in Info) + return Positive + with Pre => Is_Alive; + + function Comment + (Attributes : in Info) + return String + with Pre => Is_Alive; + + function Option_Count + (Attributes : in Info) + return Natural + with Pre => Is_Alive; + + function Option_Key + (Attributes : in Info; + Index : in Positive) + return String + with Pre => Is_Alive; + + + type Option_List is tagged private; + + Empty_Options : constant Option_List; + + + type Sample_Format is private; + type Channel_Mnemonic is (L, R, C, M, CL, CR, BL, BR, BC, SL, SR, LFE, A1, A2, A3, A4, X); + type Mnemonic_Array is array (Positive range <>) of Channel_Mnemonic; + + function Create + (Bits, Rate, Channels : in Positive; + Byte_Format : in Endianness; + Channel_Matrix : in Mnemonic_Array) + return Sample_Format; + + Stereo : constant Mnemonic_Array := (L, R); + Quadraphonic : constant Mnemonic_Array := (L, R, BL, BR); + + + + + ------------------ + -- Exceptions -- + ------------------ + + -- May be raised by Open_Live, Open_File, Driver_ID, Driver_Info + No_Driver_Error : exception; + + -- May be raised by Open_File + Not_File_Error : exception; + + -- May be raised by Open_Live + Not_Live_Error : exception; + + -- May be raised by Open_Live, Open_File + Bad_Option_Error : exception; + + -- May be raised by Open_Live + Open_Device_Error : exception; + + -- May be raised by Shutdown, Close + Close_Device_Error : exception; + + -- May be raised by Default_Driver_ID + No_Device_Error : exception; + + -- May be raised by Open_File + Open_File_Error : exception; + + -- May be raised by Open_File + File_Exists_Error : exception; + + -- Documentation lacking, but presumably may be raised by Open_Live, Open_File + Bad_Format_Error : exception; + + -- May be raised by Open_Live, Open_File, Play + General_Failure : exception; + + -- Storage_Error may be raised by Append, Append_Global_Option + -- Program_Error may be raised if libao in general does something out of spec + + + + + ------------------------------ + -- Library Setup/Teardown -- + ------------------------------ + + function Is_Alive + return Boolean; + + procedure Startup + with Pre => not Is_Alive, + Post => Is_Alive; + + procedure Shutdown + with Pre => Is_Alive, + Post => not Is_Alive; + + + + + -------------------------------------- + -- Device Setup/Playback/Teardown -- + -------------------------------------- + + procedure Append + (This : in out Option_List; + Key : in String; + Value : in String) + with Pre => Is_Alive; + + procedure Append_Global_Option + (Key : in String; + Value : in String) + with Pre => Is_Alive; + + function Open_Live + (Driver_ID : in Driver_ID_Number; + Format : in Sample_Format; + Options : in Option_List'Class) + return Device + with Pre => Is_Alive; + + function Open_File + (Driver_ID : in Driver_ID_Number; + Filename : in String; + Format : in Sample_Format; + Options : in Option_List'Class; + Overwrite : in Boolean := False) + return Device + with Pre => Is_Alive; + + procedure Play + (Output_Device : in Device; + Samples : in Data_Buffer) + with Pre => Is_Alive; + + procedure Close + (Output_Device : in out Device) + with Pre => Is_Alive; + + + + + -------------------------- + -- Driver Information -- + -------------------------- + + function Driver_ID + (Short_Name : in String) + return Driver_ID_Number + with Pre => Is_Alive; + + function Default_Driver_ID + return Driver_ID_Number + with Pre => Is_Alive; + + function Driver_Info + (Ident : in Driver_ID_Number) + return Info + with Pre => Is_Alive; + + function Driver_Info_List + return Info_Array + with Pre => Is_Alive; + + function File_Extension + (Ident : in Driver_ID_Number) + return String + with Pre => Is_Alive; + + + + + --------------------- + -- Miscellaneous -- + --------------------- + + function Is_Big_Endian + return Boolean + with Pre => Is_Alive; + + +private + + + pragma Linker_Options ("-lao"); + pragma Inline (Is_Alive); + + + + + procedure Do_Append + (Ptr : in out System.Address; + Key : in Interfaces.C.char_array; + Value : in Interfaces.C.char_array); + + procedure Do_Close + (Ptr : in System.Address); + + + + + type Device is record + Ptr : System.Address; + end record; + + + type Info is tagged record + Ptr : System.Address; + end record; + + + type Option_List is new Ada.Finalization.Controlled with record + Ptr : System.Address := System.Null_Address; + end record; + + overriding procedure Adjust + (This : in out Option_List); + + overriding procedure Finalize + (This : in out Option_List); + + Empty_Options : constant Option_List := + (Ada.Finalization.Controlled with Ptr => System.Null_Address); + + + type C_Sample_Format is record + Bits : Interfaces.C.int; + Rate : Interfaces.C.int; + Channels : Interfaces.C.int; + Byte_Format : Interfaces.C.int; + Matrix : Interfaces.C.Strings.chars_ptr; + end record with Convention => C; + + type Sample_Format is new Ada.Finalization.Controlled with record + C_Struct : C_Sample_Format; + end record; + + overriding procedure Adjust + (This : in out Sample_Format); + + overriding procedure Finalize + (This : in out Sample_Format); + + + + + Alive_Status : Boolean := False; + + package Address_Vectors is new Ada.Containers.Vectors + (Index_Type => Positive, + Element_Type => System.Address, + "=" => System."="); + + Device_List : Address_Vectors.Vector := Address_Vectors.Empty_Vector; + + +end Libao; + + -- cgit