Add gen README

This commit is contained in:
Brandon Taylor 2021-07-01 10:40:17 -04:00
parent bbd238dbfe
commit fb49203835
3 changed files with 43 additions and 44 deletions

1
gen/README.md Normal file
View file

@ -0,0 +1 @@
The clang generators will automatically generate wrappers for a C library based on its headers. So everything you see in libportaudio.jl is automatically generated from the C library. If a newer version of portaudio adds more features, we won't have to add new wrappers: clang will handle it for us. It is easy to use currently unused features: the wrappers have already been written for us. Even though it does an admirable job, clang doesn't handle errors and set locks. Fortunately, it's very easy to add secondary wrappers, or just do it at point of use.

View file

@ -60,7 +60,7 @@ using .LibPortAudio:
Pa_Terminate, Pa_Terminate,
Pa_WriteStream Pa_WriteStream
# for structs from indexes # for structs and strings
# PortAudio will return C_NULL instead of erroring # PortAudio will return C_NULL instead of erroring
# so we need to handle these errors # so we need to handle these errors
function safe_load(result, an_error) function safe_load(result, an_error)
@ -254,7 +254,7 @@ end
# 1) the buffer # 1) the buffer
# 2) a tuple of custom inputs # 2) a tuple of custom inputs
# and return the output type # and return the output type
# this call method should make use of read_buffer/write_buffer methods above # this call method can make use of read_buffer/write_buffer methods above
abstract type Scribe end abstract type Scribe end
struct SampledSignalsReader{Sample} <: Scribe struct SampledSignalsReader{Sample} <: Scribe
@ -304,11 +304,7 @@ function cut_to_size(buffer, julia_buffer, use_frames, offset, already)
) )
end end
function (writer::SampledSignalsWriter)( function (writer::SampledSignalsWriter)(buffer, (julia_buffer, offset, frame_count))
buffer,
(julia_buffer, offset, frame_count),
# data is passed to and from portaudio in chunks with this many frames
)
already = 0 already = 0
chunk_frames = buffer.chunk_frames chunk_frames = buffer.chunk_frames
# if we still have frames to write # if we still have frames to write
@ -412,7 +408,7 @@ end
# PortAudioStream # PortAudioStream
# #
struct PortAudioStream{Sample, SinkBuffer, SourceBuffer} struct PortAudioStream{SinkBuffer, SourceBuffer}
sample_rate::Float64 sample_rate::Float64
# pointer to the c object # pointer to the c object
pointer_to::Ptr{PaStream} pointer_to::Ptr{PaStream}
@ -422,24 +418,6 @@ struct PortAudioStream{Sample, SinkBuffer, SourceBuffer}
source_task::Task source_task::Task
end end
function PortAudioStream{Sample}(
sample_rate::Float64,
pointer_to::Ptr{PaStream},
sink_buffer::SinkBuffer,
sink_task::Task,
source_buffer::SourceBuffer,
source_task::Task,
) where {Sample, SinkBuffer, SourceBuffer}
PortAudioStream{Sample, SinkBuffer, SourceBuffer}(
sample_rate,
pointer_to,
sink_buffer,
sink_task,
source_buffer,
source_task,
)
end
# portaudio uses codes instead of types for the sample format # portaudio uses codes instead of types for the sample format
const TYPE_TO_FORMAT = Dict{Type, PaSampleFormat}( const TYPE_TO_FORMAT = Dict{Type, PaSampleFormat}(
Float32 => 1, Float32 => 1,
@ -454,7 +432,13 @@ const TYPE_TO_FORMAT = Dict{Type, PaSampleFormat}(
nothing_to_c_null(::Nothing) = C_NULL nothing_to_c_null(::Nothing) = C_NULL
nothing_to_c_null(something) = something nothing_to_c_null(something) = something
function make_parameters(device, channels, Sample, latency, host_api_specific_stream_info) function make_parameters(
device,
channels,
latency;
Sample = Float32,
host_api_specific_stream_info = nothing,
)
if channels == 0 if channels == 0
# if we don't need any channels, we don't need the source/sink at all # if we don't need any channels, we don't need the source/sink at all
C_NULL C_NULL
@ -568,6 +552,7 @@ function PortAudioStream(
latency = nothing, latency = nothing,
warn_xruns = true, warn_xruns = true,
# these defaults are currently undocumented # these defaults are currently undocumented
# data is passed to and from portaudio in chunks with this many frames
chunk_frames = 128, chunk_frames = 128,
frames_per_buffer = 0, frames_per_buffer = 0,
flags = paNoFlag, flags = paNoFlag,
@ -640,19 +625,17 @@ function PortAudioStream(
make_parameters( make_parameters(
input_device, input_device,
input_channels_filled, input_channels_filled,
Sample, latency;
latency, host_api_specific_stream_info = input_info,
input_info,
), ),
make_parameters( make_parameters(
output_device, output_device,
output_channels_filled, output_channels_filled,
Sample, latency;
latency, Sample = Sample,
output_info, host_api_specific_stream_info = output_info,
), ),
# can't be an integer sample_rate,
float(sample_rate),
frames_per_buffer, frames_per_buffer,
flags, flags,
nothing_to_c_null(call_back), nothing_to_c_null(call_back),
@ -661,7 +644,7 @@ function PortAudioStream(
) )
pointer_to = mutable_pointer[] pointer_to = mutable_pointer[]
handle_status(Pa_StartStream(pointer_to)) handle_status(Pa_StartStream(pointer_to))
PortAudioStream{Sample}( PortAudioStream(
sample_rate, sample_rate,
pointer_to, pointer_to,
buffer_task( buffer_task(
@ -767,7 +750,11 @@ end
isopen(stream::PortAudioStream) = isopen(stream.pointer_to) isopen(stream::PortAudioStream) = isopen(stream.pointer_to)
samplerate(stream::PortAudioStream) = stream.sample_rate samplerate(stream::PortAudioStream) = stream.sample_rate
eltype(::Type{<:PortAudioStream{Sample}}) where {Sample} = Sample function eltype(
::Type{<:PortAudioStream{<:Buffer{Sample}, <:Buffer{Sample}}},
) where {Sample}
Sample
end
read(stream::PortAudioStream, arguments...) = read(stream.source, arguments...) read(stream::PortAudioStream, arguments...) = read(stream.source, arguments...)
read!(stream::PortAudioStream, arguments...) = read!(stream.source, arguments...) read!(stream::PortAudioStream, arguments...) = read!(stream.source, arguments...)
@ -803,14 +790,20 @@ end
# If we had multiple inheritance, then PortAudioStreams could be both a sink and source # If we had multiple inheritance, then PortAudioStreams could be both a sink and source
# Since we don't, we have to make wrappers instead # Since we don't, we have to make wrappers instead
for (TypeName, Super) in ((:PortAudioSink, :SampleSink), (:PortAudioSource, :SampleSource)) for (TypeName, Super) in ((:PortAudioSink, :SampleSink), (:PortAudioSource, :SampleSource))
@eval struct $TypeName{Sample, InputBuffer, OutputBuffer} <: $Super @eval struct $TypeName{InputBuffer, OutputBuffer} <: $Super
stream::PortAudioStream{Sample, InputBuffer, OutputBuffer} stream::PortAudioStream{InputBuffer, OutputBuffer}
end end
end end
# provided for backwards compatibility # provided for backwards compatibility
# only defined for SampledSignals scribes # only defined for SampledSignals scribes
function getproperty(stream::PortAudioStream{<:Any, <:Buffer{<:Any, <:SampledSignalsWriter}, <:Buffer{<:Any, <:SampledSignalsReader}}, property::Symbol) function getproperty(
stream::PortAudioStream{
<:Buffer{<:Any, <:SampledSignalsWriter},
<:Buffer{<:Any, <:SampledSignalsReader},
},
property::Symbol,
)
if property === :sink if property === :sink
PortAudioSink(stream) PortAudioSink(stream)
elseif property === :source elseif property === :source
@ -830,7 +823,12 @@ function samplerate(source_or_sink::Union{PortAudioSink, PortAudioSource})
samplerate(source_or_sink.stream) samplerate(source_or_sink.stream)
end end
function eltype( function eltype(
::Type{<:Union{PortAudioSink{Sample}, PortAudioSource{Sample}}}, ::Type{
<:Union{
<:PortAudioSink{<:Buffer{Sample}, <:Buffer{Sample}},
<:PortAudioSource{<:Buffer{Sample}, <:Buffer{Sample}},
},
},
) where {Sample} ) where {Sample}
Sample Sample
end end
@ -864,7 +862,7 @@ function exchange(buffer, arguments...)
end end
function unsafe_write( function unsafe_write(
sink::PortAudioSink{<:Any, <:Buffer{<:Any, <:SampledSignalsWriter}}, sink::PortAudioSink{<:Buffer{<:Any, <:SampledSignalsWriter}},
julia_buffer::Array, julia_buffer::Array,
offset, offset,
frame_count, frame_count,
@ -873,7 +871,7 @@ function unsafe_write(
end end
function unsafe_read!( function unsafe_read!(
source::PortAudioSource{<:Any, <:Any, <:Buffer{<:Any, <:SampledSignalsReader}}, source::PortAudioSource{<:Any, <:Buffer{<:Any, <:SampledSignalsReader}},
julia_buffer::Array, julia_buffer::Array,
offset, offset,
frame_count, frame_count,