diff --git a/README.md b/README.md
index e19230e..1175182 100644
--- a/README.md
+++ b/README.md
@@ -106,7 +106,8 @@ AudioStream is an abstract type, which currently has a PortAudioStream subtype
 that writes to the sound card, and a TestAudioStream that is used in the unit
 tests.
 
-Currently only 1 stream at a time is supported so there's no reason to provide
+With the method PortAudioStream, which uses the default input and output device(s), 
+only 1 stream at a time is supported, so there's no reason to provide
 an explicit stream to the `play` function. The stream has a root mixer field
 which is an instance of the AudioMixer type, so that multiple AudioNodes
 can be heard at the same time. Whenever a new frame of audio is needed by the
@@ -114,6 +115,22 @@ sound card, the stream calls the `render` method on the root audio mixer, which
 will in turn call the `render` methods on any input AudioNodes that are set
 up as inputs.
 
+When a Pa_AudioStream is created via a call to 
+Pa_AudioStream(device_index, channels=2, input=false,
+                              sample_rate::Integer=44100,
+                              framesPerBuffer::Integer=2048,
+                              show_warnings::Bool=false,
+                              sample_format::PaSampleFormat=paInt16,
+                              callback=0)
+a single stream is opened for reading or writing. This returns a Pa_AudioStream on success, 
+which is used either via the functions AudioIO.read(::Pa_AudioStream) or 
+AudioIO.write(::Pa_AudioStream, buffer) for read and write respectively.
+
+If nonblocking I/O is needed, a callback may be passed to the Pa_AudioStream constructor, 
+which is provided by the user and should return a buffer of frames if used for output and should
+handle a buffer of frames as an argument if used as input. This is similar
+to the methods used by PyAudio's python interface to PortAudio. See the examples also.
+
 Installation
 ------------
 
diff --git a/REQUIRE b/REQUIRE
index a613e52..754bd86 100644
--- a/REQUIRE
+++ b/REQUIRE
@@ -1,4 +1,5 @@
 julia 0.3-
 BinDeps
+Compat
 @osx Homebrew
 @windows WinRPM
