Skip to content

Commit

Permalink
Merge pull request #79 from PedalPi/issue-78-lv2-effect-builder-error
Browse files Browse the repository at this point in the history
Issue #78 Improve lv2 effect builder error message
  • Loading branch information
SrMouraSilva committed Nov 30, 2017
2 parents c32033d + c8a3d19 commit 291510f
Show file tree
Hide file tree
Showing 13 changed files with 284 additions and 10 deletions.
2 changes: 2 additions & 0 deletions CHANGES
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,11 @@ Version 0.6.0 -- released 10/?/17
- `Issue #65`_ - Fix documentation bug `SystemEffectBuilder(client).build()` instead `SystemEffectBuilder(client)`;
- `Issue #68`_ - Remove current mod-host pedalboard don't removes systems connection (system.output to system.input);
- `Issue #66`_ - JSON effect improviments: Add plugin version. Remove `min` and `max`;
- `Issue #62`_ - Create a converter MOD pedalboard -> PluginsManager pedalboard.

.. _Issue #38: https://github.com/PedalPi/PluginsManager/issues/38
.. _Issue #57: https://github.com/PedalPi/PluginsManager/issues/57
.. _Issue #62: https://github.com/PedalPi/PluginsManager/issues/65
.. _Issue #65: https://github.com/PedalPi/PluginsManager/issues/65
.. _Issue #66: https://github.com/PedalPi/PluginsManager/issues/66
.. _Issue #67: https://github.com/PedalPi/PluginsManager/issues/67
Expand Down
24 changes: 16 additions & 8 deletions docs/source/util.rst
Original file line number Diff line number Diff line change
@@ -1,32 +1,40 @@
PedalPi - PluginsManager - Util
===============================

pluginsmanager.util.dict_tuple.DictTuple
----------------------------------------
DictTuple
---------

.. autoclass:: pluginsmanager.util.dict_tuple.DictTuple
:members:
:special-members:
:exclude-members: __weakref__

pluginsmanager.util.pairs_list.PairsList
----------------------------------------
ModPedalboardConverter
----------------------

.. autoclass:: pluginsmanager.util.mod_pedalboard_converter.ModPedalboardConverter
:members:
:special-members:
:exclude-members: __weakref__

PairsList
---------

.. autoclass:: pluginsmanager.util.pairs_list.PairsList
:members:
:special-members:
:exclude-members: __weakref__

pluginsmanager.util.pairs_list.PairsListResult
----------------------------------------------
PairsListResult
---------------

.. autoclass:: pluginsmanager.util.pairs_list.PairsListResult
:members:
:special-members:
:exclude-members: __weakref__

pluginsmanager.util.persistence_decoder
---------------------------------------
persistence_decoder
-------------------

.. autoclass:: pluginsmanager.util.persistence_decoder.PersistenceDecoderError
:members:
Expand Down
14 changes: 14 additions & 0 deletions pluginsmanager/jack/jack_interface.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
# 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.

import pyaudio


Expand Down
14 changes: 13 additions & 1 deletion pluginsmanager/model/lv2/lv2_effect_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@
from pluginsmanager.model.lv2.lv2_effect import Lv2Effect


class Lv2EffectBuilderError(Exception):
pass


class Lv2EffectBuilder(object):
"""
Generates lv2 audio plugins instance (as :class:`.Lv2Effect` object).
Expand Down Expand Up @@ -78,7 +82,15 @@ def build(self, lv2_uri):
:param string lv2_uri:
:return Lv2Effect: Effect created
"""
return Lv2Effect(self._plugins[lv2_uri])
try:
plugin = self._plugins[lv2_uri]
except KeyError:
raise Lv2EffectBuilderError(
"Lv2EffectBuilder not contains metadata information about the plugin '{}'. \n"
"Try re-scan the installed plugins using the reload method::\n"
" >>> lv2_effect_builder.reload(lv2_effect_builder.lv2_plugins_data())".format(lv2_uri))

return Lv2Effect(plugin)

