Skip to content
Open
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
3 changes: 3 additions & 0 deletions examples/observer_scope.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ def on_effect_status_toggled(self, effect, **kwargs):
def on_effect_updated(self, effect, update_type, index, origin, **kwargs):
pass

def on_preset_changed(self, effect, **kwargs):
pass

def on_param_value_changed(self, param, **kwargs):
pass

Expand Down
11 changes: 11 additions & 0 deletions pluginsmanager/jeanam.code-workspace
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"folders": [
{
"path": "../../../jeanam"
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This patch is specific for your user

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose that you need to create an entry into .gitignore for ignoring *.code-workspace

},
{
"path": ".."
}
],
"settings": {}
}
34 changes: 33 additions & 1 deletion pluginsmanager/model/effect.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,11 @@ class Effect(metaclass=ABCMeta):
def __init__(self):
self.pedalboard = None
self._active = True

self._preset = None
self._patches = ()
self._params = ()
self._availablePatches = DictTuple([], lambda: None)
self._availablePresets = DictTuple([], lambda: None)
self._inputs = DictTuple([], lambda: None)
self._outputs = DictTuple([], lambda: None)
self._midi_inputs = DictTuple([], lambda: None)
Expand All @@ -65,12 +68,18 @@ def __init__(self):
def observer(self):
return self._observer

@property
def availablePresets(self):
return self._availablePresets

@observer.setter
def observer(self, observer):
self._observer = observer

for param in self.params:
param.observer = self.observer
for patch in self.patches:
patch.observer = self.observer

@property
def params(self):
Expand All @@ -79,6 +88,13 @@ def params(self):
"""
return self._params

@property
def patches(self):
"""
:return list[Param]: Params of effect
"""
return self._patches

@property
def inputs(self):
"""
Expand Down Expand Up @@ -126,6 +142,22 @@ def active(self, status):
self._active = status
self.observer.on_effect_status_toggled(self)

@availablePresets.setter
def availablePresets(self, options):
self._availablePresets = options

@property
def preset(self):
return self._preset

@preset.setter
def preset(self, name):
if name in self._availablePresets:

self._preset = self._availablePresets[name]
print(f"Setting preset => {self._preset}")
self.observer.on_preset_changed(self._preset)

def toggle(self):
"""
Toggle the effect status: ``self.active = not self.active``
Expand Down
13 changes: 12 additions & 1 deletion pluginsmanager/model/lv2/lv2_effect.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

from pluginsmanager.model.effect import Effect
from pluginsmanager.model.lv2.lv2_param import Lv2Param
from pluginsmanager.model.lv2.lv2_patch import Lv2Patch
from pluginsmanager.model.lv2.lv2_preset import Lv2Preset
from pluginsmanager.model.lv2.lv2_input import Lv2Input
from pluginsmanager.model.lv2.lv2_output import Lv2Output
from pluginsmanager.model.lv2.lv2_midi_input import Lv2MidiInput
Expand Down Expand Up @@ -46,6 +48,12 @@ def __init__(self, plugin):
params = [Lv2Param(self, param) for param in plugin["ports"]["control"]["input"]]
self._params = DictTuple(params, lambda param: param.symbol)

patches = [Lv2Patch(self, p['label'], p['uri'], None) for p in plugin["patches"]]
self._patches = DictTuple(patches, lambda patch: patch.label)

presets = [Lv2Preset(self, p['label'], p['uri']) for p in plugin["presets"]]
self._availablePresets = DictTuple(presets, lambda preset: preset.label)

inputs = [Lv2Input(self, effect_input) for effect_input in plugin['ports']['audio']['input']]
self._inputs = DictTuple(inputs, lambda _input: _input.symbol)

Expand All @@ -64,8 +72,9 @@ def __str__(self):
return str(self.plugin)

def __repr__(self):
return "<{} object as '{}' {} active at 0x{:x}>".format(
return "<{} object as '{}' {} active at 0x{:x}, preset:{}>".format(
self.__class__.__name__,
self._preset.label,
str(self),
'' if self.active else 'not',
id(self)
Expand All @@ -78,6 +87,8 @@ def __dict__(self):
'plugin': self.plugin['uri'],
'active': self.active,
'params': [param.json for param in self.params],
'patches': [patch.json for patch in self.patches],
'preset': self.preset.label,
'version': self.version
}

Expand Down
2 changes: 2 additions & 0 deletions pluginsmanager/model/lv2/lv2_effect_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ def reload(self, metadata, ignore_unsupported_plugins=True):
if not ignore_unsupported_plugins \
or plugin['uri'] in supported_plugins:
self._plugins[plugin['uri']] = Lv2Plugin(plugin)
else:
print(f"Ignoring plugin: {plugin['uri']}")

@property
def _supported_plugins(self):
Expand Down
38 changes: 38 additions & 0 deletions pluginsmanager/model/lv2/lv2_patch.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Copyright 2017 SrMouraSilva
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from pluginsmanager.model.patch import Patch


class Lv2Patch(Patch):
"""
Representation of a Lv2 patch.