diff --git a/examples/callback_bands.jl b/examples/callback_bands.jl
new file mode 100644
index 0000000..e770720
--- /dev/null
+++ b/examples/callback_bands.jl
@@ -0,0 +1,34 @@
+# -*- coding: utf-8 -*-
+
+# Examples for Julia AudioIO module
+
+# display relative (not absolute) dB of bass, mid, treble bands
+
+using AudioIO, DSP
+
+
+"""
+Custom callback for read, processes passed data array
+"""
+function process_read(buf)
+    fchunk = map(Float64, buf)
+    pgram = welch_pgram(fchunk, 4096, 0, fs=SRATE*CHANNELS)
+    pxx = power(pgram)
+    frqs = freq(pgram)
+    bass = log(sum(abs(pxx[(frqs .<= 640.0) & (frqs .> 100.0)])))
+    midrange = log(sum(abs(pxx[(frqs .<= 5120.0) & (frqs .> 640.0)])))
+    treble = log(sum(abs(pxx[(frqs .<= 20480.0) & (frqs .> 5120.0)])))
+    println("bass $bass, midrange $midrange, treble $treble")
+end
+
+CHUNKSIZE = 40960
+FORMAT = AudioIO.paInt16
+CHANNELS = Cint(2)
+SRATE = 44100
+istream = AudioIO.open_read(Cint(0), CHANNELS, SRATE, CHUNKSIZE,
+                            false, FORMAT, process_read)
+println("Starting callback type reading, control-C to stop")
+
+while true
+    sleep(20)
+end
diff --git a/examples/callback_read_write.jl b/examples/callback_read_write.jl
new file mode 100644
index 0000000..ca7fa42
--- /dev/null
+++ b/examples/callback_read_write.jl
@@ -0,0 +1,92 @@
+# -*- coding: utf-8 -*-
+
+# Examples for Julia AudioIO module
+
+using AudioIO
+
+CHUNKSIZE = 40960
+FORMAT = AudioIO.paInt16
+CALLBACK_DATATYPE = AudioIO.PaSampleFormat_to_T(FORMAT)
+CHANNELS = 2
+SRATE = 44100
+RECORD_SECONDS = 3
+
+BUFFER = zeros(Int16, SRATE * RECORD_SECONDS * 4)
+BUFSIZE = SRATE * RECORD_SECONDS
+
+"""
+choose the devices for 2 channel IO
+"""
+function choose_input_output()
+    devices = get_audio_devices()
+    indev = -1
+    outdev = -1
+    for aud in devices
+        println("$(aud.device_index) $(aud.name)")
+        if (aud.max_input_channels == CHANNELS) & (indev == -1 )
+            indev = aud.device_index
+        end
+        if(aud.max_output_channels == CHANNELS) & (outdev == -1)
+            outdev = aud.device_index
+        end
+    end
+    if indev == -1
+        info("Appropriate input device not found.")
+    elseif outdev == -1
+        info("Appropriate output device not found.")
+    else
+        info("Using input device ", bytestring(devices[indev + 1].name), 
+             ", number ", devices[indev + 1].device_index, 
+             " and output device ", bytestring(devices[outdev + 1].name), 
+             ", number ", devices[outdev + 1].device_index)
+    end
+    return indev, outdev
+end
+
+read_position = 0
+"""
+Custom callback for read, processes passed data array
+"""
+function store_read(buf)
+    read_size = length(buf)
+    global read_position
+    if read_position + read_size > length(BUFFER)
+        read_size = length(BUFFER) - read_position
+    end
+    if read_size > 0
+        BUFFER[read_position + 1 : read_position + read_size] = 
+            buf[1: read_size]
+        read_position += read_size
+    end
+end
+
+write_position = 0
+"""
+Custom callback for write, returns data array
+"""
+function get_writeable()
+    write_size = CHUNKSIZE * CHANNELS
+    global write_position
+    if write_position + write_size > length(BUFFER)
+        write_position = length(BUFFER) - write_size
+        retval = 1
+    end
+    start_position = write_position + 1
+    write_position += write_size
+    buf = BUFFER[start_position: write_position]
+    buf
+end
+
+INS, OUTS = choose_input_output()
+
+istream = AudioIO.open_read(INS, CHANNELS, SRATE, CHUNKSIZE,
+                            false, FORMAT, store_read)
+println("Started callback type reading device number $INS")
+sleep(5)
+AudioIO.Pa_CloseStream(istream.stream)
+
+ostream = AudioIO.open_write(OUTS, CHANNELS, SRATE, CHUNKSIZE, 
+                             false, FORMAT, get_writeable)
+println("Started callback type writing device number $OUTS")
+sleep(3)
+AudioIO.Pa_CloseStream(ostream.stream)
diff --git a/examples/read_and_write.jl b/examples/read_and_write.jl
new file mode 100644
index 0000000..5f27098
--- /dev/null
+++ b/examples/read_and_write.jl
@@ -0,0 +1,110 @@
+# -*- coding: utf-8 -*-
+
+# Examples for Julia AudioIO module
+
+using AudioIO
+
+CHUNKSIZE = 40960
+FORMAT = AudioIO.paInt16
+CHANNELS = 2
+SRATE = 44100
+RECORD_SECONDS = 3
+
+BUFFER = zeros(Int16, SRATE * RECORD_SECONDS * 4)
+BUFSIZE = SRATE * RECORD_SECONDS
+
+"""
+choose the devices for 2 channel IO
+"""
+function choose_input_output()
+    devices = get_audio_devices()
+    indev = -1
+    outdev = -1
+    for aud in devices
+        println("$(aud.device_index) $(aud.name)")
+        if (aud.max_input_channels == CHANNELS) & (indev == -1 )
+            indev = aud.device_index
+        end
+        if(aud.max_output_channels == CHANNELS) & (outdev == -1)
+            outdev = aud.device_index
+        end
+    end
+    if indev == -1
+        info("Appropriate input device not found.")
+    elseif outdev == -1
+        info("Appropriate output device not found.")
+    else
+        info("Using input device ", bytestring(devices[indev + 1].name), 
+             ", number ", devices[indev + 1].device_index, 
+             " and output device ", bytestring(devices[outdev + 1].name), 
+             ", number ", devices[outdev + 1].device_index)
+    end
+    return indev, outdev
+end
+
+"""
+read from input
+"""
+function read_blocking(devnum, buffer)
+    instream = AudioIO.open_read(devnum, CHANNELS, SRATE, CHUNKSIZE)
+    buf = AudioIO.read(instream, BUFSIZE)
+    buflen = length(buf)
+    buffer[1: buflen] = buf[1: buflen]
+    AudioIO.Pa_CloseStream(instream.stream)
+end
+
+"""
+write to output
+"""
+function write_blocking(devnum, buffer)
+    outstream = AudioIO.open_write(devnum, CHANNELS, SRATE, CHUNKSIZE)
+    AudioIO.write(outstream, buffer)
+    AudioIO.Pa_CloseStream(outstream.stream)
+end
+
+"""
+Create a string of numbers representing a sinewave audio tone
+"""
+function make_note_buffer(frequency, amplitude, duration, srate)
+    N = round(Int, srate / frequency)
+    T = round(Int, frequency * duration)  # repeat for T cycles
+    dt = 1.0 / srate
+    tone = zeros(Int16, (N + N) * T)
+    idx = 1
+    while idx < (N + N) * T
+        tone[idx] = round(Int, amplitude * sin(2 * pi * frequency * 
+                                idx * dt) * 32767.0)
+        tone[idx + 1] = tone[idx]
+        idx += 2
+    end
+    tone
+end
+
+"""
+Write a note to output device
+"""
+function play_note(frequency, amplitude, duration, srate, ostream)
+    note = make_note_buffer(frequency, amplitude, duration, srate)
+    AudioIO.write(ostream, note)
+end
+
+INS, OUTS = choose_input_output()
+
+read_blocking(INS, BUFFER)
+println("Finished blocking type reading device number $INS")
+println("Recording volume is $(mean(abs(BUFFER))*(100/16783))% of max")
+sleep(2)
+
+write_blocking(OUTS, BUFFER)
+println("Finished blocking type writing device number $OUTS")
+
+outstream = AudioIO.open_write(OUTS, CHANNELS, SRATE, CHUNKSIZE)
+# play the C major scale
+scale = [130.8, 146.8, 164.8, 174.6, 195.0, 220.0, 246.9, 261.6]
+for note in scale
+    play_note(note, 0.1, 0.75, SRATE, outstream)
+end
+# up an octave
+for note in scale[2:8]
+    play_note(2*note, 0.1, 0.75, SRATE, outstream)
+end
diff --git a/examples/record_to_wav.jl b/examples/record_to_wav.jl
new file mode 100644
index 0000000..3d9bde8
--- /dev/null
+++ b/examples/record_to_wav.jl
@@ -0,0 +1,78 @@
+# -*- coding: utf-8 -*-
+
+# Examples for Julia AudioIO module
+
+using AudioIO
+using WAV
+
+CHUNKSIZE = 40960
+FORMAT = AudioIO.paInt16
+CHANNELS = 2
+SRATE = 44100
+RECORD_SECONDS = 20
+
+"""
+choose the devices for 2 channel IO
+"""
+function choose_input_output()
+    devices = get_audio_devices()
+    indev = -1
+    outdev = -1
+    for aud in devices
+        println("$(aud.device_index) $(aud.name)")
+        if (aud.max_input_channels == CHANNELS) & (indev == -1 )
+            indev = aud.device_index
+        end
+        if(aud.max_output_channels == CHANNELS) & (outdev == -1)
+            outdev = aud.device_index
+        end
+    end
+    if indev == -1
+        info("Appropriate input device not found.")
+    elseif outdev == -1
+        info("Appropriate output device not found.")
+    else
+        info("Using input device ", bytestring(devices[indev + 1].name), 
+             ", number ", devices[indev + 1].device_index, 
+             " and output device ", bytestring(devices[outdev + 1].name), 
+             ", number ", devices[outdev + 1].device_index)
+    end
+    return indev, outdev
+end
+
+"""
+read from input
+"""
+function record_audio(devnum, seconds)
+    instream = AudioIO.open_read(devnum, CHANNELS, SRATE, CHUNKSIZE)
+    bufsize = seconds * SRATE
+    buf = AudioIO.read(instream, bufsize)
+    AudioIO.Pa_CloseStream(instream.stream)
+    buf
+end
+
+"""
+write to WAV file
+"""
+function write_as_WAV(buffer, filename="temp.WAV")
+    fio = open(filename, "w")
+    WAV.wavwrite(deinterlace_stereo(buffer), fio, Fs=SRATE)
+end
+
+"""
+interlaced to noninterlaced stereo data
+"""
+function deinterlace_stereo(buffer)
+    reshape([buffer[1:2:end]; buffer[2:2:end]], 
+            (floor(Int, length(buffer)/2), 2))
+end
+
+INS, OUTS = choose_input_output()
+
+println("Starting recording...")
+BUF = record_audio(INS, RECORD_SECONDS)
+println("Finished reading from device number $INS")
+println("Recording volume was $(mean(abs(BUF))*(100/16783))% of max")
+
+write_as_WAV(BUF)
+println("Finished writing to WAV file.")
diff --git a/src/AudioIO.jl b/src/AudioIO.jl
index 644ad8f..9256f60 100644
--- a/src/AudioIO.jl
+++ b/src/AudioIO.jl
@@ -1,7 +1,9 @@
 module AudioIO
