From 734544d457cb098c1d434798528670e0bf156cdb Mon Sep 17 00:00:00 2001 From: Jedidiah Barber Date: Thu, 20 Jul 2023 18:53:27 +1200 Subject: Completed command API --- src/libsndfile-commands.adb | 608 ++++++++++++++++++++++++++++++-------------- 1 file changed, 420 insertions(+), 188 deletions(-) (limited to 'src/libsndfile-commands.adb') diff --git a/src/libsndfile-commands.adb b/src/libsndfile-commands.adb index 0d3f767..364fa3e 100644 --- a/src/libsndfile-commands.adb +++ b/src/libsndfile-commands.adb @@ -135,12 +135,29 @@ package body Libsndfile.Commands is sfc_set_channel_map_info : constant Interfaces.C.int; pragma Import (C, sfc_set_channel_map_info, "sfc_set_channel_map_info"); - -- ... + sfc_get_cart_info : constant Interfaces.C.int; + pragma Import (C, sfc_get_cart_info, "sfc_get_cart_info"); + + sfc_set_cart_info : constant Interfaces.C.int; + pragma Import (C, sfc_set_cart_info, "sfc_set_cart_info"); + + sfc_get_loop_info : constant Interfaces.C.int; + pragma Import (C, sfc_get_loop_info, "sfc_get_loop_info"); + + sfc_get_instrument : constant Interfaces.C.int; + pragma Import (C, sfc_get_instrument, "sfc_get_instrument"); + + sfc_set_instrument : constant Interfaces.C.int; + pragma Import (C, sfc_set_instrument, "sfc_set_instrument"); sfc_get_cue_count : constant Interfaces.C.int; pragma Import (C, sfc_get_cue_count, "sfc_get_cue_count"); - -- ... + sfc_get_cue : constant Interfaces.C.int; + pragma Import (C, sfc_get_cue, "sfc_get_cue"); + + sfc_set_cue : constant Interfaces.C.int; + pragma Import (C, sfc_set_cue, "sfc_set_cue"); sfc_rf64_auto_downgrade : constant Interfaces.C.int; pragma Import (C, sfc_rf64_auto_downgrade, "sfc_rf64_auto_downgrade"); @@ -165,6 +182,19 @@ package body Libsndfile.Commands is pragma Import (C, sf_ambisonic_b_format, "sf_ambisonic_b_format"); + sf_loop_none : constant Interfaces.C.int; + pragma Import (C, sf_loop_none, "sf_loop_none"); + + sf_loop_forward : constant Interfaces.C.int; + pragma Import (C, sf_loop_forward, "sf_loop_forward"); + + sf_loop_backward : constant Interfaces.C.int; + pragma Import (C, sf_loop_backward, "sf_loop_backward"); + + sf_loop_alternating : constant Interfaces.C.int; + pragma Import (C, sf_loop_alternating, "sf_loop_alternating"); + + sf_bitrate_mode_constant : constant Interfaces.C.int; pragma Import (C, sf_bitrate_mode_constant, "sf_bitrate_mode_constant"); @@ -219,23 +249,59 @@ package body Libsndfile.Commands is function asfc_get_embed_file_info (File : in System.Address; - Info : in out Embedded_Info) + Info : in out C_Embedded_Info) return Interfaces.C.int; pragma Import (C, asfc_get_embed_file_info, "asfc_get_embed_file_info"); - ---------------------------------- - -- Data Structure Subprograms -- - ---------------------------------- + ------------------------ + -- Internal Utility -- + ------------------------ + + function To_Ada + (Num : in Interfaces.C.int) + return Loop_Mode is + begin + if Num = sf_loop_none then + return No_Loop; + elsif Num = sf_loop_forward then + return Loop_Forward; + elsif Num = sf_loop_backward then + return Loop_Backward; + elsif Num = sf_loop_alternating then + return Loop_Alternating; + else + raise Program_Error; + end if; + end To_Ada; + + function To_C + (Enum : in Loop_Mode) + return Interfaces.C.int is + begin + case Enum is + when No_Loop => return sf_loop_none; + when Loop_Forward => return sf_loop_forward; + when Loop_Backward => return sf_loop_backward; + when Loop_Alternating => return sf_loop_alternating; + end case; + end To_C; + + + + + --------------------------------- + -- Data Types and Structures -- + --------------------------------- function Major (Info : in Format_Info) return Major_Format is Raw : Interfaces.Unsigned_32 := - Interfaces.Unsigned_32 (Info.My_Format) and sf_format_typemask; + Interfaces.Unsigned_32 (Info.C_Data.My_Format) and sf_format_typemask; begin return To_Major (Interfaces.C.int (Raw)); end Major; @@ -245,7 +311,7 @@ package body Libsndfile.Commands is return Minor_Format is Raw : Interfaces.Unsigned_32 := - Interfaces.Unsigned_32 (Info.My_Format) and sf_format_submask; + Interfaces.Unsigned_32 (Info.C_Data.My_Format) and sf_format_submask; begin return To_Minor (Interfaces.C.int (Raw)); end Minor; @@ -255,7 +321,7 @@ package body Libsndfile.Commands is return Endianness is Raw : Interfaces.Unsigned_32 := - Interfaces.Unsigned_32 (Info.My_Format) and sf_format_endmask; + Interfaces.Unsigned_32 (Info.C_Data.My_Format) and sf_format_endmask; begin return To_Endian (Interfaces.C.int (Raw)); end Endian; @@ -264,172 +330,76 @@ package body Libsndfile.Commands is (Info : in Format_Info) return String is begin - return Interfaces.C.Strings.Value (Info.My_Name); + return Interfaces.C.Strings.Value (Info.C_Data.My_Name); end Name; function Extension (Info : in Format_Info) return String is begin - return Interfaces.C.Strings.Value (Info.My_Extension); + return Interfaces.C.Strings.Value (Info.C_Data.My_Extension); end Extension; - function Offset - (Info : in Embedded_Info) - return Count_Type is - begin - return Count_Type (Info.My_Offset); - end Offset; - - function Length - (Info : in Embedded_Info) - return Count_Type is - begin - return Count_Type (Info.My_Length); - end Length; - - function Create - (Description : in String; - Originator : in String; - Originator_Reference : in String; - Origination_Date : in String; - Origination_Time : in String; - Time_Reference_Low : in Interfaces.Unsigned_32; - Time_Reference_High : in Interfaces.Unsigned_32; - Version : in Short_Integer; - Umid : in String; - Reserved : in String; - Coding_History_Size : in Interfaces.Unsigned_32; - Coding_History : in String) - return Broadcast_Info - is - Buffer : String (1 .. 256); - - function Pad - (Input : in String; - Size : in Natural) - return String is - begin - Ada.Strings.Fixed.Move (Source => Input, Target => Buffer, Pad => Character'Val (0)); - return Buffer (1 .. Size); - end Pad; - begin - return - (My_Description => Interfaces.C.To_C (Pad (Description, 256), False), - My_Originator => Interfaces.C.To_C (Pad (Originator, 32), False), - My_Originator_Reference => Interfaces.C.To_C (Pad (Originator_Reference, 32), False), - My_Origination_Date => Interfaces.C.To_C (Pad (Origination_Date, 10), False), - My_Origination_Time => Interfaces.C.To_C (Pad (Origination_Time, 8), False), - My_Time_Reference_Low => Interfaces.C.unsigned (Time_Reference_Low), - My_Time_Reference_High => Interfaces.C.unsigned (Time_Reference_High), - My_Version => Interfaces.C.short (Version), - My_Umid => Interfaces.C.To_C (Pad (Umid, 64), False), - My_Reserved => Interfaces.C.To_C (Pad (Reserved, 190), False), - My_Coding_History_Size => Interfaces.C.unsigned (Coding_History_Size), - My_Coding_History => Interfaces.C.To_C (Pad (Coding_History, 256), False)); + (Base : in Instrument_Data; + Repeats : in Loop_Data_Array) + return Instrument_Info is + begin + return Result : Instrument_Info do + Result.C_Data.My_Gain := Interfaces.C.int (Base.Gain); + Result.C_Data.My_Basenote := Interfaces.C.char (Base.Basenote); + Result.C_Data.My_Detune := Interfaces.C.char (Base.Detune); + Result.C_Data.My_Velocity_Lo := Interfaces.C.char (Base.Velocity_Low); + Result.C_Data.My_Velocity_Hi := Interfaces.C.char (Base.Velocity_High); + Result.C_Data.My_Key_Lo := Interfaces.C.char (Base.Key_Low); + Result.C_Data.My_Key_Hi := Interfaces.C.char (Base.Key_High); + Result.C_Data.My_Loop_Count := Repeats'Length; + for Index in Repeats'Range loop + Result.C_Data.My_Loops (Index).My_Mode := + To_C (Repeats (Index).Mode); + Result.C_Data.My_Loops (Index).My_Start := + Interfaces.C.unsigned (Repeats (Index).Start); + Result.C_Data.My_Loops (Index).My_End := + Interfaces.C.unsigned (Repeats (Index).Finish); + Result.C_Data.My_Loops (Index).My_Count := + Interfaces.C.unsigned (Repeats (Index).Count); + end loop; + end return; end Create; - function Description - (Info : in Broadcast_Info) - return String is - begin - return Interfaces.C.To_Ada - (Info.My_Description, - Interfaces.C.Is_Nul_Terminated (Info.My_Description)); - end Description; - - function Originator - (Info : in Broadcast_Info) - return String is - begin - return Interfaces.C.To_Ada - (Info.My_Originator, - Interfaces.C.Is_Nul_Terminated (Info.My_Originator)); - end Originator; - - function Originator_Reference - (Info : in Broadcast_Info) - return String is - begin - return Interfaces.C.To_Ada - (Info.My_Originator_Reference, - Interfaces.C.Is_Nul_Terminated (Info.My_Originator_Reference)); - end Originator_Reference; - - function Origination_Date - (Info : in Broadcast_Info) - return String is - begin - return Interfaces.C.To_Ada - (Info.My_Origination_Date, - Interfaces.C.Is_Nul_Terminated (Info.My_Origination_Date)); - end Origination_Date; - - function Origination_Time - (Info : in Broadcast_Info) - return String is - begin - return Interfaces.C.To_Ada - (Info.My_Origination_Time, - Interfaces.C.Is_Nul_Terminated (Info.My_Origination_Time)); - end Origination_Time; - - function Time_Reference_Low - (Info : in Broadcast_Info) - return Interfaces.Unsigned_32 is - begin - return Interfaces.Unsigned_32 (Info.My_Time_Reference_Low); - end Time_Reference_Low; - - function Time_Reference_High - (Info : in Broadcast_Info) - return Interfaces.Unsigned_32 is - begin - return Interfaces.Unsigned_32 (Info.My_Time_Reference_High); - end Time_Reference_High; - - function Version - (Info : in Broadcast_Info) - return Short_Integer is - begin - return Short_Integer (Info.My_Version); - end Version; - - function Umid - (Info : in Broadcast_Info) - return String is - begin - return Interfaces.C.To_Ada - (Info.My_Umid, - Interfaces.C.Is_Nul_Terminated (Info.My_Umid)); - end Umid; - - function Reserved - (Info : in Broadcast_Info) - return String is - begin - return Interfaces.C.To_Ada - (Info.My_Reserved, - Interfaces.C.Is_Nul_Terminated (Info.My_Reserved)); - end Reserved; - - function Coding_History_Size - (Info : in Broadcast_Info) - return Interfaces.Unsigned_32 is - begin - return Interfaces.Unsigned_32 (Info.My_Coding_History_Size); - end Coding_History_Size; - - function Coding_History - (Info : in Broadcast_Info) - return String is - begin - return Interfaces.C.To_Ada - (Info.My_Coding_History, - Interfaces.C.Is_Nul_Terminated (Info.My_Coding_History)); - end Coding_History; + function Base + (Info : in Instrument_Info) + return Instrument_Data is + begin + return Result : Instrument_Data do + Result.Gain := Integer (Info.C_Data.My_Gain); + Result.Basenote := Character (Info.C_Data.My_Basenote); + Result.Detune := Character (Info.C_Data.My_Detune); + Result.Velocity_Low := Character (Info.C_Data.My_Velocity_Lo); + Result.Velocity_High := Character (Info.C_Data.My_Velocity_Hi); + Result.Key_Low := Character (Info.C_Data.My_Key_Lo); + Result.Key_High := Character (Info.C_Data.My_Key_Hi); + end return; + end Base; + + function Repeats + (Info : in Instrument_Info) + return Loop_Data_Array is + begin + return Result : Loop_Data_Array (1 .. Integer (Info.C_Data.My_Loop_Count)) do + for Index in Result'Range loop + Result (Index).Mode := + To_Ada (Info.C_Data.My_Loops (Index).My_Mode); + Result (Index).Start := + Interfaces.Unsigned_32 (Info.C_Data.My_Loops (Index).My_Start); + Result (Index).Finish := + Interfaces.Unsigned_32 (Info.C_Data.My_Loops (Index).My_End); + Result (Index).Count := + Interfaces.Unsigned_32 (Info.C_Data.My_Loops (Index).My_Count); + end loop; + end return; + end Repeats; @@ -714,7 +684,7 @@ package body Libsndfile.Commands is (Index : in Positive) return Format_Info is - Result : Format_Info := + Raw : C_Format_Info := (My_Format => Interfaces.C.int (Index) - 1, My_Name => Interfaces.C.Strings.Null_Ptr, My_Extension => Interfaces.C.Strings.Null_Ptr); @@ -723,12 +693,12 @@ package body Libsndfile.Commands is Code := sf_command (System.Null_Address, sfc_get_simple_format, - Result'Address, - Format_Info'Size / Interfaces.C.CHAR_BIT); + Raw'Address, + C_Format_Info'Size / Interfaces.C.CHAR_BIT); if Code /= 0 then raise Command_Error; else - return Result; + return (C_Data => Raw); end if; end Get_Simple_Format; @@ -736,7 +706,7 @@ package body Libsndfile.Commands is (Format : in Interfaces.C.int) return Format_Info is - Result : Format_Info := + Raw : C_Format_Info := (My_Format => Format, My_Name => Interfaces.C.Strings.Null_Ptr, My_Extension => Interfaces.C.Strings.Null_Ptr); @@ -745,12 +715,12 @@ package body Libsndfile.Commands is Code := sf_command (System.Null_Address, sfc_get_format_info, - Result'Address, - Format_Info'Size / Interfaces.C.CHAR_BIT); + Raw'Address, + C_Format_Info'Size / Interfaces.C.CHAR_BIT); if Code /= 0 then raise Command_Error; else - return Result; + return (C_Data => Raw); end if; end Do_Get_Format_Info; @@ -785,7 +755,7 @@ package body Libsndfile.Commands is (Index : in Positive) return Format_Info is - Result : Format_Info := + Raw : C_Format_Info := (My_Format => Interfaces.C.int (Index) - 1, My_Name => Interfaces.C.Strings.Null_Ptr, My_Extension => Interfaces.C.Strings.Null_Ptr); @@ -794,12 +764,12 @@ package body Libsndfile.Commands is Code := sf_command (System.Null_Address, sfc_get_format_major, - Result'Address, - Format_Info'Size / Interfaces.C.CHAR_BIT); + Raw'Address, + C_Format_Info'Size / Interfaces.C.CHAR_BIT); if Code /= 0 then raise Command_Error; else - return Result; + return (C_Data => Raw); end if; end Get_Format_Major; @@ -820,7 +790,7 @@ package body Libsndfile.Commands is (Index : in Positive) return Format_Info is - Result : Format_Info := + Raw : C_Format_Info := (My_Format => Interfaces.C.int (Index) - 1, My_Name => Interfaces.C.Strings.Null_Ptr, My_Extension => Interfaces.C.Strings.Null_Ptr); @@ -829,12 +799,12 @@ package body Libsndfile.Commands is Code := sf_command (System.Null_Address, sfc_get_format_subtype, - Result'Address, - Format_Info'Size / Interfaces.C.CHAR_BIT); + Raw'Address, + C_Format_Info'Size / Interfaces.C.CHAR_BIT); if Code /= 0 then raise Command_Error; else - return Result; + return (C_Data => Raw); end if; end Get_Format_Subtype; @@ -937,14 +907,16 @@ package body Libsndfile.Commands is (File : in Sound_File) return Embedded_Info is - Info : Embedded_Info; + Raw : C_Embedded_Info; Code : Interfaces.C.int; begin - Code := asfc_get_embed_file_info (File.Ptr, Info); + Code := asfc_get_embed_file_info (File.Ptr, Raw); if Code /= 0 then raise Command_Error; else - return Info; + return + (Offset => Count_Type (Raw.My_Offset), + Length => Count_Type (Raw.My_Length)); end if; end Get_Embedded_File_Info; @@ -1097,16 +1069,30 @@ package body Libsndfile.Commands is (File : in Sound_File) return Broadcast_Info is - Result : Broadcast_Info; + Raw : C_Broadcast_Info; Code : Interfaces.C.int; begin Code := sf_command (File.Ptr, sfc_get_broadcast_info, - Result'Address, - Broadcast_Info'Size / Interfaces.C.CHAR_BIT); + Raw'Address, + C_Broadcast_Info'Size / Interfaces.C.CHAR_BIT); if Code = sf_true then - return Result; + return Result : Broadcast_Info do + Result.Description := Interfaces.C.To_Ada (Raw.My_Description, False); + Result.Originator := Interfaces.C.To_Ada (Raw.My_Originator, False); + Result.Originator_Reference := + Interfaces.C.To_Ada (Raw.My_Originator_Reference, False); + Result.Origination_Date := Interfaces.C.To_Ada (Raw.My_Origination_Date, False); + Result.Origination_Time := Interfaces.C.To_Ada (Raw.My_Origination_Time, False); + Result.Time_Reference_Low := Interfaces.Unsigned_32 (Raw.My_Time_Reference_Low); + Result.Time_Reference_High := Interfaces.Unsigned_32 (Raw.My_Time_Reference_High); + Result.Version := Short_Integer (Raw.My_Version); + Result.Umid := Interfaces.C.To_Ada (Raw.My_Umid, False); + Result.Reserved := Interfaces.C.To_Ada (Raw.My_Reserved, False); + Result.Coding_History_Size := Interfaces.Unsigned_32 (Raw.My_Coding_History_Size); + Result.Coding_History := Interfaces.C.To_Ada (Raw.My_Coding_History, False); + end return; elsif Code = sf_false then raise Command_Error; else @@ -1118,13 +1104,26 @@ package body Libsndfile.Commands is (File : in Sound_File; Value : in Broadcast_Info) is + C_Data : C_Broadcast_Info := + (My_Description => Interfaces.C.To_C (Value.Description, False), + My_Originator => Interfaces.C.To_C (Value.Originator, False), + My_Originator_Reference => Interfaces.C.To_C (Value.Originator_Reference, False), + My_Origination_Date => Interfaces.C.To_C (Value.Origination_Date, False), + My_Origination_Time => Interfaces.C.To_C (Value.Origination_Time, False), + My_Time_Reference_Low => Interfaces.C.unsigned (Value.Time_Reference_Low), + My_Time_Reference_High => Interfaces.C.unsigned (Value.Time_Reference_High), + My_Version => Interfaces.C.short (Value.Version), + My_Umid => Interfaces.C.To_C (Value.Umid, False), + My_Reserved => Interfaces.C.To_C (Value.Reserved, False), + My_Coding_History_Size => Interfaces.C.unsigned (Value.Coding_History_Size), + My_Coding_History => Interfaces.C.To_C (Value.Coding_History, False)); Code : Interfaces.C.int; begin Code := sf_command (File.Ptr, sfc_set_broadcast_info, - Value'Address, - Broadcast_Info'Size / Interfaces.C.CHAR_BIT); + C_Data'Address, + C_Broadcast_Info'Size / Interfaces.C.CHAR_BIT); if Code = sf_false then raise Command_Error; elsif Code /= sf_true then @@ -1182,6 +1181,171 @@ package body Libsndfile.Commands is end if; end Set_Channel_Map_Info; + function Get_Cart_Info + (File : in Sound_File) + return Cart_Info + is + Raw : C_Cart_Info; + Code : Interfaces.C.int; + begin + Code := sf_command + (File.Ptr, + sfc_get_cart_info, + Raw'Address, + Raw'Size / Interfaces.C.CHAR_BIT); + if Code = sf_false then + raise Command_Error; + elsif Code = sf_true then + return Result : Cart_Info (Natural (Raw.My_Tag_Text_Size)) do + Result.Version := Interfaces.C.To_Ada (Raw.My_Version, False); + Result.Title := Interfaces.C.To_Ada (Raw.My_Title, False); + Result.Artist := Interfaces.C.To_Ada (Raw.My_Artist, False); + Result.Cut_ID := Interfaces.C.To_Ada (Raw.My_Cut_ID, False); + Result.Client_ID := Interfaces.C.To_Ada (Raw.My_Client_ID, False); + Result.Category := Interfaces.C.To_Ada (Raw.My_Category, False); + Result.Classification := Interfaces.C.To_Ada (Raw.My_Classification, False); + Result.Out_Cue := Interfaces.C.To_Ada (Raw.My_Out_Cue, False); + Result.Start_Date := Interfaces.C.To_Ada (Raw.My_Start_Date, False); + Result.Start_Time := Interfaces.C.To_Ada (Raw.My_Start_Time, False); + Result.End_Date := Interfaces.C.To_Ada (Raw.My_End_Date, False); + Result.End_Time := Interfaces.C.To_Ada (Raw.My_End_Time, False); + Result.Producer_App_ID := Interfaces.C.To_Ada (Raw.My_Producer_App_ID, False); + Result.Producer_App_Version := + Interfaces.C.To_Ada (Raw.My_Producer_App_Version, False); + Result.User_Defined := Interfaces.C.To_Ada (Raw.My_User_Def, False); + Result.Level_Reference := Long_Integer (Raw.My_Level_Reference); + for Index in Result.Post_Timers'Range loop + Result.Post_Timers (Index).Usage := + Interfaces.C.To_Ada (Raw.My_Post_Timers (Index).My_Usage, False); + Result.Post_Timers (Index).Value := Raw.My_Post_Timers (Index).My_Value; + end loop; + Result.Reserved := Interfaces.C.To_Ada (Raw.My_Reserved, False); + Result.URL := Interfaces.C.To_Ada (Raw.My_URL, False); + Result.Tag_Text := Interfaces.C.To_Ada + (Raw.My_Tag_Text (1 .. Interfaces.C.size_t (Raw.My_Tag_Text_Size)), False); + end return; + else + raise Program_Error; + end if; + end Get_Cart_Info; + + procedure Set_Cart_Info + (File : in Sound_File; + Info : in Cart_Info) + is + C_Data : C_Cart_Info := + (My_Version => Interfaces.C.To_C (Info.Version, False), + My_Title => Interfaces.C.To_C (Info.Title, False), + My_Artist => Interfaces.C.To_C (Info.Artist, False), + My_Cut_ID => Interfaces.C.To_C (Info.Cut_ID, False), + My_Client_ID => Interfaces.C.To_C (Info.Client_ID, False), + My_Category => Interfaces.C.To_C (Info.Category, False), + My_Classification => Interfaces.C.To_C (Info.Classification, False), + My_Out_Cue => Interfaces.C.To_C (Info.Out_Cue, False), + My_Start_Date => Interfaces.C.To_C (Info.Start_Date, False), + My_Start_Time => Interfaces.C.To_C (Info.Start_Time, False), + My_End_Date => Interfaces.C.To_C (Info.End_Date, False), + My_End_Time => Interfaces.C.To_C (Info.End_Time, False), + My_Producer_App_ID => Interfaces.C.To_C (Info.Producer_App_ID, False), + My_Producer_App_Version => Interfaces.C.To_C (Info.Producer_App_Version, False), + My_User_Def => Interfaces.C.To_C (Info.User_Defined, False), + My_Level_Reference => Interfaces.C.long (Info.Level_Reference), + My_Post_Timers => (others => (" ", 0)), + My_Reserved => Interfaces.C.To_C (Info.Reserved, False), + My_URL => Interfaces.C.To_C (Info.URL, False), + My_Tag_Text_Size => Interfaces.C.unsigned (Info.Tag_Size), + My_Tag_Text => (others => ' ')); + Code : Interfaces.C.int; + begin + for Index in C_Data.My_Post_Timers'Range loop + C_Data.My_Post_Timers (Index).My_Usage := Interfaces.C.To_C + (Info.Post_Timers (Index).Usage, False); + C_Data.My_Post_Timers (Index).My_Value := Info.Post_Timers (Index).Value; + end loop; + C_Data.My_Tag_Text (1 .. Interfaces.C.size_t (C_Data.My_Tag_Text_Size)) := + Interfaces.C.To_C (Info.Tag_Text, False); + Code := sf_command + (File.Ptr, + sfc_set_cart_info, + C_Data'Address, + C_Data'Size / Interfaces.C.CHAR_BIT); + if Code = sf_false then + raise Command_Error; + elsif Code /= sf_true then + raise Program_Error; + end if; + end Set_Cart_Info; + + function Get_Loop_Info + (File : in Sound_File) + return Loop_Info + is + Raw : C_Loop_Info; + Code : Interfaces.C.int; + begin + Code := sf_command + (File.Ptr, + sfc_get_loop_info, + Raw'Address, + C_Loop_Info'Size / Interfaces.C.CHAR_BIT); + if Code = sf_false then + raise Command_Error; + elsif Code = sf_true then + return Result : Loop_Info do + Result.Time_Sig_Num := Short_Integer (Raw.My_Time_Sig_Num); + Result.Time_Sig_Den := Short_Integer (Raw.My_Time_Sig_Den); + Result.Mode := To_Ada (Raw.My_Loop_Mode); + Result.Beats := Positive (Raw.My_Num_Beats); + Result.BPM := Beats_Per_Minute (Raw.My_BPM); + Result.Root_Key := MIDI_Note (Raw.My_Root_Key); + for Index in Result.Future'Range loop + Result.Future (Index) := Integer (Raw.My_Future (Index)); + end loop; + end return; + else + raise Program_Error; + end if; + end Get_Loop_Info; + + function Get_Instrument + (File : in Sound_File) + return Instrument_Info + is + Result : Instrument_Info; + Code : Interfaces.C.int; + begin + Code := sf_command + (File.Ptr, + sfc_get_instrument, + Result.C_Data'Address, + C_Instrument_Info'Size / Interfaces.C.CHAR_BIT); + if Code = sf_false then + raise Command_Error; + elsif Code = sf_true then + return Result; + else + raise Program_Error; + end if; + end Get_Instrument; + + procedure Set_Instrument + (File : in Sound_File; + Info : in Instrument_Info) + is + Code : Interfaces.C.int; + begin + Code := sf_command + (File.Ptr, + sfc_set_instrument, + Info.C_Data'Address, + C_Instrument_Info'Size / Interfaces.C.CHAR_BIT); + if Code = sf_false then + raise Command_Error; + elsif Code /= sf_true then + raise Program_Error; + end if; + end Set_Instrument; + function Get_Cue_Count (File : in Sound_File) return Interfaces.Unsigned_32 @@ -1203,6 +1367,74 @@ package body Libsndfile.Commands is end if; end Get_Cue_Count; + function Get_Cue + (File : in Sound_File) + return Cue_Marker_Array + is + Raw : C_Cue_Info; + Code : Interfaces.C.int; + begin + Code := sf_command + (File.Ptr, + sfc_get_cue, + Raw'Address, + C_Cue_Info'Size / Interfaces.C.CHAR_BIT); + if Code = sf_false then + raise Command_Error; + elsif Code = sf_true then + return Result : Cue_Marker_Array (1 .. Integer (Raw.My_Cue_Count)) do + for Index in Result'Range loop + Result (Index).Index := Integer (Raw.My_Cue_Points (Index).My_Indx); + Result (Index).Position := Raw.My_Cue_Points (Index).My_Position; + Result (Index).FCC_Chunk := Integer (Raw.My_Cue_Points (Index).My_FCC_Chunk); + Result (Index).Chunk_Start := + Integer (Raw.My_Cue_Points (Index).My_Chunk_Start); + Result (Index).Block_Start := + Integer (Raw.My_Cue_Points (Index).My_Block_Start); + Result (Index).Sample_Offset := Raw.My_Cue_Points (Index).My_Sample_Offset; + Result (Index).Name := + Interfaces.C.To_Ada (Raw.My_Cue_Points (Index).My_Name, False); + end loop; + end return; + else + raise Program_Error; + end if; + end Get_Cue; + + procedure Set_Cue + (File : in Sound_File; + Info : in Cue_Marker_Array) + is + C_Data : C_Cue_Info; + Code : Interfaces.C.int; + begin + C_Data.My_Cue_Count := Info'Length; + for Index in Info'Range loop + C_Data.My_Cue_Points (Index).My_Indx := + Interfaces.Integer_32 (Info (Index).Index); + C_Data.My_Cue_Points (Index).My_Position := Info (Index).Position; + C_Data.My_Cue_Points (Index).My_FCC_Chunk := + Interfaces.Integer_32 (Info (Index).FCC_Chunk); + C_Data.My_Cue_Points (Index).My_Chunk_Start := + Interfaces.Integer_32 (Info (Index).Chunk_Start); + C_Data.My_Cue_Points (Index).My_Block_Start := + Interfaces.Integer_32 (Info (Index).Block_Start); + C_Data.My_Cue_Points (Index).My_Sample_Offset := Info (Index).Sample_Offset; + C_Data.My_Cue_Points (Index).My_Name := + Interfaces.C.To_C (Info (Index).Name, False); + end loop; + Code := sf_command + (File.Ptr, + sfc_set_cue, + C_Data'Address, + C_Cue_Info'Size / Interfaces.C.CHAR_BIT); + if Code = sf_false then + raise Command_Error; + elsif Code /= sf_true then + raise Program_Error; + end if; + end Set_Cue; + procedure RF64_Auto_Downgrade (File : in Sound_File; Value : in Boolean) -- cgit