def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.passthru_description = node_db.NodeDescription( uri='test://passthru', type=node_db.NodeDescription.PROCESSOR, ports=[ node_db.PortDescription( name='in:left', direction=node_db.PortDescription.INPUT, types=[node_db.PortDescription.AUDIO], ), node_db.PortDescription( name='in:right', direction=node_db.PortDescription.INPUT, types=[node_db.PortDescription.AUDIO], ), node_db.PortDescription( name='out:left', direction=node_db.PortDescription.OUTPUT, types=[node_db.PortDescription.AUDIO], ), node_db.PortDescription( name='out:right', direction=node_db.PortDescription.OUTPUT, types=[node_db.PortDescription.AUDIO], ), ], processor=node_db.ProcessorDescription(type='builtin://null', ), )
def __init__( self, *, host_system: host_system_lib.HostSystem, description: node_db.NodeDescription, id: str, # pylint: disable=redefined-builtin name: Optional[str] = None, initial_state: Optional[audioproc.PluginState] = None) -> None: assert isinstance(description, node_db.NodeDescription), description self._host_system = host_system self.description = node_db.NodeDescription() self.description.CopyFrom(description) self.name = name or type(self).__name__ self.id = id self.initial_state = initial_state self.__realm = None # type: realm_lib.PyRealm self.broken = False self.ports = [] # type: List[Port] self.inputs = {} # type: Dict[str, InputPort] self.outputs = {} # type: Dict[str, OutputPort] self.__control_values = { } # type: Dict[str, control_value.PyControlValue] self.__port_properties = { } # type: Dict[str, node_port_properties_pb2.NodePortProperties] self.__parameters = node_parameters_pb2.NodeParameters() for port_desc in self.description.ports: self.__add_port(self.__create_port(port_desc))
def description(self) -> node_db.NodeDescription: node_desc = node_db.NodeDescription() node_desc.CopyFrom(node_description.MidiCCtoCVDescription) for idx in range(len(self.channels)): node_desc.ports.add( name='channel%d' % (idx + 1), direction=node_db.PortDescription.OUTPUT, types=[node_db.PortDescription.ARATE_CONTROL], ) return node_desc
def test_id(self): node_description = node_db.NodeDescription( uri='test://test', type=node_db.NodeDescription.PROCESSOR, ports=[], processor=node_db.ProcessorDescription( type='builtin://null', ), ) proc1 = processor.PyProcessor('realm', 'test_node_1', self.host_system, node_description) proc2 = processor.PyProcessor('realm', 'test_node_2', self.host_system, node_description) self.assertNotEqual(proc1.id, proc2.id)
async def __handle_play_file( self, session: Session, request: audioproc_pb2.PlayFileRequest, response: empty_message_pb2.EmptyMessage) -> None: realm = self.__engine.get_realm('root') node_desc = node_db.NodeDescription() node_desc.CopyFrom(node_db.Builtins.SoundFileDescription) node_desc.sound_file.sound_file_path = request.path node = engine.Node.create(host_system=self.__host_system, id=uuid.uuid4().hex, description=node_desc) realm.graph.add_node(node) await realm.setup_node(node) sink = realm.graph.find_node('sink') sink.inputs['in:left'].connect(node.outputs['out:left'], node_db.PortDescription.AUDIO) sink.inputs['in:right'].connect(node.outputs['out:right'], node_db.PortDescription.AUDIO) realm.update_spec() sound_file_complete_uri = 'http://noisicaa.odahoda.de/lv2/processor_sound_file#complete' complete = asyncio.Event(loop=self.event_loop) def handle_notification( notification: engine_notification_pb2.EngineNotification ) -> None: for node_message in notification.node_messages: if node_message.node_id == node.id: msg = lv2.wrap_atom(self.__urid_mapper, node_message.atom).as_object if msg.get(sound_file_complete_uri, False): complete.set() listener = self.__engine.notifications.add(handle_notification) try: await asyncio.wait_for(complete.wait(), timeout=10.0, loop=self.event_loop) except asyncio.TimeoutError: pass listener.remove() sink.inputs['in:left'].disconnect(node.outputs['out:left']) sink.inputs['in:right'].disconnect(node.outputs['out:right']) realm.graph.remove_node(node) realm.update_spec()
def test_event_input_port(self): self.node_description = node_db.NodeDescription( uri='test://test', type=node_db.NodeDescription.PROCESSOR, ports=[ node_db.PortDescription( name='in', direction=node_db.PortDescription.INPUT, types=[node_db.PortDescription.EVENTS], ), node_db.PortDescription( name='out', direction=node_db.PortDescription.OUTPUT, types=[node_db.PortDescription.AUDIO], ), ], processor=node_db.ProcessorDescription( type='builtin://csound', ), csound=node_db.CSoundDescription( orchestra=textwrap.dedent("""\ sr=44100 0dbfs=1 ksmps=32 nchnls=1 gaOut chnexport "out", 2 instr 1 iPitch = p4 iVelocity = p5 iFreq = cpsmidinn(iPitch) iVolume = -20 * log10(127^2 / iVelocity^2) gaOut = db(iVolume) * linseg(0, 0.08, 1, 0.1, 0.6, 0.5, 0.0) * poscil(1.0, iFreq) endin """), score='', ), ) self.create_processor() self.fill_midi_buffer( 'in', [(0, [0x90, 60, 100]), (64, [0x80, 60, 0])]) self.process_block() self.assertBufferIsNotQuiet('out')
def test_csound(self): self.node_description = node_db.NodeDescription( uri='test://test', type=node_db.NodeDescription.PROCESSOR, ports=[ node_db.PortDescription( name='gain', direction=node_db.PortDescription.INPUT, types=[node_db.PortDescription.KRATE_CONTROL], ), node_db.PortDescription( name='in', direction=node_db.PortDescription.INPUT, types=[node_db.PortDescription.AUDIO], ), node_db.PortDescription( name='out', direction=node_db.PortDescription.OUTPUT, types=[node_db.PortDescription.AUDIO], ), ], processor=node_db.ProcessorDescription( type='builtin://csound', ), csound=node_db.CSoundDescription( orchestra=textwrap.dedent("""\ sr=44100 0dbfs=1 ksmps=32 nchnls=1 gkGain chnexport "gain", 1 gaIn chnexport "in", 1 gaOut chnexport "out", 2 instr 1 gaOut = gkGain * gaIn endin """), score='i1 0 -1', ), ) self.create_processor() self.fill_buffer('in', 1.0) self.fill_buffer('gain', 0.5) self.process_block() self.assertBufferAllEqual('out', 0.5)
def description(self) -> node_db.NodeDescription: desc = node_db.NodeDescription() desc.CopyFrom(node_description.CustomCSoundDescription) for port in self.ports: port_desc = desc.ports.add( name=port.name, display_name=port.display_name or port.name, types=[port.type], direction=port.direction, csound_name=port.csound_name, ) if port.type in (node_db.PortDescription.KRATE_CONTROL, node_db.PortDescription.ARATE_CONTROL): port_desc.float_value.min = 0.0 port_desc.float_value.max = 1.0 port_desc.float_value.default = 0.0 return desc
def scan(self) -> Iterator[node_db.NodeDescription]: rootdir = os.path.join(constants.DATA_DIR, 'csound') for dirpath, _, filenames in os.walk(rootdir): for filename in filenames: if not filename.endswith('.csnd'): continue uri = 'builtin://csound/%s' % filename[:-5] path = os.path.join(dirpath, filename) logger.info("Loading csound node %s from %s", uri, path) tree = ElementTree.parse(path) root = tree.getroot() assert root.tag == 'csound' desc = node_db.NodeDescription() desc.uri = uri desc.supported = True desc.node_ui.type = 'builtin://plugin' desc.builtin_icon = 'node-type-builtin' desc.type = node_db.NodeDescription.PROCESSOR desc.processor.type = 'builtin://csound' desc.display_name = ''.join( root.find('display-name').itertext()) desc.has_ui = False for port_elem in root.find('ports').findall('port'): port_desc = desc.ports.add() port_desc.name = port_elem.get('name') display_name_elem = port_elem.find('display-name') if display_name_elem is not None: port_desc.display_name = ''.join( display_name_elem.itertext()) port_desc.types.append({ 'audio': node_db.PortDescription.AUDIO, 'kratecontrol': node_db.PortDescription.KRATE_CONTROL, 'aratecontrol': node_db.PortDescription.ARATE_CONTROL, 'events': node_db.PortDescription.EVENTS, }[port_elem.get('type')]) port_desc.direction = { 'input': node_db.PortDescription.INPUT, 'output': node_db.PortDescription.OUTPUT, }[port_elem.get('direction')] if port_desc.direction == node_db.PortDescription.OUTPUT: drywet_elem = port_elem.find('drywet') if drywet_elem is not None: port_desc.drywet_port = drywet_elem.get('port') port_desc.drywet_default = float( drywet_elem.get('default')) bypass_elem = port_elem.find('bypass') if bypass_elem is not None: port_desc.bypass_port = bypass_elem.get('port') if (port_desc.direction == node_db.PortDescription.INPUT and port_desc.types[0] == node_db.PortDescription.EVENTS): csound_elem = port_elem.find('csound') if csound_elem is not None: port_desc.csound_name = csound_elem.get('instr') if (port_desc.direction == node_db.PortDescription.INPUT and port_desc.types[0] in (node_db.PortDescription.KRATE_CONTROL, node_db.PortDescription.ARATE_CONTROL)): float_control_elem = port_elem.find('float-control') if float_control_elem is not None: value_desc = port_desc.float_value min_value = float_control_elem.get('min') if min_value is not None: value_desc.min = float(min_value) max_value = float_control_elem.get('max') if max_value is not None: value_desc.max = float(max_value) default_value = float_control_elem.get('default') if default_value is not None: value_desc.default = float(default_value) csound_desc = desc.csound orchestra = ''.join(root.find('orchestra').itertext()) orchestra = orchestra.strip() + '\n' csound_desc.orchestra = orchestra score = ''.join(root.find('score').itertext()) score = score.strip() + '\n' csound_desc.score = score yield desc
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # # @end:license from noisicaa import node_db InstrumentDescription = node_db.NodeDescription( uri='builtin://instrument', display_name='Instrument', type=node_db.NodeDescription.PROCESSOR, node_ui=node_db.NodeUIDescription(type='builtin://instrument', ), builtin_icon='node-type-builtin', processor=node_db.ProcessorDescription(type='builtin://instrument', ), ports=[ node_db.PortDescription( name='in', direction=node_db.PortDescription.INPUT, types=[node_db.PortDescription.EVENTS], ), node_db.PortDescription( name='out:left', direction=node_db.PortDescription.OUTPUT, types=[node_db.PortDescription.AUDIO], ), node_db.PortDescription( name='out:right', direction=node_db.PortDescription.OUTPUT, types=[node_db.PortDescription.AUDIO], ), ])
# # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # # @end:license from noisicaa import node_db OscilloscopeDescription = node_db.NodeDescription( uri='builtin://oscilloscope', display_name='Oscilloscope', type=node_db.NodeDescription.PROCESSOR, node_ui=node_db.NodeUIDescription( type='builtin://oscilloscope', muteable=False, ), builtin_icon='node-type-builtin', processor=node_db.ProcessorDescription(type='builtin://oscilloscope', ), ports=[ node_db.PortDescription( name='in', direction=node_db.PortDescription.INPUT, types=[ node_db.PortDescription.ARATE_CONTROL, node_db.PortDescription.KRATE_CONTROL, node_db.PortDescription.AUDIO, ], ), ])
# # @end:license from noisicaa import node_db VUMeterDescription = node_db.NodeDescription( uri='builtin://vumeter', display_name='VU Meter', type=node_db.NodeDescription.PROCESSOR, node_ui=node_db.NodeUIDescription( type='builtin://vumeter', ), builtin_icon='node-type-builtin', processor=node_db.ProcessorDescription( type='builtin://vumeter', ), ports=[ node_db.PortDescription( name='in:left', direction=node_db.PortDescription.INPUT, types=[node_db.PortDescription.AUDIO], ), node_db.PortDescription( name='in:right', direction=node_db.PortDescription.INPUT, types=[node_db.PortDescription.AUDIO], ), ] )
MixerDescription = node_db.NodeDescription( uri='builtin://mixer', display_name='Mixer', type=node_db.NodeDescription.PROCESSOR, node_ui=node_db.NodeUIDescription(type='builtin://mixer', ), builtin_icon='node-type-builtin', processor=node_db.ProcessorDescription(type='builtin://mixer', ), ports=[ node_db.PortDescription( name='in:left', direction=node_db.PortDescription.INPUT, types=[node_db.PortDescription.AUDIO], ), node_db.PortDescription( name='in:right', direction=node_db.PortDescription.INPUT, types=[node_db.PortDescription.AUDIO], ), node_db.PortDescription( name='out:left', direction=node_db.PortDescription.OUTPUT, types=[node_db.PortDescription.AUDIO], ), node_db.PortDescription( name='out:right', direction=node_db.PortDescription.OUTPUT, types=[node_db.PortDescription.AUDIO], ), node_db.PortDescription( name='gain', direction=node_db.PortDescription.INPUT, types=[node_db.PortDescription.KRATE_CONTROL], float_value=node_db.FloatValueDescription(default=0.0, min=-50.0, max=20.0), ), node_db.PortDescription( name='pan', direction=node_db.PortDescription.INPUT, types=[node_db.PortDescription.KRATE_CONTROL], float_value=node_db.FloatValueDescription(default=0.0, min=-1.0, max=1.0), ), node_db.PortDescription( name='lp_cutoff', direction=node_db.PortDescription.INPUT, types=[node_db.PortDescription.KRATE_CONTROL], float_value=node_db.FloatValueDescription(default=20000.0, min=1.0, max=20000.0), ), node_db.PortDescription( name='hp_cutoff', direction=node_db.PortDescription.INPUT, types=[node_db.PortDescription.KRATE_CONTROL], float_value=node_db.FloatValueDescription(default=1.0, min=1.0, max=20000.0), ), ])
def scan(self) -> Iterator[node_db.NodeDescription]: # TODO: support configurable searchpaths rootdirs = os.environ.get('LADSPA_PATH', '/usr/lib/ladspa') for rootdir in rootdirs.split(':'): for dirpath, _, filenames in os.walk(rootdir): for filename in filenames: if not filename.endswith('.so'): continue path = os.path.join(dirpath, filename) logger.info("Loading LADSPA plugins from %s", path) try: lib = ladspa.Library(path) except ladspa.Error as exc: logger.warning("Failed to load LADSPA library %s: %s", path, exc) continue for descriptor in lib.descriptors: # pylint: disable=not-an-iterable uri = 'ladspa://%s/%s' % (filename, descriptor.label) logger.info("Adding LADSPA plugin %s", uri) desc = node_db.NodeDescription() desc.uri = uri desc.supported = True desc.display_name = descriptor.name desc.type = node_db.NodeDescription.PLUGIN desc.node_ui.type = 'builtin://plugin' desc.builtin_icon = 'node-type-ladspa' desc.processor.type = 'builtin://plugin' desc.plugin.type = node_db.PluginDescription.LADSPA desc.has_ui = False ladspa_desc = desc.ladspa ladspa_desc.library_path = path ladspa_desc.label = descriptor.label for port in descriptor.ports: port_desc = desc.ports.add() port_desc.name = port.name if port.direction == ladspa.PortDirection.Input: port_desc.direction = node_db.PortDescription.INPUT elif port.direction == ladspa.PortDirection.Output: port_desc.direction = node_db.PortDescription.OUTPUT else: raise ValueError(port) if port.type == ladspa.PortType.Control: port_desc.types.append( node_db.PortDescription.KRATE_CONTROL) elif port.type == ladspa.PortType.Audio: port_desc.types.append( node_db.PortDescription.AUDIO) else: raise ValueError(port) if (port.type == ladspa.PortType.Control and port.direction == ladspa.PortDirection.Input): lower_bound = port.lower_bound(44100) upper_bound = port.upper_bound(44100) default = port.default(44100) value_desc = port_desc.float_value # Using a fixed sample rate is pretty ugly... if lower_bound is not None: value_desc.min = lower_bound if upper_bound is not None: value_desc.max = upper_bound if default is not None: value_desc.default = default yield desc
# the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # # @end:license from noisicaa import node_db MidiCCtoCVDescription = node_db.NodeDescription( uri='builtin://midi-cc-to-cv', display_name='MIDI CC to Control Value', type=node_db.NodeDescription.PROCESSOR, node_ui=node_db.NodeUIDescription(type='builtin://midi-cc-to-cv', ), builtin_icon='node-type-builtin', processor=node_db.ProcessorDescription(type='builtin://midi-cc-to-cv', ), ports=[ node_db.PortDescription( name='in', direction=node_db.PortDescription.INPUT, types=[node_db.PortDescription.EVENTS], ), ])
# the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # # @end:license from noisicaa import node_db BeatTrackDescription = node_db.NodeDescription( uri='builtin://beat-track', display_name='Beat Track', type=node_db.NodeDescription.PROCESSOR, node_ui=node_db.NodeUIDescription(type='builtin://beat-track', ), builtin_icon='track-type-beat', processor=node_db.ProcessorDescription(type='builtin://pianoroll', ), ports=[ node_db.PortDescription( name='out', direction=node_db.PortDescription.OUTPUT, types=[node_db.PortDescription.EVENTS], ), ])
def description(self) -> node_db.NodeDescription: node_desc = node_db.NodeDescription() node_desc.CopyFrom(node_description.MidiMonitorDescription) return node_desc
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # # @end:license from noisicaa import node_db CVMapperDescription = node_db.NodeDescription( uri='builtin://cv-mapper', display_name='Control Value Mapper (a-rate)', type=node_db.NodeDescription.PROCESSOR, node_ui=node_db.NodeUIDescription(type='builtin://cv-mapper', ), builtin_icon='node-type-builtin', processor=node_db.ProcessorDescription(type='builtin://cv-mapper', ), ports=[ node_db.PortDescription( name='in', direction=node_db.PortDescription.INPUT, types=[node_db.PortDescription.ARATE_CONTROL], ), node_db.PortDescription( name='out', direction=node_db.PortDescription.OUTPUT, types=[node_db.PortDescription.ARATE_CONTROL], ), ])
# @begin:license # # Copyright (c) 2015-2019, Benjamin Niemann <*****@*****.**> # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # # @end:license from noisicaa import node_db CustomCSoundDescription = node_db.NodeDescription( uri='builtin://custom-csound', display_name='Custom CSound', type=node_db.NodeDescription.PROCESSOR, processor=node_db.ProcessorDescription(type='builtin://custom-csound', ), node_ui=node_db.NodeUIDescription(type='builtin://custom-csound', ), builtin_icon='node-type-builtin', )
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # # @end:license from noisicaa import node_db SampleTrackDescription = node_db.NodeDescription( uri='builtin://sample-track', display_name='Sample Track', type=node_db.NodeDescription.PROCESSOR, node_ui=node_db.NodeUIDescription(type='builtin://sample-track', ), processor=node_db.ProcessorDescription(type='builtin://sample-script', ), builtin_icon='track-type-sample', ports=[ node_db.PortDescription( name='out:left', direction=node_db.PortDescription.OUTPUT, types=[node_db.PortDescription.AUDIO], ), node_db.PortDescription( name='out:right', direction=node_db.PortDescription.OUTPUT, types=[node_db.PortDescription.AUDIO], ), ])
def description(self) -> node_db.NodeDescription: node_desc = node_db.NodeDescription() node_desc.CopyFrom(node_description.MetronomeDescription) return node_desc
# # @end:license from noisicaa import node_db MidiLooperDescription = node_db.NodeDescription( uri='builtin://midi-looper', display_name='MIDI Looper', type=node_db.NodeDescription.PROCESSOR, node_ui=node_db.NodeUIDescription( type='builtin://midi-looper', ), builtin_icon='node-type-builtin', processor=node_db.ProcessorDescription( type='builtin://midi-looper', ), ports=[ node_db.PortDescription( name='in', direction=node_db.PortDescription.INPUT, types=[node_db.PortDescription.EVENTS], ), node_db.PortDescription( name='out', direction=node_db.PortDescription.OUTPUT, types=[node_db.PortDescription.EVENTS], ), ] )
def description(self) -> node_db.NodeDescription: node_desc = node_db.NodeDescription() node_desc.CopyFrom(node_description.CVMapperDescription) return node_desc
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # # @end:license from noisicaa import node_db StepSequencerDescription = node_db.NodeDescription( uri='builtin://step-sequencer', display_name='Step Sequencer', type=node_db.NodeDescription.PROCESSOR, node_ui=node_db.NodeUIDescription(type='builtin://step-sequencer', ), builtin_icon='node-type-builtin', processor=node_db.ProcessorDescription(type='builtin://step-sequencer', ), ports=[ node_db.PortDescription( name='tempo', direction=node_db.PortDescription.INPUT, types=[node_db.PortDescription.ARATE_CONTROL], float_value=node_db.FloatValueDescription( min=0.01, max=100.0, default=8, scale=node_db.FloatValueDescription.LOG), ), ])
def description(self) -> node_db.NodeDescription: node_desc = node_db.NodeDescription() node_desc.CopyFrom(node_description.OscilloscopeDescription) return node_desc
async def test_processor(self): self.host_system.set_block_size(256) async with self.create_realm() as realm: node_description = node_db.NodeDescription( uri='test://test', type=node_db.NodeDescription.PROCESSOR, processor=node_db.ProcessorDescription( type='builtin://null', ), ports=[ node_db.PortDescription( name='gain', direction=node_db.PortDescription.INPUT, types=[node_db.PortDescription.KRATE_CONTROL], ), node_db.PortDescription( name='in', direction=node_db.PortDescription.INPUT, types=[node_db.PortDescription.AUDIO], ), node_db.PortDescription( name='out', direction=node_db.PortDescription.OUTPUT, types=[node_db.PortDescription.AUDIO], ), ]) processor = PyProcessor(realm.name, 'amp', self.host_system, node_description) processor.setup() realm.add_active_processor(processor) spec = PySpec() spec.append_buffer( 'sink:in:left', buffers.PyFloatAudioBlockBuffer(node_db.PortDescription.AUDIO)) spec.append_buffer( 'sink:in:right', buffers.PyFloatAudioBlockBuffer(node_db.PortDescription.AUDIO)) spec.append_buffer('gain', buffers.PyFloatControlValueBuffer()) spec.append_buffer( 'in', buffers.PyFloatAudioBlockBuffer(node_db.PortDescription.AUDIO)) spec.append_buffer( 'out', buffers.PyFloatAudioBlockBuffer(node_db.PortDescription.AUDIO)) spec.append_processor(processor) spec.append_opcode('CONNECT_PORT', processor, 0, 'gain') spec.append_opcode('CONNECT_PORT', processor, 1, 'in') spec.append_opcode('CONNECT_PORT', processor, 2, 'out') spec.append_opcode('CALL', processor) realm.set_spec(spec) # Initializes the program with the new spec (required for Realm::get_buffer() to work). program = realm.get_active_program() buf_gain = realm.get_buffer('gain', buffers.PyFloatControlValueBuffer()) buf_gain[0] = 0.5 buf_in = realm.get_buffer( 'in', buffers.PyFloatAudioBlockBuffer(node_db.PortDescription.AUDIO)) buf_in[0] = 1.0 buf_in[1] = 2.0 buf_in[2] = 3.0 buf_in[3] = 4.0 realm.process_block(program)
def get_node_description(self, uri: str) -> node_db.NodeDescription: desc = node_db.NodeDescription() desc.CopyFrom(self.__nodes[uri]) return desc
def scan(self) -> Iterator[node_db.NodeDescription]: world = lilv.World() ns = world.ns world.load_all() plugins = world.get_all_plugins() for plugin in plugins: logger.info("Adding LV2 plugin %s", plugin.get_uri()) desc = node_db.NodeDescription() desc.uri = str(plugin.get_uri()) desc.supported = True desc.type = node_db.NodeDescription.PLUGIN desc.node_ui.type = 'builtin://plugin' desc.builtin_icon = 'node-type-lv2' desc.processor.type = 'builtin://plugin' desc.plugin.type = node_db.PluginDescription.LV2 desc.display_name = str(plugin.get_name()) lv2_desc = desc.lv2 lv2_desc.uri = str(plugin.get_uri()) for uri in plugin.required_features: feature_desc = lv2_desc.features.add() feature_desc.required = True feature_desc.uri = uri if not lv2.supports_plugin_feature(uri): desc.supported = False desc.not_supported_reasons.unsupported_lv2_feature.append(uri) for feature_uri in plugin.optional_features: feature_desc = lv2_desc.features.add() feature_desc.required = False feature_desc.uri = feature_uri for ui in plugin.get_uis(): ui_desc = lv2_desc.uis.add() ui_desc.supported = True ui_desc.uri = ui.uri for cl in ui.get_classes(): if str(cl) in supported_uis: ui_desc.type_uri = str(cl) if not ui_desc.type_uri: ui_desc.supported = False for cl in ui.get_classes(): ui_desc.not_supported_reasons.unsupported_lv2_ui_type.append(str(cl)) for uri in ui.required_features: feature_desc = ui_desc.features.add() feature_desc.required = True feature_desc.uri = uri if not lv2.supports_ui_feature(uri): ui_desc.supported = False ui_desc.not_supported_reasons.unsupported_lv2_feature.append(uri) for feature_uri in ui.optional_features: feature_desc = ui_desc.features.add() feature_desc.required = False feature_desc.uri = feature_uri if ui_desc.supported: ui_desc.bundle_path = ui.bundle_path ui_desc.binary_path = ui.binary_path if not lv2_desc.ui_uri: lv2_desc.ui_uri = ui.uri desc.has_ui = bool(lv2_desc.ui_uri) for port in (plugin.get_port_by_index(i) for i in range(plugin.get_num_ports())): port_desc = desc.ports.add() port_desc.name = str(port.get_symbol()) port_desc.display_name = str(port.get_name()) if port.is_a(ns.lv2.InputPort): port_desc.direction = node_db.PortDescription.INPUT elif port.is_a(ns.lv2.OutputPort): port_desc.direction = node_db.PortDescription.OUTPUT else: raise ValueError(port) if port.is_a(ns.lv2.ControlPort): port_desc.types.append(node_db.PortDescription.KRATE_CONTROL) elif port.is_a(ns.lv2.AudioPort): port_desc.types.append(node_db.PortDescription.AUDIO) elif port.is_a(ns.atom.AtomPort): port_desc.types.append(node_db.PortDescription.EVENTS) else: port_desc.types.append(node_db.PortDescription.UNSUPPORTED) if port.is_a(ns.lv2.ControlPort): # # if port.has_property(ns.lv2.integer): # # # TODO: this should be IntParameter # # parameter_cls = node_db.FloatParameterDescription # # else: # # parameter_cls = node_db.FloatParameterDescription value_desc = port_desc.float_value default, range_min, range_max = port.get_range() if default is not None: if default.is_int(): value_desc.default = int(default) else: value_desc.default = float(default) if range_min is not None: if range_min.is_int(): value_desc.min = int(range_min) else: value_desc.min = float(range_min) if range_max is not None: if range_max.is_int(): value_desc.max = int(range_max) else: value_desc.max = float(range_max) if not desc.supported: # TODO: also add unsupported plugins to DB. logger.warning( "Not adding LV2 plugin %s:\n%s", plugin.get_uri(), desc.not_supported_reasons) continue yield desc
# GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # # @end:license from noisicaa import node_db ControlTrackDescription = node_db.NodeDescription( uri='builtin://control-track', display_name='Control Track', type=node_db.NodeDescription.PROCESSOR, node_ui=node_db.NodeUIDescription( type='builtin://control-track', ), builtin_icon='track-type-control', processor=node_db.ProcessorDescription( type='builtin://cv-generator', ), ports=[ node_db.PortDescription( name='out', direction=node_db.PortDescription.OUTPUT, types=[node_db.PortDescription.ARATE_CONTROL], ), ] )