Compat Julia 0.7
This commit is contained in:
parent
03aefe619d
commit
5823404f1a
11 changed files with 102 additions and 80 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,6 +1,7 @@
|
||||||
*.swp
|
*.swp
|
||||||
*.o
|
*.o
|
||||||
deps/deps.jl
|
deps/deps.jl
|
||||||
|
deps/build.log
|
||||||
*.wav
|
*.wav
|
||||||
*.flac
|
*.flac
|
||||||
*.cov
|
*.cov
|
||||||
|
|
|
@ -6,6 +6,7 @@ os:
|
||||||
sudo: required
|
sudo: required
|
||||||
julia:
|
julia:
|
||||||
- 0.6
|
- 0.6
|
||||||
|
- nightly
|
||||||
notifications:
|
notifications:
|
||||||
email: false
|
email: false
|
||||||
script:
|
script:
|
||||||
|
|
9
REQUIRE
9
REQUIRE
|
@ -1,6 +1,7 @@
|
||||||
julia 0.6.0-dev.2746
|
julia 0.6
|
||||||
BinDeps
|
BinDeps 0.8.8
|
||||||
SampledSignals 0.3.0
|
SampledSignals 1.1.2
|
||||||
RingBuffers 1.0.0
|
RingBuffers 1.1.2
|
||||||
|
Compat 0.66.0
|
||||||
@osx Homebrew
|
@osx Homebrew
|
||||||
@windows WinRPM
|
@windows WinRPM
|
||||||
|
|
|
@ -2,6 +2,7 @@ environment:
|
||||||
matrix:
|
matrix:
|
||||||
- JULIA_URL: "https://julialang-s3.julialang.org/bin/winnt/x86/0.6/julia-0.6-latest-win32.exe"
|
- JULIA_URL: "https://julialang-s3.julialang.org/bin/winnt/x86/0.6/julia-0.6-latest-win32.exe"
|
||||||
- JULIA_URL: "https://julialang-s3.julialang.org/bin/winnt/x64/0.6/julia-0.6-latest-win64.exe"
|
- JULIA_URL: "https://julialang-s3.julialang.org/bin/winnt/x64/0.6/julia-0.6-latest-win64.exe"
|
||||||
|
- JULIA_URL: "https://julialangnightlies-s3.julialang.org/bin/winnt/x64/julia-latest-win64.exe"
|
||||||
|
|
||||||
notifications:
|
notifications:
|
||||||
- provider: Email
|
- provider: Email
|
||||||
|
|
3
deps/build.jl
vendored
3
deps/build.jl
vendored
|
@ -1,8 +1,9 @@
|
||||||
using BinDeps
|
using BinDeps
|
||||||
|
using Compat
|
||||||
|
|
||||||
@BinDeps.setup
|
@BinDeps.setup
|
||||||
|
|
||||||
ENV["JULIA_ROOT"] = abspath(JULIA_HOME, "../../")
|
ENV["JULIA_ROOT"] = abspath(Compat.Sys.BINDIR, "../../")
|
||||||
|
|
||||||
# include alias for WinRPM library
|
# include alias for WinRPM library
|
||||||
libportaudio = library_dependency("libportaudio", aliases=["libportaudio-2"])
|
libportaudio = library_dependency("libportaudio", aliases=["libportaudio-2"])
|
||||||
|
|
|
@ -1,30 +1,26 @@
|
||||||
__precompile__()
|
__precompile__(true)
|
||||||
|
|
||||||
module PortAudio
|
module PortAudio
|
||||||
|
|
||||||
using SampledSignals
|
using SampledSignals
|
||||||
using RingBuffers
|
using RingBuffers
|
||||||
#using Suppressor
|
using Compat
|
||||||
|
import Compat: undef, fetch, @compat
|
||||||
|
import Compat.LinearAlgebra: transpose!
|
||||||
|
|
||||||
import Base: eltype, show
|
import Base: eltype, show
|
||||||
import Base: close, isopen
|
import Base: close, isopen
|
||||||
import Base: read, read!, write, flush
|
import Base: read, read!, write, flush
|
||||||
|
|
||||||
|
export PortAudioStream
|
||||||
|
|
||||||
|
|
||||||
# Get binary dependencies loaded from BinDeps
|
# Get binary dependencies loaded from BinDeps
|
||||||
include("../deps/deps.jl")
|
include("../deps/deps.jl")
|
||||||
include("suppressor.jl")
|
include("suppressor.jl")
|
||||||
include("pa_shim.jl")
|
include("pa_shim.jl")
|
||||||
include("libportaudio.jl")
|
include("libportaudio.jl")
|
||||||
|
|
||||||
function __init__()
|
|
||||||
init_pa_shim()
|
|
||||||
global const notifycb_c = cfunction(notifycb, Cint, (Ptr{Void}, ))
|
|
||||||
# initialize PortAudio on module load
|
|
||||||
@suppress_err Pa_Initialize()
|
|
||||||
end
|
|
||||||
|
|
||||||
export PortAudioStream
|
|
||||||
|
|
||||||
# These sizes are all in frames
|
# These sizes are all in frames
|
||||||
|
|
||||||
# the block size is what we request from portaudio if no blocksize is given.
|
# the block size is what we request from portaudio if no blocksize is given.
|
||||||
|
@ -46,7 +42,7 @@ function versioninfo(io::IO=STDOUT)
|
||||||
println(io, "Shim Source Hash: ", shimhash()[1:10])
|
println(io, "Shim Source Hash: ", shimhash()[1:10])
|
||||||
end
|
end
|
||||||
|
|
||||||
type PortAudioDevice
|
mutable struct PortAudioDevice
|
||||||
name::String
|
name::String
|
||||||
hostapi::String
|
hostapi::String
|
||||||
maxinchans::Int
|
maxinchans::Int
|
||||||
|
@ -76,7 +72,7 @@ devnames() = join(["\"$(dev.name)\"" for dev in devices()], "\n")
|
||||||
# PortAudioStream
|
# PortAudioStream
|
||||||
##################
|
##################
|
||||||
|
|
||||||
type PortAudioStream{T}
|
mutable struct PortAudioStream{T}
|
||||||
samplerate::Float64
|
samplerate::Float64
|
||||||
blocksize::Int
|
blocksize::Int
|
||||||
stream::PaStream
|
stream::PaStream
|
||||||
|
@ -98,7 +94,7 @@ type PortAudioStream{T}
|
||||||
Ptr{Pa_StreamParameters}(0) :
|
Ptr{Pa_StreamParameters}(0) :
|
||||||
Ref(Pa_StreamParameters(outdev.idx, outchans, type_to_fmt[T], 0.0, C_NULL))
|
Ref(Pa_StreamParameters(outdev.idx, outchans, type_to_fmt[T], 0.0, C_NULL))
|
||||||
this = new(sr, blocksize, C_NULL)
|
this = new(sr, blocksize, C_NULL)
|
||||||
finalizer(this, close)
|
@compat finalizer(close, this)
|
||||||
this.sink = PortAudioSink{T}(outdev.name, this, outchans, blocksize*2)
|
this.sink = PortAudioSink{T}(outdev.name, this, outchans, blocksize*2)
|
||||||
this.source = PortAudioSource{T}(indev.name, this, inchans, blocksize*2)
|
this.source = PortAudioSource{T}(indev.name, this, inchans, blocksize*2)
|
||||||
this.errbuf = RingBuffer{pa_shim_errmsg_t}(1, ERR_BUFSIZE)
|
this.errbuf = RingBuffer{pa_shim_errmsg_t}(1, ERR_BUFSIZE)
|
||||||
|
@ -127,6 +123,7 @@ type PortAudioStream{T}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# this is the top-level outer constructor that all the other outer constructors end up calling
|
||||||
"""
|
"""
|
||||||
PortAudioStream(inchannels=2, outchannels=2; options...)
|
PortAudioStream(inchannels=2, outchannels=2; options...)
|
||||||
PortAudioStream(duplexdevice, inchannels=2, outchannels=2; options...)
|
PortAudioStream(duplexdevice, inchannels=2, outchannels=2; options...)
|
||||||
|
@ -150,8 +147,6 @@ Options:
|
||||||
`false`, you are free to read and write separately, but
|
`false`, you are free to read and write separately, but
|
||||||
overflow or underflow can affect the round-trip latency.
|
overflow or underflow can affect the round-trip latency.
|
||||||
"""
|
"""
|
||||||
# this is the top-level outer constructor that all the other outer constructors
|
|
||||||
# end up calling
|
|
||||||
function PortAudioStream(indev::PortAudioDevice, outdev::PortAudioDevice,
|
function PortAudioStream(indev::PortAudioDevice, outdev::PortAudioDevice,
|
||||||
inchans=2, outchans=2; eltype=Float32, samplerate=-1, blocksize=DEFAULT_BLOCKSIZE, synced=false)
|
inchans=2, outchans=2; eltype=Float32, samplerate=-1, blocksize=DEFAULT_BLOCKSIZE, synced=false)
|
||||||
if samplerate == -1
|
if samplerate == -1
|
||||||
|
@ -226,7 +221,7 @@ end
|
||||||
isopen(stream::PortAudioStream) = stream.stream != C_NULL
|
isopen(stream::PortAudioStream) = stream.stream != C_NULL
|
||||||
|
|
||||||
SampledSignals.samplerate(stream::PortAudioStream) = stream.samplerate
|
SampledSignals.samplerate(stream::PortAudioStream) = stream.samplerate
|
||||||
eltype{T}(stream::PortAudioStream{T}) = T
|
eltype(stream::PortAudioStream{T}) where T = T
|
||||||
|
|
||||||
read(stream::PortAudioStream, args...) = read(stream.source, args...)
|
read(stream::PortAudioStream, args...) = read(stream.source, args...)
|
||||||
read!(stream::PortAudioStream, args...) = read!(stream.source, args...)
|
read!(stream::PortAudioStream, args...) = read!(stream.source, args...)
|
||||||
|
@ -253,7 +248,7 @@ Handle errors coming over the error stream from PortAudio. This is run as an
|
||||||
independent task while the stream is active.
|
independent task while the stream is active.
|
||||||
"""
|
"""
|
||||||
function handle_errors(stream::PortAudioStream)
|
function handle_errors(stream::PortAudioStream)
|
||||||
err = Vector{pa_shim_errmsg_t}(1)
|
err = Vector{pa_shim_errmsg_t}(undef, 1)
|
||||||
while true
|
while true
|
||||||
nread = read!(stream.errbuf, err)
|
nread = read!(stream.errbuf, err)
|
||||||
nread == 1 || break
|
nread == 1 || break
|
||||||
|
@ -279,7 +274,7 @@ end
|
||||||
# Define our source and sink types
|
# Define our source and sink types
|
||||||
for (TypeName, Super) in ((:PortAudioSink, :SampleSink),
|
for (TypeName, Super) in ((:PortAudioSink, :SampleSink),
|
||||||
(:PortAudioSource, :SampleSource))
|
(:PortAudioSource, :SampleSource))
|
||||||
@eval type $TypeName{T} <: $Super
|
@eval mutable struct $TypeName{T} <: $Super
|
||||||
name::String
|
name::String
|
||||||
stream::PortAudioStream{T}
|
stream::PortAudioStream{T}
|
||||||
chunkbuf::Array{T, 2}
|
chunkbuf::Array{T, 2}
|
||||||
|
@ -319,7 +314,7 @@ function SampledSignals.unsafe_write(sink::PortAudioSink, buf::Array, frameoffse
|
||||||
towrite = min(framecount-nwritten, CHUNKSIZE)
|
towrite = min(framecount-nwritten, CHUNKSIZE)
|
||||||
# make a buffer of interleaved samples
|
# make a buffer of interleaved samples
|
||||||
transpose!(view(sink.chunkbuf, :, 1:towrite),
|
transpose!(view(sink.chunkbuf, :, 1:towrite),
|
||||||
view(buf, (1:towrite)+nwritten+frameoffset, :))
|
view(buf, (1:towrite) .+ nwritten .+ frameoffset, :))
|
||||||
n = write(sink.ringbuf, sink.chunkbuf, towrite)
|
n = write(sink.ringbuf, sink.chunkbuf, towrite)
|
||||||
nwritten += n
|
nwritten += n
|
||||||
# break early if the stream is closed
|
# break early if the stream is closed
|
||||||
|
@ -335,7 +330,7 @@ function SampledSignals.unsafe_read!(source::PortAudioSource, buf::Array, frameo
|
||||||
toread = min(framecount-nread, CHUNKSIZE)
|
toread = min(framecount-nread, CHUNKSIZE)
|
||||||
n = read!(source.ringbuf, source.chunkbuf, toread)
|
n = read!(source.ringbuf, source.chunkbuf, toread)
|
||||||
# de-interleave the samples
|
# de-interleave the samples
|
||||||
transpose!(view(buf, (1:toread)+nread+frameoffset, :),
|
transpose!(view(buf, (1:toread) .+ nread .+ frameoffset, :),
|
||||||
view(source.chunkbuf, :, 1:toread))
|
view(source.chunkbuf, :, 1:toread))
|
||||||
|
|
||||||
nread += toread
|
nread += toread
|
||||||
|
@ -346,9 +341,43 @@ function SampledSignals.unsafe_read!(source::PortAudioSource, buf::Array, frameo
|
||||||
nread
|
nread
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
const libpa_shim = find_pa_shim()
|
||||||
|
|
||||||
|
"""
|
||||||
|
PortAudio.shimhash()
|
||||||
|
|
||||||
|
Return the sha256 hash(as a string) of the source file used to build the shim.
|
||||||
|
We may use this sometime to verify that the distributed binary stays in sync
|
||||||
|
with the rest of the package.
|
||||||
|
"""
|
||||||
|
shimhash() = unsafe_string(ccall((:pa_shim_getsourcehash, libpa_shim), Cstring, ()))
|
||||||
|
|
||||||
|
|
||||||
# this is called by the shim process callback to notify that there is new data.
|
# this is called by the shim process callback to notify that there is new data.
|
||||||
# it's run in the audio context so don't do anything besides wake up the
|
# it's run in the audio context so don't do anything besides wake up the
|
||||||
# AsyncCondition handle associated with that ring buffer
|
# AsyncCondition handle associated with that ring buffer
|
||||||
notifycb(handle) = ccall(:uv_async_send, Cint, (Ptr{Void}, ), handle)
|
notifycb(handle) = ccall(:uv_async_send, Cint, (Ptr{Cvoid},), handle)
|
||||||
|
|
||||||
|
global shim_processcb_c, notifycb_c
|
||||||
|
|
||||||
|
function set_global_callbacks()
|
||||||
|
shim_dlib = Libdl.dlopen(libpa_shim)
|
||||||
|
|
||||||
|
# pointer to the shim's process callback
|
||||||
|
global shim_processcb_c = Libdl.dlsym(shim_dlib, :pa_shim_processcb)
|
||||||
|
if shim_processcb_c == C_NULL
|
||||||
|
error("Got NULL pointer loading `pa_shim_processcb`")
|
||||||
|
end
|
||||||
|
|
||||||
|
global notifycb_c = @cfunction notifycb Cint (Ptr{Cvoid},)
|
||||||
|
end
|
||||||
|
|
||||||
|
function __init__()
|
||||||
|
set_global_callbacks()
|
||||||
|
|
||||||
|
# initialize PortAudio on module load
|
||||||
|
@suppress_err Pa_Initialize()
|
||||||
|
end
|
||||||
|
|
||||||
end # module PortAudio
|
end # module PortAudio
|
||||||
|
|
|
@ -9,8 +9,8 @@ const PaHostApiIndex = Cint
|
||||||
const PaHostApiTypeId = Cint
|
const PaHostApiTypeId = Cint
|
||||||
# PaStream is always used as an opaque type, so we're always dealing
|
# PaStream is always used as an opaque type, so we're always dealing
|
||||||
# with the pointer
|
# with the pointer
|
||||||
const PaStream = Ptr{Void}
|
const PaStream = Ptr{Cvoid}
|
||||||
const PaStreamCallback = Void
|
const PaStreamCallback = Cvoid
|
||||||
const PaStreamFlags = Culong
|
const PaStreamFlags = Culong
|
||||||
|
|
||||||
const paNoFlag = PaStreamFlags(0x00)
|
const paNoFlag = PaStreamFlags(0x00)
|
||||||
|
@ -86,7 +86,7 @@ const pa_host_api_names = Dict{PaHostApiTypeId, String}(
|
||||||
14 => "AudioScience HPI"
|
14 => "AudioScience HPI"
|
||||||
)
|
)
|
||||||
|
|
||||||
type PaHostApiInfo
|
mutable struct PaHostApiInfo
|
||||||
struct_version::Cint
|
struct_version::Cint
|
||||||
api_type::PaHostApiTypeId
|
api_type::PaHostApiTypeId
|
||||||
name::Ptr{Cchar}
|
name::Ptr{Cchar}
|
||||||
|
@ -100,7 +100,7 @@ Pa_GetHostApiInfo(i) = unsafe_load(ccall((:Pa_GetHostApiInfo, libportaudio),
|
||||||
|
|
||||||
# Device Functions
|
# Device Functions
|
||||||
|
|
||||||
type PaDeviceInfo
|
mutable struct PaDeviceInfo
|
||||||
struct_version::Cint
|
struct_version::Cint
|
||||||
name::Ptr{Cchar}
|
name::Ptr{Cchar}
|
||||||
host_api::PaHostApiIndex
|
host_api::PaHostApiIndex
|
||||||
|
@ -126,15 +126,15 @@ Pa_GetDefaultOutputDevice() = ccall((:Pa_GetDefaultOutputDevice, libportaudio),
|
||||||
|
|
||||||
# Stream Functions
|
# Stream Functions
|
||||||
|
|
||||||
type Pa_StreamParameters
|
mutable struct Pa_StreamParameters
|
||||||
device::PaDeviceIndex
|
device::PaDeviceIndex
|
||||||
channelCount::Cint
|
channelCount::Cint
|
||||||
sampleFormat::PaSampleFormat
|
sampleFormat::PaSampleFormat
|
||||||
suggestedLatency::PaTime
|
suggestedLatency::PaTime
|
||||||
hostAPISpecificStreamInfo::Ptr{Void}
|
hostAPISpecificStreamInfo::Ptr{Cvoid}
|
||||||
end
|
end
|
||||||
|
|
||||||
type PaStreamInfo
|
mutable struct PaStreamInfo
|
||||||
structVersion::Cint
|
structVersion::Cint
|
||||||
inputLatency::PaTime
|
inputLatency::PaTime
|
||||||
outputLatency::PaTime
|
outputLatency::PaTime
|
||||||
|
@ -148,7 +148,7 @@ end
|
||||||
# err = ccall((:Pa_OpenDefaultStream, libportaudio),
|
# err = ccall((:Pa_OpenDefaultStream, libportaudio),
|
||||||
# PaError, (Ref{PaStream}, Cint, Cint,
|
# PaError, (Ref{PaStream}, Cint, Cint,
|
||||||
# PaSampleFormat, Cdouble, Culong,
|
# PaSampleFormat, Cdouble, Culong,
|
||||||
# Ref{Void}, Ref{Void}),
|
# Ref{Cvoid}, Ref{Cvoid}),
|
||||||
# streamPtr, inChannels, outChannels, sampleFormat, sampleRate,
|
# streamPtr, inChannels, outChannels, sampleFormat, sampleRate,
|
||||||
# framesPerBuffer, C_NULL, C_NULL)
|
# framesPerBuffer, C_NULL, C_NULL)
|
||||||
# handle_status(err)
|
# handle_status(err)
|
||||||
|
@ -166,7 +166,7 @@ function Pa_OpenStream(inParams, outParams,
|
||||||
Ptr{Pa_StreamParameters},
|
Ptr{Pa_StreamParameters},
|
||||||
Ptr{Pa_StreamParameters},
|
Ptr{Pa_StreamParameters},
|
||||||
Cdouble, Culong, PaStreamFlags,
|
Cdouble, Culong, PaStreamFlags,
|
||||||
Ptr{Void}, Ptr{Void}),
|
Ptr{Cvoid}, Ptr{Cvoid}),
|
||||||
streamPtr,
|
streamPtr,
|
||||||
inParams, outParams,
|
inParams, outParams,
|
||||||
sampleRate, framesPerBuffer, flags,
|
sampleRate, framesPerBuffer, flags,
|
||||||
|
@ -211,7 +211,7 @@ function Pa_ReadStream(stream::PaStream, buf::Array, frames::Integer=length(buf)
|
||||||
show_warnings::Bool=true)
|
show_warnings::Bool=true)
|
||||||
frames <= length(buf) || error("Need a buffer at least $frames long")
|
frames <= length(buf) || error("Need a buffer at least $frames long")
|
||||||
err = ccall((:Pa_ReadStream, libportaudio), PaError,
|
err = ccall((:Pa_ReadStream, libportaudio), PaError,
|
||||||
(PaStream, Ptr{Void}, Culong),
|
(PaStream, Ptr{Cvoid}, Culong),
|
||||||
stream, buf, frames)
|
stream, buf, frames)
|
||||||
handle_status(err, show_warnings)
|
handle_status(err, show_warnings)
|
||||||
buf
|
buf
|
||||||
|
@ -221,7 +221,7 @@ function Pa_WriteStream(stream::PaStream, buf::Array, frames::Integer=length(buf
|
||||||
show_warnings::Bool=true)
|
show_warnings::Bool=true)
|
||||||
frames <= length(buf) || error("Need a buffer at least $frames long")
|
frames <= length(buf) || error("Need a buffer at least $frames long")
|
||||||
err = ccall((:Pa_WriteStream, libportaudio), PaError,
|
err = ccall((:Pa_WriteStream, libportaudio), PaError,
|
||||||
(PaStream, Ptr{Void}, Culong),
|
(PaStream, Ptr{Cvoid}, Culong),
|
||||||
stream, buf, frames)
|
stream, buf, frames)
|
||||||
handle_status(err, show_warnings)
|
handle_status(err, show_warnings)
|
||||||
nothing
|
nothing
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
function init_pa_shim()
|
function find_pa_shim()
|
||||||
libdir = joinpath(dirname(@__FILE__), "..", "deps", "usr", "lib")
|
libdir = joinpath(dirname(@__FILE__), "..", "deps", "usr", "lib")
|
||||||
libsuffix = ""
|
libsuffix = ""
|
||||||
basename = "pa_shim"
|
basename = "pa_shim"
|
||||||
@static if is_linux() && Sys.ARCH == :x86_64
|
@static if Compat.Sys.islinux() && Sys.ARCH == :x86_64
|
||||||
libsuffix = "x86_64-linux-gnu"
|
libsuffix = "x86_64-linux-gnu"
|
||||||
elseif is_linux() && Sys.ARCH == :i686
|
elseif Compat.Sys.islinux() && Sys.ARCH == :i686
|
||||||
libsuffix = "i686-linux-gnu"
|
libsuffix = "i686-linux-gnu"
|
||||||
elseif is_apple() && Sys.ARCH == :x86_64
|
elseif Compat.Sys.isapple() && Sys.ARCH == :x86_64
|
||||||
libsuffix = "x86_64-apple-darwin14"
|
libsuffix = "x86_64-apple-darwin14"
|
||||||
elseif is_windows() && Sys.ARCH == :x86_64
|
elseif Compat.Sys.iswindows() && Sys.ARCH == :x86_64
|
||||||
libsuffix = "x86_64-w64-mingw32"
|
libsuffix = "x86_64-w64-mingw32"
|
||||||
elseif is_windows() && Sys.ARCH == :i686
|
elseif Compat.Sys.iswindows() && Sys.ARCH == :i686
|
||||||
libsuffix = "i686-w64-mingw32"
|
libsuffix = "i686-w64-mingw32"
|
||||||
elseif !any(
|
elseif !any(
|
||||||
(sfx) -> isfile(joinpath(libdir, "$basename.$sfx")),
|
(sfx) -> isfile(joinpath(libdir, "$basename.$sfx")),
|
||||||
|
@ -19,16 +19,11 @@ function init_pa_shim()
|
||||||
end
|
end
|
||||||
# if there's a suffix-less library, it was built natively on this machine,
|
# if there's a suffix-less library, it was built natively on this machine,
|
||||||
# so load that one first, otherwise load the pre-built one
|
# so load that one first, otherwise load the pre-built one
|
||||||
global const libpa_shim = Base.Libdl.find_library(
|
libpa_shim = Libdl.find_library(
|
||||||
[basename, "$(basename)_$libsuffix"],
|
[basename, "$(basename)_$libsuffix"],
|
||||||
[libdir])
|
[libdir])
|
||||||
libpa_shim == "" && error("Could not load $basename library, please file an issue at https://github.com/JuliaAudio/RingBuffers.jl/issues with your `versioninfo()` output")
|
libpa_shim == "" && error("Could not load $basename library, please file an issue at https://github.com/JuliaAudio/RingBuffers.jl/issues with your `versioninfo()` output")
|
||||||
shim_dlib = Libdl.dlopen(libpa_shim)
|
return libpa_shim
|
||||||
# pointer to the shim's process callback
|
|
||||||
global const shim_processcb_c = Libdl.dlsym(shim_dlib, :pa_shim_processcb)
|
|
||||||
if shim_processcb_c == C_NULL
|
|
||||||
error("Got NULL pointer loading `pa_shim_processcb`")
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
const pa_shim_errmsg_t = Cint
|
const pa_shim_errmsg_t = Cint
|
||||||
|
@ -43,19 +38,10 @@ mutable struct pa_shim_info_t
|
||||||
outputbuf::Ptr{PaUtilRingBuffer} # ringbuffer for output
|
outputbuf::Ptr{PaUtilRingBuffer} # ringbuffer for output
|
||||||
errorbuf::Ptr{PaUtilRingBuffer} # ringbuffer to send error notifications
|
errorbuf::Ptr{PaUtilRingBuffer} # ringbuffer to send error notifications
|
||||||
sync::Cint # keep input/output ring buffers synchronized (0/1)
|
sync::Cint # keep input/output ring buffers synchronized (0/1)
|
||||||
notifycb::Ptr{Void} # Julia callback to notify on updates (called from audio thread)
|
notifycb::Ptr{Cvoid} # Julia callback to notify on updates (called from audio thread)
|
||||||
inputhandle::Ptr{Void} # condition to notify on new input data
|
inputhandle::Ptr{Cvoid} # condition to notify on new input data
|
||||||
outputhandle::Ptr{Void} # condition to notify when ready for output
|
outputhandle::Ptr{Cvoid} # condition to notify when ready for output
|
||||||
errorhandle::Ptr{Void} # condition to notify on new errors
|
errorhandle::Ptr{Cvoid} # condition to notify on new errors
|
||||||
end
|
end
|
||||||
|
|
||||||
"""
|
Base.unsafe_convert(::Type{Ptr{Cvoid}}, info::pa_shim_info_t) = pointer_from_objref(info)
|
||||||
PortAudio.shimhash()
|
|
||||||
|
|
||||||
Return the sha256 hash(as a string) of the source file used to build the shim.
|
|
||||||
We may use this sometime to verify that the distributed binary stays in sync
|
|
||||||
with the rest of the package.
|
|
||||||
"""
|
|
||||||
shimhash() = unsafe_string(
|
|
||||||
ccall((:pa_shim_getsourcehash, libpa_shim), Cstring, ()))
|
|
||||||
Base.unsafe_convert(::Type{Ptr{Void}}, info::pa_shim_info_t) = pointer_from_objref(info)
|
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
macro suppress_err(block)
|
macro suppress_err(block)
|
||||||
quote
|
quote
|
||||||
if ccall(:jl_generating_output, Cint, ()) == 0
|
if ccall(:jl_generating_output, Cint, ()) == 0
|
||||||
ORIGINAL_STDERR = STDERR
|
ORIGINAL_STDERR = stderr
|
||||||
err_rd, err_wr = redirect_stderr()
|
err_rd, err_wr = redirect_stderr()
|
||||||
err_reader = @async readstring(err_rd)
|
err_reader = @async read(err_rd, String)
|
||||||
end
|
end
|
||||||
|
|
||||||
value = $(esc(block))
|
value = $(esc(block))
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#!/usr/bin/env julia
|
#!/usr/bin/env julia
|
||||||
|
|
||||||
using Base.Test
|
using Compat
|
||||||
|
using Compat.Test
|
||||||
|
import Compat: Cvoid
|
||||||
using TestSetExtensions
|
using TestSetExtensions
|
||||||
using PortAudio
|
using PortAudio
|
||||||
using SampledSignals
|
using SampledSignals
|
||||||
|
@ -34,7 +36,7 @@ function setup_callback(inchans, outchans, nframes, synced)
|
||||||
|
|
||||||
function processfunc()
|
function processfunc()
|
||||||
ccall(shim_processcb_c, Cint,
|
ccall(shim_processcb_c, Cint,
|
||||||
(Ptr{Float32}, Ptr{Float32}, Culong, Ptr{Void}, Culong, Ptr{Void}),
|
(Ptr{Float32}, Ptr{Float32}, Culong, Ptr{Cvoid}, Culong, Ptr{Cvoid}),
|
||||||
cb_input, cb_output, nframes, C_NULL, flags, pointer_from_objref(info))
|
cb_input, cb_output, nframes, C_NULL, flags, pointer_from_objref(info))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -5,13 +5,13 @@
|
||||||
include("runtests.jl")
|
include("runtests.jl")
|
||||||
|
|
||||||
# these default values are specific to my machines
|
# these default values are specific to my machines
|
||||||
if is_windows()
|
if Compat.Sys.iswindows()
|
||||||
default_indev = "Microphone Array (Realtek High "
|
default_indev = "Microphone Array (Realtek High "
|
||||||
default_outdev = "Speaker/Headphone (Realtek High"
|
default_outdev = "Speaker/Headphone (Realtek High"
|
||||||
elseif is_apple()
|
elseif Compat.Sys.isapple()
|
||||||
default_indev = "Built-in Microph"
|
default_indev = "Built-in Microphone"
|
||||||
default_outdev = "Built-in Output"
|
default_outdev = "Built-in Output"
|
||||||
elseif is_linux()
|
elseif Compat.Sys.islinux()
|
||||||
default_indev = "default"
|
default_indev = "default"
|
||||||
default_outdev = "default"
|
default_outdev = "default"
|
||||||
end
|
end
|
||||||
|
@ -50,12 +50,12 @@ end
|
||||||
write(stream, buf)
|
write(stream, buf)
|
||||||
io = IOBuffer()
|
io = IOBuffer()
|
||||||
show(io, stream)
|
show(io, stream)
|
||||||
@test String(take!(io)) == """
|
@test Compat.occursin("""
|
||||||
PortAudio.PortAudioStream{Float32}
|
PortAudioStream{Float32}
|
||||||
Samplerate: 44100.0Hz
|
Samplerate: 44100.0Hz
|
||||||
Buffer Size: 4096 frames
|
Buffer Size: 4096 frames
|
||||||
2 channel sink: "$default_outdev"
|
2 channel sink: "$default_outdev"
|
||||||
2 channel source: "$default_indev\""""
|
2 channel source: "$default_indev\"""", String(take!(io)))
|
||||||
close(stream)
|
close(stream)
|
||||||
end
|
end
|
||||||
@testset "Error on wrong name" begin
|
@testset "Error on wrong name" begin
|
||||||
|
@ -68,8 +68,8 @@ end
|
||||||
buf = SampleBuf(rand(eltype(stream), 48000, nchannels(stream.sink))*0.1, samplerate(stream))
|
buf = SampleBuf(rand(eltype(stream), 48000, nchannels(stream.sink))*0.1, samplerate(stream))
|
||||||
t1 = @async write(stream, buf)
|
t1 = @async write(stream, buf)
|
||||||
t2 = @async write(stream, buf)
|
t2 = @async write(stream, buf)
|
||||||
@test wait(t1) == 48000
|
@test fetch(t1) == 48000
|
||||||
@test wait(t2) == 48000
|
@test fetch(t2) == 48000
|
||||||
flush(stream)
|
flush(stream)
|
||||||
close(stream)
|
close(stream)
|
||||||
end
|
end
|
||||||
|
@ -78,8 +78,8 @@ end
|
||||||
buf = SampleBuf(rand(eltype(stream), 48000, nchannels(stream.source))*0.1, samplerate(stream))
|
buf = SampleBuf(rand(eltype(stream), 48000, nchannels(stream.source))*0.1, samplerate(stream))
|
||||||
t1 = @async read!(stream, buf)
|
t1 = @async read!(stream, buf)
|
||||||
t2 = @async read!(stream, buf)
|
t2 = @async read!(stream, buf)
|
||||||
@test wait(t1) == 48000
|
@test fetch(t1) == 48000
|
||||||
@test wait(t2) == 48000
|
@test fetch(t2) == 48000
|
||||||
close(stream)
|
close(stream)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in a new issue