+using Compat
+importall Base.Operators
 
 # export the basic API
-export play, stop, get_audio_devices
+export play, stop, get_audio_devices, open_read, open_write, read, write
 
 # default stream used when none is given
 _stream = nothing
diff --git a/src/nodes.jl b/src/nodes.jl
index daca2cd..0f142b1 100644
--- a/src/nodes.jl
+++ b/src/nodes.jl
@@ -13,7 +13,7 @@ end
 
 # Generates a sin tone at the given frequency
 
-type SinOscRenderer{T<:Union(Float32, AudioNode)} <: AudioRenderer
+@compat type SinOscRenderer{T<:Union{Float32, AudioNode}} <: AudioRenderer
     freq::T
     phase::Float32
     buf::AudioBuf
@@ -124,7 +124,7 @@ end
 Base.push!(mixer::AudioMixer, node::AudioNode) = push!(mixer.renderer.inputs, node)
 
 #### Gain ####
-type GainRenderer{T<:Union(Float32, AudioNode)} <: AudioRenderer
+@compat type GainRenderer{T<:Union{Float32, AudioNode}} <: AudioRenderer
     in1::AudioNode
     in2::T
     buf::AudioBuf
@@ -228,7 +228,7 @@ function play(arr::AudioBuf, args...)
 end
 
 # If the array is the wrong floating type, convert it
