Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/pya-ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ jobs:
run: brew install portaudio
- uses: conda-incubator/setup-miniconda@v2
with:
miniconda-version: "latest"
activate-environment: test-env
environment-file: ci/test-environment.yml
python-version: ${{ matrix.python-version }}
Expand Down
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -253,3 +253,20 @@ Asig methods usually return an Asig, so methods can be chained, e.g
## Contributing
* Please get in touch with us if you wish to contribute. We are happy to be involved in the discussion of new features and to receive pull requests.

### Local development

For local development, start your own virtual environment then: `pip install -e .`

Example to set logging level to see pya logging:

```Python
import logging
logger = logging.getLogger('pya') # Get the pya logger
logger.setLevel(logging.INFO)
# Create console handler with formatting
ch = logging.StreamHandler()
ch.setLevel(logging.INFO)
formatter = logging.Formatter('%(name)s - %(levelname)s - %(message)s')
ch.setFormatter(formatter)
logger.addHandler(ch)
```
9 changes: 7 additions & 2 deletions pya/arecorder.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,13 @@ class Arecorder(Aserver):
>>> ar.record()
>>> time.sleep(1)
>>> ar.stop()
>>> print(ar.recordings) # doctest:+ELLIPSIS
[Asig(''): ... x ... @ 44100Hz = ...
>>> ar.quit() # This is important to avoid pyaudio trace trap error

>>> # Using context manager, no need to call quit()
>>> with Arecorder() as ar: # doctest:+SKIP
... ar.record()
... time.sleep(1)
... ar.stop()
"""

def __init__(self, sr: int = 44100, bs: int = 256, device: Optional[int] = None,
Expand Down
14 changes: 10 additions & 4 deletions pya/aserver.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class Aserver:
>>> asine = Ugen().sine()
>>> asine.play(server=ser)
Asig('sine'): 1 x 44100 @ 44100Hz = 1.000s cn=['0']
>>> ser.quit() # Important to call quit() to close the stream when you are done. Or use context manager.
"""

default = None # that's the default Aserver if Asigs play via it
Expand Down Expand Up @@ -213,7 +214,6 @@ def quit(self):
except AttributeError:
_LOGGER.info("No stream found...")
self.stream = None
return 0

def play(self, asig, onset: Union[int, float] = 0, out: int = 0, **kwargs):
"""Dispatch asigs or arrays for given onset.
Expand Down Expand Up @@ -317,10 +317,16 @@ def __enter__(self):
return self.boot()

def __exit__(self, exc_type, exc_value, traceback):
"""Context manager exit"""
_LOGGER.info("Exiting context manager. Cleaning up stream and backend")
self.quit()
self.backend.terminate()

def __del__(self):
self.quit()
self.backend.terminate()

"""Backup cleanup, only if context manager wasn't used"""
if hasattr(self, 'stream') and self.stream is not None:
try:
self.quit()
self.backend.terminate()
except:
pass # Ignore cleanup errors during shutdown
Loading
Loading