### ----------------------------------------------------
### -- Audio::PortAudio
### -- Licenses: Artistic-2.0
### -- Authors: Jonathan Stowe <jns+gh@gellyfish.co.uk>
### -- File: lib/Audio/PortAudio.rakumod
### ----------------------------------------------------
### -- Chunk 2 of 2
  {
        my $count = Pa_GetDeviceCount();
        if $count < 0 {
            X::PortAudio.new(code => $count, what => "getting device count").throw;
        }
        $count;
    }


    sub Pa_GetDeviceInfo(int32 $device-number --> DeviceInfo )  is export is native('portaudio',v2) {...}

    method device-info(Int $device-number --> DeviceInfo )  {
        Pa_GetDeviceInfo($device-number);
    }

    method devices() {
        my Int $no-devices = self.device-count();
        gather {
            for ^$no-devices -> $device-number {
                take self.device-info($device-number);
            }

        }
    }


    method error-text(Int $error-code --> Str )  {
        Pa_GetErrorText($error-code);
    }

    sub Pa_GetDefaultOutputDevice( --> int32 )  is native('portaudio',v2) {...}

    method default-output-device( --> DeviceInfo )  {
        my Int $device-number = Pa_GetDefaultOutputDevice();
        if $device-number < 0 {
            X::PortAudio.new(code => $device-number, what => "getting output device").throw;
        }
        self.device-info($device-number);
    }

    sub Pa_GetDefaultInputDevice( --> int32 )  is native('portaudio',v2) {...}

    method default-input-device( --> DeviceInfo )  {
        my Int $device-number = Pa_GetDefaultInputDevice();
        if $device-number < 0 {
            X::PortAudio.new(code => $device-number, what => "getting input device").throw;
        }
        self.device-info($device-number);
    }

    sub Pa_OpenDefaultStream(CArray[Stream] $stream,
                             int32 $input,
                             int32 $output,
                             int32 $format,
                             num64 $sample-rate,
                             int32 $frames-per-buffer ,
                             &callback (CArray $inputbuf, CArray $outputbuf, int32 $framecount, StreamCallbackTimeInfo $callback-time-info, int32 $flags, CArray $cb-user-data --> int32),
                             CArray $user-data)
        returns int32 is native('portaudio',v2) {...}

    class X::OpenError is X::PortAudio {
        method message( --> Str )   {
            "error opening stream: '{ $.error-text }'";
        }
    }

    method open-default-stream(Int $input = 0, Int $output = 2, StreamFormat $format = StreamFormat::Float32, Int $sample-rate = 44100, Int $frames-per-buffer = 256 --> Stream )  {
        my CArray[Stream] $stream = CArray[Stream].new;
        $stream[0] = Stream.new;
        my $rc = Pa_OpenDefaultStream($stream,$input,$output,$format.Int, Num($sample-rate), $frames-per-buffer, Pointer, CArray);
        if $rc != 0 {
            X::OpenError.new(code => $rc, error-text => self.error-text($rc)).throw;
        }
        $stream[0];
    }

    sub Pa_OpenStream(CArray[Stream] $stream,
                      StreamParameters $in-params,
                      StreamParameters $out-params,
                      num64 $sample-rate,
                      int32 $frames-per-buffer,
                      int32 $flags,
                      &callback (CArray $inputbuf, CArray $outputbuf, int32 $framecount, StreamCallbackTimeInfo $callback-time-info, int32 $cb-flags, CArray $cb-user-data --> int32),
                      CArray $user-data)
        returns int32 is native('portaudio',v2) {...}

    method open-stream(StreamParameters $in-params, StreamParameters $out-params, Int $sample-rate = 44100, Int $frames-per-buffer = 256 --> Stream )  {
        my CArray[Stream] $stream = CArray[Stream].new;
        $stream[0] = Stream.new;
        my $rc = Pa_OpenStream($stream, $in-params, $out-params, Num($sample-rate), $frames-per-buffer, 0, Pointer, CArray);
        if $rc != 0 {
            X::OpenError.new(code => $rc, error-text => self.error-text($rc)).throw;
        }
        $stream[0];
    }
    sub Pa_IsFormatSupported( StreamParameters $input, StreamParameters $output, num64 $sample-rate --> int32 )  is native('portaudio', v2) { * }

    method is-format-supported(StreamParameters $input, StreamParameters $output, Int $sample-rate --> Bool )  {
        my $rc = Pa_IsFormatSupported($input, $output, Num($sample-rate));
        $rc == 0 ?? True !! False;
    }
}
# vim: expandtab shiftwidth=4 ft=raku