-function play{T <: FloatingPoint}(arr::Array{T}, args...)
+@compat function play{T <: AbstractFloat}(arr::Array{T}, args...)
     arr = convert(AudioBuf, arr)
     play(arr, args...)
 end
diff --git a/src/portaudio.jl b/src/portaudio.jl
index 6b081bb..72e2ccd 100644
--- a/src/portaudio.jl
+++ b/src/portaudio.jl
@@ -1,14 +1,15 @@
 typealias PaTime Cdouble
 typealias PaError Cint
 typealias PaSampleFormat Culong
-# PaStream is always used as an opaque type, so we're always dealing with the
-# pointer
+# PaStream is always used as an opaque type, so we're always dealing 
+# with the pointer
 typealias PaStream Ptr{Void}
 typealias PaDeviceIndex Cint
 typealias PaHostApiIndex Cint
 typealias PaTime Cdouble
 typealias PaHostApiTypeId Cint
 typealias PaStreamCallback Void
+typealias PaStreamFlags Culong
 
 const PA_NO_ERROR = 0
 const PA_INPUT_OVERFLOWED = -10000 + 19
@@ -22,7 +23,7 @@ const paInt8    = convert(PaSampleFormat, 0x10)
 const paUInt8   = convert(PaSampleFormat, 0x20)
 
 # PaHostApiTypeId values
