Skip to content

Commit

Permalink
Merge 0af392d into 9a097e8
Browse files Browse the repository at this point in the history
  • Loading branch information
nocarryr committed Jun 14, 2019
2 parents 9a097e8 + 0af392d commit 1443145
Show file tree
Hide file tree
Showing 20 changed files with 302 additions and 170 deletions.
11 changes: 11 additions & 0 deletions .coveragerc
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
[run]
source = cysounddevice/*
plugins = Cython.Coverage

[report]
exclude_lines =
pragma: no cover
def __dealloc__
raise MemoryError
raise NotImplementedError
return NotImplemented
26 changes: 26 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
language: python
matrix:
include:
- python: "3.6"
sudo: required
env:
- ALLOW_DEPLOY=false
- python: "3.7"
sudo: required
env:
- ALLOW_DEPLOY=false
before_install:
- sudo apt-get update
- sudo apt-get install -y portaudio19-dev jackd2 libjack-jackd2-0
install:
- pip install -U pip setuptools wheel
- pip install -U numpy
- pip install -U pytest
- pip install -r requirements-dev.txt
- python setup.py build_ext --inplace --use-cython-trace
- pip install -e .
- ./build_tests.py
script:
- py.test --cov-config .coveragerc --cov=cysounddevice --boxed
after_success:
- coveralls
3 changes: 2 additions & 1 deletion build_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
if CPU_COUNT is None:
CPU_COUNT = 0

INCLUDE_PATH = numpy.get_include()
INCLUDE_PATH = [numpy.get_include()]

CYTHONIZE_CMD = 'cythonize {opts} {pyx_file}'

Expand All @@ -36,6 +36,7 @@ def cython_compile(path_pattern, options):
nthreads=options.parallel,
exclude_failures=options.keep_going,
exclude=options.excludes,
aliases={'NUMPY_INCLUDE':INCLUDE_PATH},
compiler_directives=options.directives,
compile_time_env=options.compile_time_env,
force=options.force,
Expand Down
1 change: 1 addition & 0 deletions cysounddevice/buffer.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ cdef class StreamBuffer:

# cpdef _build_buffers(self, Py_ssize_t buffer_len, Py_ssize_t itemsize)
cdef void _set_sample_buffer(self, SampleBuffer* bfr) except *
cdef int check_callback_errors(self) nogil except -1

cdef class StreamInputBuffer(StreamBuffer):
cpdef bint ready(self)
Expand Down
14 changes: 14 additions & 0 deletions cysounddevice/buffer.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ cdef class StreamBuffer:
self.sample_buffer = NULL
@property
def read_available(self):
self.check_callback_errors()
cdef int result = 0
cdef SampleBuffer* bfr
if self.sample_buffer != NULL:
Expand All @@ -212,13 +213,19 @@ cdef class StreamBuffer:
return result
@property
def write_available(self):
self.check_callback_errors()
cdef int result = 0
cdef SampleBuffer* bfr
if self.sample_buffer != NULL:
bfr = self.sample_buffer
result = bfr.write_available
return result


cdef int check_callback_errors(self) nogil except -1:
self.stream.check_callback_errors()
return 0

# cpdef _build_buffer(self, Py_ssize_t buffer_len, Py_ssize_t nchannels, Py_ssize_t itemsize):
# assert self.sample_buffer == NULL
#
Expand All @@ -242,11 +249,13 @@ cdef class StreamBuffer:
self.own_buffer = False
self.sample_buffer = bfr
self.nchannels = bfr.nchannels
self.check_callback_errors()

cdef class StreamInputBuffer(StreamBuffer):
cpdef bint ready(self):
"""Check the SampleBuffer for read availability
"""
self.check_callback_errors()
if self.sample_buffer == NULL:
return False
cdef SampleBuffer* bfr = self.sample_buffer
Expand Down Expand Up @@ -274,12 +283,14 @@ cdef class StreamInputBuffer(StreamBuffer):
return sample_time

cdef SampleTime_s* _read_into(self, float[:,:] data) nogil:
self.check_callback_errors()
if self.sample_buffer == NULL:
return NULL
cdef SampleTime_s* item_st = sample_buffer_read_sf32(self.sample_buffer, data)
return item_st

cdef SampleTime_s* _read_ptr(self, char *data) nogil:
self.check_callback_errors()
if self.sample_buffer == NULL:
return NULL
cdef SampleBuffer* bfr = self.sample_buffer
Expand All @@ -289,6 +300,7 @@ cdef class StreamOutputBuffer(StreamBuffer):
cpdef bint ready(self):
"""Check the SampleBuffer for write availability
"""
self.check_callback_errors()
if self.sample_buffer == NULL:
return False
cdef SampleBuffer* bfr = self.sample_buffer
Expand All @@ -311,6 +323,7 @@ cdef class StreamOutputBuffer(StreamBuffer):
return self._write_output_sf32(data)

cdef int _write_output_sf32(self, float[:,:] data) nogil:
self.check_callback_errors()
if self.sample_buffer == NULL:
return 0
return sample_buffer_write_sf32(self.sample_buffer, data)
Expand All @@ -327,6 +340,7 @@ cdef class StreamOutputBuffer(StreamBuffer):
Returns:
int: 1 on success
"""
self.check_callback_errors()
if self.sample_buffer == NULL:
return 0
cdef SampleBuffer* bfr = self.sample_buffer
Expand Down
6 changes: 4 additions & 2 deletions cysounddevice/devices.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,9 @@ cdef class PortAudio:
host_api = self.host_apis_by_paindex[device.host_api_index]
host_api._add_device(device)
default_ix = Pa_GetDefaultInputDevice()
self.default_input = self.devices_by_paindex[default_ix]
if default_ix != paNoDevice:
self.default_input = self.devices_by_paindex[default_ix]

default_ix = Pa_GetDefaultOutputDevice()
self.default_output = self.devices_by_paindex[default_ix]
if default_ix != paNoDevice:
self.default_output = self.devices_by_paindex[default_ix]
1 change: 1 addition & 0 deletions cysounddevice/pawrapper.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ cdef extern from "portaudio.h":
ctypedef int PaDeviceIndex
#define paNoDevice -1
#define paUseHostApiSpecificDeviceSpecification -2
cdef PaDeviceIndex paNoDevice = -1
ctypedef int PaHostApiIndex
PaHostApiIndex Pa_GetHostApiCount()
PaHostApiIndex Pa_GetDefaultHostApi()
Expand Down
14 changes: 14 additions & 0 deletions cysounddevice/stream_callback.pxd
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# cython: language_level=3, linetrace=False, profile=False

from cysounddevice.pawrapper cimport *
from cysounddevice.types cimport *
from cysounddevice.buffer cimport *
from cysounddevice.streams cimport *


cdef int _stream_callback(const void* in_bfr,
void* out_bfr,
unsigned long frame_count,
const PaStreamCallbackTimeInfo* time_info,
PaStreamCallbackFlags status_flags,
void* user_data) nogil
63 changes: 63 additions & 0 deletions cysounddevice/stream_callback.pyx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# cython: language_level=3, linetrace=False, profile=False

cimport cython


@cython.boundscheck(False)
@cython.wraparound(False)
cdef int _stream_callback(const void* in_bfr,
void* out_bfr,
unsigned long frame_count,
const PaStreamCallbackTimeInfo* time_info,
PaStreamCallbackFlags status_flags,
void* user_data) nogil: # pragma: no cover
cdef CallbackUserData* cb_data = <CallbackUserData*>user_data
cdef SampleBuffer* samp_bfr
cdef SampleTime_s* start_time
cdef PaTime adcTime, dacTime
cdef int r
cdef unsigned long i, bfr_size
cdef char *in_ptr = <char *>in_bfr
cdef char *out_ptr = <char *>out_bfr
if cb_data.exit_signal:
cb_data.stream_exit_complete = True
return paComplete

cb_data.error_status = CallbackError_none
cb_data.last_callback_flags = status_flags
if status_flags != 0:
cb_data.error_status = CallbackError_flags

if cb_data.input_channels > 0:
samp_bfr = cb_data.in_buffer
adcTime = time_info.inputBufferAdcTime
if samp_bfr.current_block == 0:
cb_data.firstInputAdcTime = adcTime
samp_bfr.callback_time.time_offset = adcTime
SampleTime_set_pa_time(&samp_bfr.callback_time, adcTime, True)
else:
SampleTime_set_block_vars(&samp_bfr.callback_time, samp_bfr.current_block, 0)
if samp_bfr.write_available > 0:
r = sample_buffer_write_from_callback(samp_bfr, in_ptr, frame_count, adcTime)
if r != 1:
cb_data.error_status = CallbackError_input_aborted
cb_data.stream_exit_complete = True
return paAbort
samp_bfr.current_block += 1
if cb_data.output_channels > 0:
samp_bfr = cb_data.out_buffer
dacTime = time_info.outputBufferDacTime
if samp_bfr.current_block == 0:
cb_data.firstOutputDacTime = dacTime
samp_bfr.callback_time.time_offset = dacTime
SampleTime_set_pa_time(&samp_bfr.callback_time, dacTime, True)
else:
SampleTime_set_block_vars(&samp_bfr.callback_time, samp_bfr.current_block, 0)
if samp_bfr.read_available > 0:
start_time = sample_buffer_read_from_callback(samp_bfr, out_ptr, frame_count, dacTime)
if start_time == NULL:
cb_data.error_status = CallbackError_output_aborted
cb_data.stream_exit_complete = True
return paAbort
samp_bfr.current_block += 1
return paContinue
13 changes: 13 additions & 0 deletions cysounddevice/streams.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,12 @@ from cysounddevice.types cimport *
from cysounddevice.devices cimport DeviceInfo
from cysounddevice.buffer cimport *

cdef enum CallbackErrorStatus:
CallbackError_none
CallbackError_flags
CallbackError_input_aborted
CallbackError_output_aborted

cdef struct CallbackUserData:
int input_channels
int output_channels
Expand All @@ -13,6 +19,10 @@ cdef struct CallbackUserData:
# SampleFormat* sample_format
PaTime firstInputAdcTime
PaTime firstOutputDacTime
PaStreamCallbackFlags last_callback_flags
CallbackErrorStatus error_status
bint exit_signal
bint stream_exit_complete

cdef class Stream:
cdef readonly DeviceInfo device
Expand All @@ -30,6 +40,7 @@ cdef class Stream:
cpdef check_active(self)
cpdef open(self)
cpdef close(self)
cdef int check_callback_errors(self) nogil except -1

cdef class StreamInfo:
cdef SampleFormat* sample_format
Expand Down Expand Up @@ -59,4 +70,6 @@ cdef class StreamCallback:

cdef void _build_user_data(self, Py_ssize_t buffer_len=*) except *
cdef void _free_user_data(self) except *
cdef void _send_exit_signal(self, float timeout) except *
cdef void _update_pa_data(self) except *
cdef int check_callback_errors(self) nogil except -1

0 comments on commit 1443145

Please sign in to comment.