Skip to content

Commit

Permalink
Merge pull request #5 from HEnquist/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
HEnquist authored Sep 4, 2020
2 parents 57bb693 + 8db8611 commit 8f34544
Show file tree
Hide file tree
Showing 10 changed files with 268 additions and 684 deletions.
24 changes: 24 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
name: pyCamillaDSP

on: [push]

jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: '3.x'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install PyYAML
pip install websocket_client
pip install .
- name: Test with pytest
run: |
pip install pytest
pip install pytest-cov
pytest --cov=camilladsp --cov-report=html
46 changes: 24 additions & 22 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,37 @@
![pyCamillaDSP](https://github.com/HEnquist/pycamilladsp/workflows/pyCamillaDSP/badge.svg)

# pyCamillaDSP
Companion Python library for CamillaDSP.
Works with CamillaDSP version 0.3.2 and up.

Install with
Download the library, either by `git clone` or by downloading a zip file of the code. Then unpack the files, go to the folder containing the `setup.py` file and run:
```sh
pip install .
```
Note that on some systems the command is `pip3` instead of `pip`.

## Plotting a configuration
This library provides the console command `plotcamillaconf`. Once the library is installed, the command should be available in your terminal.
To use it type:
```sh
plotcamillaconf /path/to/some/config.yml
```
## Dependencies
pyCamillaDSP requires python 3.6 or newer and the package websocket-client.

These are the names of the packages needed:
| Distribution | python | websocket-client |
|--------------|--------|------------------|
| Fedora | python3 | python3-websocket-client |
| Debian/Raspbian | python3 | python3-websocket |
| Arch | python | python-websocket-client |
| pip | - | websocket_client |
| Anaconda | - | websocket_client |

### Linux
Most linux distributions have Python 3.6 or newer installed by default. Use the normal package manager to install the packages.

### Windows
Use Anaconda: https://www.anaconda.com/products/individual. Then use Anaconda Navigator to install `websocket_client`.

This will plot the frequency response of all the defined filters, and show a block diagram of the pipeline.
### macOS
On macOS use either Anaconda or Homebrew. The Anaconda procedure is the same as for Windows.

For Homebrew, install Python with `brew install python`, after which you can install the needed packages with pip, `pip3 install websocket_client`.

## Communicating with the CamillaDSP process
This library provides an easy way to communicate with CamillaDSP via a websocket.
Expand Down Expand Up @@ -92,20 +108,6 @@ The CamillaConnection class provides the following methods:
|`read_config(config)` | Read a config from yaml string and return the contents as an obect, with defaults filled out with their default values.|


## Evaluating filters
To plot the frequency response of a filter, use the function `plot_filter`. This is mostly meant for internal use by the `plotcamillaconf` command.
```python
plot_filter(filterconf, name=None, samplerate=44100, npoints=1000, toimage=False)
```
This will plot using PyPlot. The filter configuration `fiterconf` must be provided. The `samplerate` defaults to 44100 if not given. The filter `name` is used for labels. The number of points in the plot is set with `npoints`. If `toimage` is set to True, then it will instead return the plot as an svg image.

## Plotting the pipeline
To plot a block diagram of the pipeline, use the function `plot_pipeline`. This is mostly meant for internal use by the `plotcamillaconf` command.
```python
plot_pipeline(conf, toimage=False)
```
This takes a full CamillaDSP configuration, `conf`. It will then plot the pipeline using PyPlot. If `toimage` is set to True, then it will instead return the plot as an svg image.

# Included examples:

play_wav: Play a wav file. This example reads a configuration from a file, updates the capture device fto point at a given .wav file, and sends this modified config to CamillaDSP.
Expand Down
2 changes: 0 additions & 2 deletions camilladsp/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
from camilladsp.camilladsp import CamillaConnection, CamillaError
from camilladsp.plot_filters import plot_filters, plot_filter
from camilladsp.plot_pipeline import plot_pipeline
83 changes: 45 additions & 38 deletions camilladsp/camilladsp.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ class CamillaError(ValueError):
"""
A class representing errors returned by CamillaDSP
"""

pass


Expand All @@ -42,39 +43,6 @@ def __init__(self, host, port):
self._version = None
self._lock = Lock()

def connect(self):
"""
Connect to the websocket of CamillaDSP.
"""
try:
with self._lock:
self._ws = create_connection(
"ws://{}:{}".format(self._host, self._port)
)
rawvers = self._query("getversion")
self._update_version(rawvers)
except Exception as _e:
self._ws = None
raise

def disconnect(self):
"""
Close the connection to the websocket.
"""
if self._ws is not None:
try:
with self._lock:
self._ws.close()
except Exception as _e:
pass
self._ws = None

def is_connected(self):
"""
Is websocket connected? Returns True or False.
"""
return self._ws is not None

def _query(self, command, arg=None):
if self._ws is not None:
if arg:
Expand All @@ -88,7 +56,13 @@ def _query(self, command, arg=None):
except Exception as _e:
self._ws = None
raise IOError("Lost connection to CamillaDSP")
state, cmd, reply = self._parse_response(rawrepl)
return self._handle_reply(command, rawrepl)
else:
raise IOError("Not connected to CamillaDSP")

def _handle_reply(self, command, rawreply):
try:
state, cmd, reply = self._parse_response(rawreply)
if state == "OK" and cmd == command.lower():
if reply:
return reply
Expand All @@ -99,9 +73,9 @@ def _query(self, command, arg=None):
else:
raise CamillaError("Command returned an error")
else:
raise IOError("Invalid response received")
else:
raise IOError("Not connected to CamillaDSP")
raise IOError("Invalid response received: {}".format(rawreply))
except IndexError:
raise IOError("Invalid response received: {}".format(rawreply))

def _parse_response(self, resp):
parts = resp.split(":", 2)
Expand All @@ -115,6 +89,39 @@ def _parse_response(self, resp):
def _update_version(self, resp):
self._version = tuple(resp.split(".", 3))

def connect(self):
"""
Connect to the websocket of CamillaDSP.
"""
try:
with self._lock:
self._ws = create_connection(
"ws://{}:{}".format(self._host, self._port)
)
rawvers = self._query("getversion")
self._update_version(rawvers)
except Exception as _e:
self._ws = None
raise

def disconnect(self):
"""
Close the connection to the websocket.
"""
if self._ws is not None:
try:
with self._lock:
self._ws.close()
except Exception as _e:
pass
self._ws = None

def is_connected(self):
"""
Is websocket connected? Returns True or False.
"""
return self._ws is not None

def get_version(self):
"""Read CamillaDSP version, returns a tuple of (major, minor, patch)."""
return self._version
Expand Down Expand Up @@ -269,7 +276,7 @@ def validate_config(self, config_object):
return validated_object


if __name__ == "__main__":
if __name__ == "__main__": # pragma: no cover
"""Testing area"""
print("\n---Connect---")
cdsp = CamillaConnection("127.0.0.1", 1234)
Expand Down
Loading

0 comments on commit 8f34544

Please sign in to comment.