-const pa_host_api_names = {
+@compat const pa_host_api_names = (
     0 => "In Development", # use while developing support for a new host API
     1 => "Direct Sound",
     2 => "MME",
@@ -37,7 +38,7 @@ const pa_host_api_names = {
     12 => "Jack",
     13 => "WASAPI",
     14 => "AudioScience HPI"
-}
+)
 
 # track whether we've already inited PortAudio
 portaudio_inited = false
@@ -81,6 +82,203 @@ function destroy(stream::PortAudioStream)
     portaudio_inited = false
 end
 
+type CCallbackTimeInfo
+   inAdc::Cdouble
+   current::Cdouble
+   outAdc::Cdouble
+end
+
+typealias PaStreamCallbackFlags Culong
+
+type CCallbackUdata
+    func::Function
+    sample_format::PaSampleFormat
+    channels::Cint
+    is_read::Bool
+end
+
+type Pa_StreamParameters
+    device::PaDeviceIndex
+    channelCount::Cint
+    sampleFormat::PaSampleFormat
+    suggestedLatency::PaTime
+    hostAPISpecificStreamInfo::Ptr{Void}
+end
+
+"""
+    Open a single stream, not necessarily the default one
+    The stream is unidirectional, either input or default output
+    see http://portaudio.com/docs/v19-doxydocs/portaudio_8h.html
+"""
+function Pa_OpenStream(device::PaDeviceIndex, channels::Integer, 
+                       input::Bool, sampleFormat::PaSampleFormat,
+                       sampleRate::Cdouble, framesPerBuffer::Culong,
+                       callback, udata)
+    streamPtr::Array{PaStream} = PaStream[1]
+    ioParameters = Pa_StreamParameters(device, Cint(channels), 
+                                       sampleFormat, PaTime(0.001), 
+                                       Ptr{Void}(0))
+    streamcallback = Ptr{PaStreamCallback}(callback) 
+    if input
+        err = ccall((:Pa_OpenStream, libportaudio), PaError, 
+                    (PaStream, Ref{Pa_StreamParameters}, Ptr{Void},
+                    Cdouble, Culong, Culong, 
+                    Ptr{PaStreamCallback}, Ptr{Void}),
+                    streamPtr, ioParameters, Ptr{Void}(0),
+                    sampleRate, framesPerBuffer, 0, 
+                    streamcallback, Ptr{Void}(udata))
+    else
+        err = ccall((:Pa_OpenStream, libportaudio), PaError, 
+                    (PaStream, Ptr{Void}, Ref{Pa_StreamParameters},
+                    Cdouble, Culong, Culong,
+                    Ptr{PaStreamCallback}, Ptr{Void}),
+                    streamPtr, Ptr{Void}(0), ioParameters,
+                    sampleRate, framesPerBuffer, 0, 
+                    streamcallback, Ptr{Void}(udata))
+    end             
+    handle_status(err)
+    streamPtr[1]
+end
+
+type Pa_AudioStream <: AudioStream
+    root::AudioMixer
+    info::DeviceInfo
+    show_warnings::Bool
+    stream::PaStream
+    sformat::PaSampleFormat
+    channels::Integer
+    framesPerBuffer::Integer
+
+    """ 
+        Get device parameters needed for opening with portaudio
+        default is output as 44100/16bit int, same as CD audio type input
+        callback is optional, otherwise use blocing read and write functions
+        the callback must be a function that, if for writing, can return as an argument
+        a buffer the size and type same as stream.sbuffer, or if for output should 
+    """
+    function Pa_AudioStream(device_index, channels=2, input=false,
+                              sample_rate::Integer=44100,
+                              framesPerBuffer::Integer=2048,
+                              show_warnings::Bool=false,
+                              sample_format::PaSampleFormat=paInt16,
+                              callback=0, udata=0)
+        require_portaudio_init()
+        if (callback != 0) & (udata == 0)
+            # need to make a callback udata package
+            udata = CCallbackUdata(callback, sample_format, channels, input)
+            callback = pa_callback
+        end
+        stream = Pa_OpenStream(device_index, channels, input, sample_format,
+                               Cdouble(sample_rate), Culong(framesPerBuffer),
+                               callback, pointer_from_objref(udata))
+        Pa_StartStream(stream)
+        root = AudioMixer()
+        this = new(root, DeviceInfo(sample_rate, framesPerBuffer), 
+                   show_warnings, stream, sample_format, 
+                   channels, framesPerBuffer)
+    end
+end
+
+function open_read(device_index, channels=2,
+                   sample_rate::Integer=44100, 
+                   framesPerBuffer::Integer=2048,
+                   show_warnings::Bool=false,
+                   sample_format::PaSampleFormat=paInt16,
+                   callback=0)
+    Pa_AudioStream(device_index, channels, true, sample_rate,
+                   framesPerBuffer, show_warnings,
+                   sample_format, callback)
+end
+
+function open_write(device_index, channels=2,
+                   sample_rate::Integer=44100, 
+                   framesPerBuffer::Integer=2048,
+                   show_warnings::Bool=false,
+                   sample_format::PaSampleFormat=paInt16,
+                   callback=0)
+    Pa_AudioStream(device_index, channels, false, sample_rate,
+                   framesPerBuffer, show_warnings,
+                   sample_format, callback)
+end
+
+"""
+Blocking read from a Pa_AudioStream that is open as input
+"""
+function read(stream::Pa_AudioStream, nframes::Int)
+    datatype = PaSampleFormat_to_T(stream.sformat)
+    buf = zeros(datatype, stream.framesPerBuffer * stream.channels)
+    return_buffer = zeros(datatype, nframes * stream.channels)
+    cur = 0
+    read_needed = nframes
+    while read_needed > 0
+        read_size = min(read_needed, stream.framesPerBuffer)
+        used = read_size * stream.channels
+        while Pa_GetStreamReadAvailable(stream.stream) < read_size
+            sleep(0.001)
+            yield()
+        end
+        err = ccall((:Pa_ReadStream, libportaudio), PaError,
+                    (PaStream, Ptr{Void}, Culong),
+                    stream.stream, buf, read_size)
+        handle_status(err, stream.show_warnings)
+        return_buffer[cur + 1: cur + used] = buf[1:used]
+        cur = cur + used
+        read_needed -= read_size
+    end
+    return_buffer
+end
+
+"""
+Blocking write to a Pa_AudioStream that is open for output
+"""
+function write(ostream::Pa_AudioStream, buffer)
+    cur = 0
+    write_needed = length(buffer)
+    while write_needed > 0
+        write_size = min(write_needed, ostream.framesPerBuffer)
+        while Pa_GetStreamWriteAvailable(ostream.stream) < write_size
+            sleep(0.001)
+            yield()
+        end
+        end_cur = cur + write_size
+        err = ccall((:Pa_WriteStream, libportaudio), PaError,
+                    (PaStream, Ptr{Void}, Culong), ostream.stream, 
+                    buffer[cur + 1: end_cur], 
+                    Culong(write_size/ostream.channels))
+        handle_status(err, ostream.show_warnings)
+        write_needed -= write_size
+        cur = end_cur
+    end
+    0
+end
+
+"""
+Take the c callback, restore types, pass to the callback functions
+"""
+function callback_wrapper(input::Ptr{Void}, output::Ptr{Void}, 
+                               frameCount::Culong, 
+                               timeInfo::Ptr{AudioIO.CCallbackTimeInfo}, 
+                               sflags::Culong, udata::Ptr{Void})
+    ("$udata")  # workaround, get julia to prep for the dereference 
+    cudata = unsafe_pointer_to_objref(Ptr{CCallbackUdata}(udata))
+    datatype = PaSampleFormat_to_T(cudata.sample_format)
+    if cudata.is_read
+        indata = pointer_to_array(Ptr{datatype}(input), 
+                            (frameCount * cudata.channels, ))
+        cudata.func(indata)
+    else
+        outdata = (cudata.func)()
+        ccall(:memcpy, Ptr{Void}, (Ptr{Void}, Ptr{Void}, Cint), 
+              output, outdata, length(outdata) * sizeof(outdata[1]))    
+    end
+    Cint(0)
+end
+
+const pa_callback = cfunction(callback_wrapper, Cint, (Ptr{Void}, 
+                              Ptr{Void}, 
+                              Culong, Ptr{AudioIO.CCallbackTimeInfo}, 
+                              Culong, Ptr{Void}))
+
 ############ Internal Functions ############
 
 function portaudio_task(stream::PortAudioStream)
@@ -112,6 +310,30 @@ function portaudio_task(stream::PortAudioStream)
     end
 end
 
+"""
+Helper function to make the right type of buffer for various 
+sample formats. Converts PaSampleFormat to a typeof
+"""
+function PaSampleFormat_to_T(fmt::PaSampleFormat)
+    retval = UInt8(0x0)
+    if fmt == 1
+        retval = Float32(1.0)
+    elseif fmt == 2
+        retval = Int32(0x02)
+    elseif fmt == 4
+        retval = Int24(0x04)
+    elseif fmt == 8
+        retval = Int16(0x08)
+    elseif fmt == 16
+        retval = Int8(0x10)
+    elseif fmt == 32
+        retval = UInt8(0x20)
+    else
+        info("Flawed input to PaSampleFormat_to_T, primitive unknown")
+    end
+    typeof(retval)
+end
+
 type PaDeviceInfo
     struct_version::Cint
     name::Ptr{Cchar}
@@ -134,21 +356,23 @@ type PaHostApiInfo
     defaultOutputDevice::PaDeviceIndex
 end
 
-type PortAudioInterface <: AudioInterface
-    name::String
-    host_api::String
+@compat type PortAudioInterface <: AudioInterface
+    name::AbstractString
+    host_api::AbstractString
     max_input_channels::Int
     max_output_channels::Int
+    device_index::PaDeviceIndex
 end
 
 function get_portaudio_devices()
     require_portaudio_init()
     device_count = ccall((:Pa_GetDeviceCount, libportaudio), PaDeviceIndex, ())
-    pa_devices = [Pa_GetDeviceInfo(i) for i in 0:(device_count - 1)]
-    [PortAudioInterface(bytestring(d.name),
-                        bytestring(Pa_GetHostApiInfo(d.host_api).name),
-                        d.max_input_channels,
-                        d.max_output_channels)
+    pa_devices = [ [Pa_GetDeviceInfo(i), i] for i in 0:(device_count - 1)]
+    [PortAudioInterface(bytestring(d[1].name),
+                        bytestring(Pa_GetHostApiInfo(d[1].host_api).name),
+                        d[1].max_input_channels,
+                        d[1].max_output_channels,
+                        d[2])
      for d in pa_devices]
 end
 
diff --git a/src/sndfile.jl b/src/sndfile.jl
index b8ac331..66fd589 100644
--- a/src/sndfile.jl
+++ b/src/sndfile.jl
@@ -1,7 +1,7 @@
 export af_open, FilePlayer, rewind, samplerate
 
-const SFM_READ = int32(0x10)
-const SFM_WRITE = int32(0x20)
+@compat const SFM_READ = Int32(0x10)
+@compat const SFM_WRITE = Int32(0x20)
 
 const SF_FORMAT_WAV =  0x010000
 const SF_FORMAT_FLAC = 0x170000
@@ -16,10 +16,10 @@ const SF_SEEK_SET = 0
 const SF_SEEK_CUR = 1
 const SF_SEEK_END = 2
 
-const EXT_TO_FORMAT = [
+@compat const EXT_TO_FORMAT = (
     ".wav" => SF_FORMAT_WAV,
     ".flac" => SF_FORMAT_FLAC
-]
+)
 
 type SF_INFO
     frames::Int64
@@ -45,7 +45,7 @@ samplerate(f::AudioFile) = f.sfinfo.samplerate
 
 # AudioIO.open is part of the public API, but is not exported so that it
 # doesn't conflict with Base.open
-function open(path::String, mode::String = "r",
+@compat function open(path::AbstractString, mode::AbstractString = "r",
             sampleRate::Integer = 44100, channels::Integer = 1,
             format::Integer = 0)
     @assert channels <= 2
@@ -180,7 +180,7 @@ end
 
 typealias FilePlayer AudioNode{FileRenderer}
 FilePlayer(file::AudioFile) = FilePlayer(FileRenderer(file))
-FilePlayer(path::String) = FilePlayer(AudioIO.open(path))
+@compat FilePlayer(path::AbstractString) = FilePlayer(AudioIO.open(path))
 
 function render(node::FileRenderer, device_input::AudioBuf, info::DeviceInfo)
     @assert node.file.sfinfo.samplerate == info.sample_rate
@@ -204,7 +204,7 @@ function render(node::FileRenderer, device_input::AudioBuf, info::DeviceInfo)
     end
 end
 
-function play(filename::String, args...)
+@compat function play(filename::AbstractString, args...)
     player = FilePlayer(filename)
     play(player, args...)
 end