From 87b89d768d367a475bb553de295ac867909c28c9 Mon Sep 17 00:00:00 2001
From: Jedidiah Barber <contact@jedbarber.id.au>
Date: Thu, 12 Oct 2023 17:39:45 +1300
Subject: Added callbacks for streams finishing

---
 src/portaudio-streams.adb | 138 +++++++++++++++++++++++++++++-----------------
 src/portaudio-streams.ads |  78 +++++++++++++++-----------
 2 files changed, 132 insertions(+), 84 deletions(-)

(limited to 'src')

diff --git a/src/portaudio-streams.adb b/src/portaudio-streams.adb
index 18a091e..ed837b9 100644
--- a/src/portaudio-streams.adb
+++ b/src/portaudio-streams.adb
@@ -285,7 +285,7 @@ package body Portaudio.Streams is
 
         Result : Callback_Result;
     begin
-        Result := Stream_Actual.Func
+        Result := Stream_Actual.Callfun
            (Input_Buffer,
             Output_Buffer,
             Frame_Amount (Frame_Count),
@@ -300,6 +300,16 @@ package body Portaudio.Streams is
         return To_Cint (Result);
     end Stream_Callback_Hook;
 
+    procedure Stream_Finished_Callback_Hook
+           (Userdata : in System.Address)
+    is
+        Stream_Actual : Audio_Stream;
+        for Stream_Actual'Address use Userdata;
+        pragma Import (Ada, Stream_Actual);
+    begin
+        Stream_Actual.Finfun.all;
+    end Stream_Finished_Callback_Hook;
+
 
 
 
@@ -627,12 +637,12 @@ package body Portaudio.Streams is
     end Is_Format_Supported;
 
     procedure Open_Input
-           (Stream        : in out Audio_Stream;
-            Input_Params  : in     Parameters;
-            Sample_Rate   : in     Hertz;
-            Buffer_Frames : in     Frame_Amount;
-            Bunting       : in     Stream_Flags;
-            Callback      : in     Callback_Function)
+           (Stream        : in out      Audio_Stream;
+            Input_Params  : in          Parameters;
+            Sample_Rate   : in          Hertz;
+            Buffer_Frames : in          Frame_Amount;
+            Bunting       : in          Stream_Flags;
+            Callback      : in not null Callback_Function)
     is
         Code : Interfaces.C.int;
     begin
@@ -649,22 +659,20 @@ package body Portaudio.Streams is
             Raise_Error (Code);
             raise Program_Error;
         else
-            Stream.Open  := True;
-            Stream.Func  := Callback;
-            Stream.Chin  := Input_Params.My_Channels;
-            Stream.Chout := 0;
-            Stream.Sin   := Input_Params.My_Samples;
-            Stream.Sout  := 0;
+            Stream.Open    := True;
+            Stream.Callfun := Callback;
+            Stream.Chin    := Input_Params.My_Channels;
+            Stream.Sin     := Input_Params.My_Samples;
         end if;
     end Open_Input;
 
     procedure Open_Output
-           (Stream        : in out Audio_Stream;
-            Output_Params : in     Parameters;
-            Sample_Rate   : in     Hertz;
-            Buffer_Frames : in     Frame_Amount;
-            Bunting       : in     Stream_Flags;
-            Callback      : in     Callback_Function)
+           (Stream        : in out      Audio_Stream;
+            Output_Params : in          Parameters;
+            Sample_Rate   : in          Hertz;
+            Buffer_Frames : in          Frame_Amount;
+            Bunting       : in          Stream_Flags;
+            Callback      : in not null Callback_Function)
     is
         Code : Interfaces.C.int;
     begin
@@ -681,23 +689,21 @@ package body Portaudio.Streams is
             Raise_Error (Code);
             raise Program_Error;
         else
-            Stream.Open  := True;
-            Stream.Func  := Callback;
-            Stream.Chin  := 0;
-            Stream.Chout := Output_Params.My_Channels;
-            Stream.Sin   := 0;
-            Stream.Sout  := Output_Params.My_Samples;
+            Stream.Open    := True;
+            Stream.Callfun := Callback;
+            Stream.Chout   := Output_Params.My_Channels;
+            Stream.Sout    := Output_Params.My_Samples;
         end if;
     end Open_Output;
 
     procedure Open_Full
-           (Stream        : in out Audio_Stream;
-            Input_Params  : in     Parameters;
-            Output_Params : in     Parameters;
-            Sample_Rate   : in     Hertz;
-            Buffer_Frames : in     Frame_Amount;
-            Bunting       : in     Stream_Flags;
-            Callback      : in     Callback_Function)
+           (Stream        : in out      Audio_Stream;
+            Input_Params  : in          Parameters;
+            Output_Params : in          Parameters;
+            Sample_Rate   : in          Hertz;
+            Buffer_Frames : in          Frame_Amount;
+            Bunting       : in          Stream_Flags;
+            Callback      : in not null Callback_Function)
     is
         Code : Interfaces.C.int;
     begin
@@ -714,12 +720,12 @@ package body Portaudio.Streams is
             Raise_Error (Code);
             raise Program_Error;
         else
-            Stream.Open  := True;
-            Stream.Func  := Callback;
-            Stream.Chin  := Input_Params.My_Channels;
-            Stream.Chout := Output_Params.My_Channels;
-            Stream.Sin   := Input_Params.My_Samples;
-            Stream.Sout  := Output_Params.My_Samples;
+            Stream.Open    := True;
+            Stream.Callfun := Callback;
+            Stream.Chin    := Input_Params.My_Channels;
+            Stream.Chout   := Output_Params.My_Channels;
+            Stream.Sin     := Input_Params.My_Samples;
+            Stream.Sout    := Output_Params.My_Samples;
         end if;
     end Open_Full;
 
@@ -803,13 +809,13 @@ package body Portaudio.Streams is
     end Open_Full_Blocking;
 
     procedure Open_Default
-           (Stream          : in out Audio_Stream;
-            Input_Channels  : in     Natural;
-            Output_Channels : in     Natural;
-            Format          : in     Sample_Format;
-            Sample_Rate     : in     Hertz;
-            Buffer_Frames   : in     Frame_Amount;
-            Callback        : in     Callback_Function)
+           (Stream          : in out      Audio_Stream;
+            Input_Channels  : in          Natural;
+            Output_Channels : in          Natural;
+            Format          : in          Sample_Format;
+            Sample_Rate     : in          Hertz;
+            Buffer_Frames   : in          Frame_Amount;
+            Callback        : in not null Callback_Function)
     is
         Code : Interfaces.C.int;
     begin
@@ -826,12 +832,12 @@ package body Portaudio.Streams is
             Raise_Error (Code);
             raise Program_Error;
         else
-            Stream.Open  := True;
-            Stream.Func  := Callback;
-            Stream.Chin  := Interfaces.C.int (Input_Channels);
-            Stream.Chout := Interfaces.C.int (Output_Channels);
-            Stream.Sin   := To_Cnum (Format);
-            Stream.Sout  := To_Cnum (Format);
+            Stream.Open    := True;
+            Stream.Callfun := Callback;
+            Stream.Chin    := Interfaces.C.int (Input_Channels);
+            Stream.Chout   := Interfaces.C.int (Output_Channels);
+            Stream.Sin     := To_Cnum (Format);
+            Stream.Sout    := To_Cnum (Format);
         end if;
     end Open_Default;
 
@@ -880,6 +886,36 @@ package body Portaudio.Streams is
         end if;
     end Close;
 
+    procedure Set_Finished_Callback
+           (Stream   : in out      Audio_Stream;
+            Callback : in not null Stream_Finished_Function)
+    is
+        Code : Interfaces.C.int;
+    begin
+        Stream.Finfun := Callback;
+        Code := pa_set_stream_finished_callback
+           (Stream.Ptr,
+            Stream_Finished_Callback_Hook'Address);
+        if Code /= pa_no_error then
+            Raise_Error (Code);
+            raise Program_Error;
+        end if;
+    end Set_Finished_Callback;
+
+    procedure Clear_Finished_Callback
+           (Stream : in out Audio_Stream)
+    is
+        Code : Interfaces.C.int;
+    begin
+        Code := pa_set_stream_finished_callback
+           (Stream.Ptr,
+            System.Null_Address);
+        if Code /= pa_no_error then
+            Raise_Error (Code);
+            raise Program_Error;
+        end if;
+    end Clear_Finished_Callback;
+
     procedure Start
            (Stream : in Audio_Stream)
     is
diff --git a/src/portaudio-streams.ads b/src/portaudio-streams.ads
index c8d3e92..0f3d2ba 100644
--- a/src/portaudio-streams.ads
+++ b/src/portaudio-streams.ads
@@ -272,6 +272,8 @@ package Portaudio.Streams is
             Bunting : in Callback_Flags)
         return Callback_Result;
 
+    type Stream_Finished_Function is access procedure;
+
 
 
 
@@ -297,33 +299,33 @@ package Portaudio.Streams is
         return Boolean;
 
     procedure Open_Input
-           (Stream        : in out Audio_Stream;
-            Input_Params  : in     Parameters;
-            Sample_Rate   : in     Hertz;
-            Buffer_Frames : in     Frame_Amount;
-            Bunting       : in     Stream_Flags;
-            Callback      : in     Callback_Function)
+           (Stream        : in out      Audio_Stream;
+            Input_Params  : in          Parameters;
+            Sample_Rate   : in          Hertz;
+            Buffer_Frames : in          Frame_Amount;
+            Bunting       : in          Stream_Flags;
+            Callback      : in not null Callback_Function)
     with Pre => not Stream.Is_Open,
         Post => Stream.Is_Open;
 
     procedure Open_Output
-           (Stream        : in out Audio_Stream;
-            Output_Params : in     Parameters;
-            Sample_Rate   : in     Hertz;
-            Buffer_Frames : in     Frame_Amount;
-            Bunting       : in     Stream_Flags;
-            Callback      : in     Callback_Function)
+           (Stream        : in out      Audio_Stream;
+            Output_Params : in          Parameters;
+            Sample_Rate   : in          Hertz;
+            Buffer_Frames : in          Frame_Amount;
+            Bunting       : in          Stream_Flags;
+            Callback      : in not null Callback_Function)
     with Pre => not Stream.Is_Open,
         Post => Stream.Is_Open;
 
     procedure Open_Full
-           (Stream        : in out Audio_Stream;
-            Input_Params  : in     Parameters;
-            Output_Params : in     Parameters;
-            Sample_Rate   : in     Hertz;
-            Buffer_Frames : in     Frame_Amount;
-            Bunting       : in     Stream_Flags;
-            Callback      : in     Callback_Function)
+           (Stream        : in out      Audio_Stream;
+            Input_Params  : in          Parameters;
+            Output_Params : in          Parameters;
+            Sample_Rate   : in          Hertz;
+            Buffer_Frames : in          Frame_Amount;
+            Bunting       : in          Stream_Flags;
+            Callback      : in not null Callback_Function)
     with Pre => not Stream.Is_Open,
         Post => Stream.Is_Open;
 
@@ -356,13 +358,13 @@ package Portaudio.Streams is
         Post => Stream.Is_Open;
 
     procedure Open_Default
-           (Stream          : in out Audio_Stream;
-            Input_Channels  : in     Natural;
-            Output_Channels : in     Natural;
-            Format          : in     Sample_Format;
-            Sample_Rate     : in     Hertz;
-            Buffer_Frames   : in     Frame_Amount;
-            Callback        : in     Callback_Function)
+           (Stream          : in out      Audio_Stream;
+            Input_Channels  : in          Natural;
+            Output_Channels : in          Natural;
+            Format          : in          Sample_Format;
+            Sample_Rate     : in          Hertz;
+            Buffer_Frames   : in          Frame_Amount;
+            Callback        : in not null Callback_Function)
     with Pre => not Stream.Is_Open and
             (Input_Channels > 0 or Output_Channels > 0),
         Post => Stream.Is_Open;
@@ -383,6 +385,15 @@ package Portaudio.Streams is
     with Pre => Stream.Is_Open,
         Post => not Stream.Is_Open;
 
+    procedure Set_Finished_Callback
+           (Stream   : in out      Audio_Stream;
+            Callback : in not null Stream_Finished_Function)
+    with Pre => Stream.Is_Open and then Stream.Is_Stopped;
+
+    procedure Clear_Finished_Callback
+           (Stream : in out Audio_Stream)
+    with Pre => Stream.Is_Open and then Stream.Is_Stopped;
+
     procedure Start
            (Stream : in Audio_Stream)
     with Pre => Stream.Is_Open;
@@ -495,13 +506,14 @@ private
 
 
     type Audio_Stream is tagged limited record
-        Ptr   : System.Address;
-        Open  : Boolean := False;
-        Func  : Callback_Function;
-        Chin  : Interfaces.C.int := 0;
-        Chout : Interfaces.C.int := 0;
-        Sin   : Interfaces.C.unsigned_long := 0;
-        Sout  : Interfaces.C.unsigned_long := 0;
+        Ptr     : System.Address;
+        Open    : Boolean := False;
+        Callfun : Callback_Function;
+        Finfun  : Stream_Finished_Function;
+        Chin    : Interfaces.C.int := 0;
+        Chout   : Interfaces.C.int := 0;
+        Sin     : Interfaces.C.unsigned_long := 0;
+        Sout    : Interfaces.C.unsigned_long := 0;
     end record;
 
 
-- 
cgit