def lv2_plugins_data(self):
"""
Expand Down
3 changes: 3 additions & 0 deletions pluginsmanager/util/dict_tuple.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,6 @@ def __getitem__(self, index):

else:
return self._dict[index]

def __contains__(self, item):
return item in self._dict
109 changes: 109 additions & 0 deletions pluginsmanager/util/mod_pedalboard_converter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
# 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.

import sys
from pathlib import Path

from pluginsmanager.model.pedalboard import Pedalboard
from pluginsmanager.model.system.system_effect import SystemEffect


class ModPedalboardConverter(object):
"""
ModPedalboardConverter is a utility to convert MOD pedalboards structure
in plugins manager pedalboard.
`MOD`_, an awesome music enterprise, create the `mod-ui`_, a visual interface
that enable create pedalboards in a simple way.
.. _MOD: http://moddevices.com/
.. _mod-ui: https://github.com/moddevices/mod-ui
"""

def __init__(self, mod_ui_path, builder):
"""
:param Path mod_ui_path: path that mod_ui has in the computer.
:param Lv2EffectBuilder builder: Builder for generate the lv2 effects
"""
self._load_mod_ui_libraries(mod_ui_path)
self.builder = builder

def _load_mod_ui_libraries(self, path):
"""
:param Path path:
"""
path = path / Path('mod')
sys.path.append(str(path))

def get_pedalboard_info(self, path):
"""
:param Path path: Path that the pedalboard has been persisted.
Generally is in format `path/to/pedalboard/name.pedalboard`
:return dict: pedalboard persisted configurations
"""
from utils import get_pedalboard_info

return get_pedalboard_info(str(path))

def convert(self, pedalboard_path, system_effect):
"""
:param Path pedalboard_path: Path that the pedalboard has been persisted.
Generally is in format `path/to/pedalboard/name.pedalboard`
:param SystemEffect system_effect: Effect that contains the audio interface outputs and inputs
:return Pedalboard: Pedalboard loaded
"""
info = self.get_pedalboard_info(pedalboard_path)

pedalboard = Pedalboard(info['title'])

effects_instance = {}

for effect_data in info['plugins']:
effect = self._generate_effect(effect_data)
pedalboard.append(effect)
effects_instance[effect_data['instance']] = effect

for connection_data in info['connections']:
output_port = self._get_port(connection_data['source'], effects_instance, system_effect)
input_port = self._get_port(connection_data['target'], effects_instance, system_effect)

pedalboard.connect(output_port, input_port)

return pedalboard

def _generate_effect(self, effect_data):
effect = self.builder.build(effect_data['uri'])
effect.active = not effect_data['bypassed']

for param_data in effect_data['ports']:
effect.params[param_data['symbol']].value = param_data['value']

return effect

def _get_port(self, name, effects_instance, system_effect):
effect, port = None, None

if name.startswith('capture_') or name.startswith('playback_'):
effect = system_effect
port = name
else:
instance, port = name.split('/')
effect = effects_instance[instance]

possible_ports = (effect.outputs, effect.inputs, effect.midi_outputs, effect.midi_inputs)
filtered = filter(lambda ports: port in ports, possible_ports)

ports = list(filtered)[0]
return ports[port]

2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ def readme():

setup(
name='PedalPi-PluginsManager',
version='0.6.0',
version='0.6.0alpha1',

description='Pythonic management of LV2 audio plugins with mod-host.',
long_description=readme(),
Expand Down
13 changes: 13 additions & 0 deletions test/jack/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# 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.
13 changes: 13 additions & 0 deletions test/model/lv2/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# 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.
26 changes: 26 additions & 0 deletions test/model/lv2/lv2_effect_builder_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# 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.

import unittest

from pluginsmanager.model.lv2.lv2_effect_builder import Lv2EffectBuilder
from pluginsmanager.model.lv2.lv2_effect_builder import Lv2EffectBuilderError


class Lv2EffecBuilderTest(unittest.TestCase):

def test_load_nonexistent_effect(self):
builder = Lv2EffectBuilder()
with self.assertRaises(Lv2EffectBuilderError):
builder.build('nonexistent_effect')
File renamed without changes.
35 changes: 35 additions & 0 deletions test/util/dict_tuple_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# 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.

import unittest

from pluginsmanager.util.dict_tuple import DictTuple


class DictTupleTest(unittest.TestCase):

def test__get_item__(self):
elements = ('123', '456', '789')
data = DictTuple(elements, lambda e: e)

for index, element in enumerate(elements):
self.assertEqual(element, data[index])
self.assertEqual(element, data[element])

def test_in(self):
elements = ('abc', 'cde', 'def')
data = DictTuple(elements, lambda e: e.upper())

self.assertTrue('ABC' in data)
self.assertFalse('abc' in data)
39 changes: 39 additions & 0 deletions test/util/mod_pedalboard_converter_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# 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.

import os
import unittest
from pathlib import Path

from pluginsmanager.model.lv2.lv2_effect_builder import Lv2EffectBuilder
from pluginsmanager.model.system.system_effect import SystemEffect
from pluginsmanager.util.mod_pedalboard_converter import ModPedalboardConverter


class ModPedalboardConverterTest(unittest.TestCase):

@unittest.skipIf('TRAVIS' in os.environ, 'Mod-ui not configured in Travis build')
def test_all(self):
path = Path('/home/paulo/git/mod/mod_ui/')
builder = Lv2EffectBuilder()
#builder.reload(builder.lv2_plugins_data())

converter = ModPedalboardConverter(path, builder)

pedalboard_path = Path('/home/paulo/.pedalboards/teste.pedalboard')
system_effect = SystemEffect('system', ['capture_1', 'capture_2'], ['playback_1', 'playback_2'])

print(converter.get_pedalboard_info(pedalboard_path))
pedalboard = converter.convert(pedalboard_path, system_effect)
print(pedalboard.json)

0 comments on commit 291510f

Please sign in to comment.