For general input use, see :class:`.Patch` class documentation.

:param Lv2Effect effect: Effect that contains the patchy
:param str symbol: symbol for the effect

.. _patch: http://lv2plug.in/ns/ext/patch#
"""

def __init__(self, effect, label, uri, default):
super(Lv2Patch, self).__init__(effect, label, uri, default)
print(f"Creating patch {label} {uri}")


@property
def __dict__(self):
dictionary = super(Lv2Patch, self).__dict__
return dictionary
36 changes: 36 additions & 0 deletions pluginsmanager/model/lv2/lv2_preset.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Copyright 2017 SrMouraSilva
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from pluginsmanager.model.preset import Preset


class Lv2Preset(Preset):
"""
Representation of a Lv2 Preset.

For general input use, see :class:`.Preset` class documentation.

:param Lv2Effect effect: Effect that contains the Presety
:param str symbol: symbol for the effect

.. _Preset: http://lv2plug.in/ns/ext/Preset#
"""

def __init__(self, effect, label, uri):
super(Lv2Preset, self).__init__(effect, label, uri)

@property
def __dict__(self):
dictionary = super(Lv2Preset, self).__dict__
return dictionary
130 changes: 130 additions & 0 deletions pluginsmanager/model/patch.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
# Copyright 2017 SrMouraSilva
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from abc import ABCMeta, abstractmethod

from unittest.mock import MagicMock


class PatchError(Exception):

def __init__(self, message):
super(PatchError, self).__init__(message)
self.message = message


class Patch(metaclass=ABCMeta):
"""
:class:`.Patch` represents an Audio Plugin Patch::

>>> my_awesome_effect
<Lv2Effect object as 'Amp Model' active at 0x7fd58d874ba8>
>>> my_awesome_effect.patch
(<Lv2Patch object as value=model.name)

>>> param.default
1.5
>>> param.value = 14

>>> symbol = param.symbol
>>> symbol
'model'
>>> param == my_awesome_effect.patches[symbol]
True

:param Effect effect: Effect in which this parameter belongs
"""

def __init__(self, effect, label, uri, default):
self._uri = uri
self._label = label
self._effect = effect
self._default = default
self._value = default

self.observer = MagicMock()

@property
def effect(self):
"""
:return: Effect in which this parameter belongs
"""
return self._effect

@property
def default(self):
"""
Parameter default

:getter: Current default
:setter: Set the current default
"""
return self._default

@property
def uri(self):
"""
Parameter uri

:getter: Current uri
:setter: Set the current uri
"""
return self._uri

@property
def label(self):
return self._label

@property
def value(self):
"""
Parameter value

:getter: Current value
:setter: Set the current value
"""
return self._value

@value.setter
def value(self, new_value):
if self._value == new_value:
return
self._value = new_value
self.observer.on_patch_value_changed(self)

def __repr__(self, *args, **kwargs):
return "<{} object as uri={}, value={} label={} at 0x{:x}>".format(
self.__class__.__name__,
self._uri,
self._value,
self._label,
id(self)
)

@property
def json(self):
"""
Get a json decodable representation of this param

:return dict: json representation
"""
return self.__dict__

@property
def __dict__(self):
return {
'uri': self._uri,
'label': self._label,
'value': self._value
}
Loading