Move NodeDB into separate package and process - UI and project processes use a single shared DB process.

looper
Ben Niemann 7 years ago
parent 07408041cf
commit 8bc4dfb7d7

@ -6,7 +6,7 @@ import time
import numpy
from noisicaa.music import node_description
from noisicaa import node_db
from .. import csound
from .. import ports
@ -30,14 +30,14 @@ class CSoundFilter(node.Node):
self._description = description
port_cls_map = {
(node_description.PortType.Audio,
node_description.PortDirection.Input): ports.AudioInputPort,
(node_description.PortType.Audio,
node_description.PortDirection.Output): ports.AudioOutputPort,
(node_description.PortType.Events,
node_description.PortDirection.Input): ports.EventInputPort,
(node_description.PortType.Events,
node_description.PortDirection.Output): ports.EventOutputPort,
(node_db.PortType.Audio,
node_db.PortDirection.Input): ports.AudioInputPort,
(node_db.PortType.Audio,
node_db.PortDirection.Output): ports.AudioOutputPort,
(node_db.PortType.Events,
node_db.PortDirection.Input): ports.EventInputPort,
(node_db.PortType.Events,
node_db.PortDirection.Output): ports.EventOutputPort,
}
for port_desc in self._description.ports:
@ -49,14 +49,14 @@ class CSoundFilter(node.Node):
if port_desc.drywet_port is not None:
kwargs['drywet_port'] = port_desc.drywet_port
port = port_cls(port_desc.name, **kwargs)
if port_desc.direction == node_description.PortDirection.Input:
if port_desc.direction == node_db.PortDirection.Input:
self.add_input(port)
else:
self.add_output(port)
self._parameters = {}
for parameter in self._description.parameters:
if parameter.param_type == node_description.ParameterType.Float:
if parameter.param_type == node_db.ParameterType.Float:
self._parameters[parameter.name] = parameter.default
self._csnd = None
@ -105,7 +105,7 @@ class CSoundFilter(node.Node):
samples[1][pos:pos+self._csnd.ksmps])
for parameter in self._description.parameters:
if parameter.param_type == node_description.ParameterType.Float:
if parameter.param_type == node_db.ParameterType.Float:
self._csnd.set_control_channel_value(
parameter.name, self._parameters[parameter.name])

@ -24,9 +24,15 @@ class Main(object):
self.manager.server.add_command_handler(
'CREATE_AUDIOPROC_PROCESS',
self.handle_create_audioproc_process)
self.manager.server.add_command_handler(
'CREATE_NODE_DB_PROCESS',
self.handle_create_node_db_process)
self.stop_event = asyncio.Event()
self.returncode = 0
self.node_db_process = None
self.node_db_process_lock = asyncio.Lock(loop=self.event_loop)
def run(self, argv):
self.parse_args(argv)
@ -129,6 +135,15 @@ class Main(object):
'noisicaa.audioproc.audioproc_process.AudioProcProcess')
return proc.address
async def handle_create_node_db_process(self):
async with self.node_db_process_lock:
if self.node_db_process is None:
self.node_db_process = await self.manager.start_process(
'node_db',
'noisicaa.node_db.process.NodeDBProcess')
return self.node_db_process.address
if __name__ == '__main__':
sys.exit(Main().run(sys.argv))

@ -24,13 +24,3 @@ from .time_mapper import (
from .misc import (
Pos2F
)
from .node_description import (
PortDirection, PortType,
ParameterType,
InternalParameterDescription,
StringParameterDescription,
PathParameterDescription,
TextParameterDescription,
FloatParameterDescription,
)

@ -3,13 +3,13 @@
import fractions
from noisicaa import core
from noisicaa import node_db
from . import pitch
from . import time
from . import clef
from . import key_signature
from . import time_signature
from . import misc
from . import node_description
class Instrument(core.ObjectBase):
@ -190,11 +190,11 @@ class AudioOutPipelineGraphNode(BasePipelineGraphNode):
def removable(self):
return False
__description = node_description.SystemNodeDescription(
__description = node_db.SystemNodeDescription(
ports=[
node_description.AudioPortDescription(
node_db.AudioPortDescription(
name='in',
direction=node_description.PortDirection.Input),
direction=node_db.PortDirection.Input),
])
@property
@ -209,14 +209,14 @@ class TrackMixerPipelineGraphNode(BasePipelineGraphNode):
def removable(self):
return False
__description = node_description.SystemNodeDescription(
__description = node_db.SystemNodeDescription(
ports=[
node_description.AudioPortDescription(
node_db.AudioPortDescription(
name='in',
direction=node_description.PortDirection.Input),
node_description.AudioPortDescription(
direction=node_db.PortDirection.Input),
node_db.AudioPortDescription(
name='out',
direction=node_description.PortDirection.Output),
direction=node_db.PortDirection.Output),
])
@property
@ -231,11 +231,11 @@ class EventSourcePipelineGraphNode(BasePipelineGraphNode):
def removable(self):
return False
__description = node_description.SystemNodeDescription(
__description = node_db.SystemNodeDescription(
ports=[
node_description.EventPortDescription(
node_db.EventPortDescription(
name='out',
direction=node_description.PortDirection.Output),
direction=node_db.PortDirection.Output),
])
@property
@ -250,14 +250,14 @@ class InstrumentPipelineGraphNode(BasePipelineGraphNode):
def removable(self):
return False
__description = node_description.SystemNodeDescription(
__description = node_db.SystemNodeDescription(
ports=[
node_description.EventPortDescription(
node_db.EventPortDescription(
name='in',
direction=node_description.PortDirection.Input),
node_description.AudioPortDescription(
direction=node_db.PortDirection.Input),
node_db.AudioPortDescription(
name='out',
direction=node_description.PortDirection.Output),
direction=node_db.PortDirection.Output),
])
@property

@ -3,13 +3,13 @@
import logging
from noisicaa import core
from noisicaa import node_db
from . import model
from . import state
from . import commands
from . import mutations
from . import misc
from . import node_description
logger = logging.getLogger(__name__)
@ -44,7 +44,7 @@ class SetPipelineGraphNodeParameter(commands.Command):
assert isinstance(node, BasePipelineGraphNode)
parameter = node.description.get_parameter(self.parameter_name)
if parameter.param_type == node_description.ParameterType.Float:
if parameter.param_type == node_db.ParameterType.Float:
assert self.float_value is not None
node.set_parameter(
parameter.name,
@ -139,7 +139,7 @@ class BasePipelineGraphNode(model.BasePipelineGraphNode, state.StateBase):
params = {}
for parameter in self.description.parameters:
if parameter.param_type == node_description.ParameterType.Float:
if parameter.param_type == node_db.ParameterType.Float:
params[parameter.name] = parameter_values.get(
parameter.name, parameter.default)
@ -148,7 +148,7 @@ class BasePipelineGraphNode(model.BasePipelineGraphNode, state.StateBase):
mutations.SetNodeParameter(self.pipeline_node_id, **params))
for port in self.description.ports:
if port.direction != node_description.PortDirection.Output:
if port.direction != node_db.PortDirection.Output:
continue
port_property_values = dict(

@ -22,7 +22,6 @@ from . import commands
from . import instruments
from . import sheet
from . import misc
from . import node_db
logger = logging.getLogger(__name__)
@ -191,15 +190,14 @@ class JSONDecoder(json.JSONDecoder):
class BaseProject(model.Project, state.RootMixin, state.StateBase):
SERIALIZED_CLASS_NAME = 'Project'
def __init__(self, state=None):
def __init__(self, node_db=None, state=None):
self.listeners = core.CallbackRegistry()
super().__init__(state)
if state is None:
self.metadata = Metadata()
self.node_db = node_db.NodeDB()
self.node_db.setup()
self.node_db = node_db
def get_node_description(self, uri):
return self.node_db.get_node_description(uri)

@ -54,8 +54,9 @@ class ProjectClientBase(object):
class ProjectClientMixin(object):
def __init__(self, *args, **kwargs):
def __init__(self, *args, node_db=None, **kwargs):
super().__init__(*args, **kwargs)
self._node_db = node_db
self._stub = None
self._session_id = None
self._object_map = {}
@ -67,6 +68,7 @@ class ProjectClientMixin(object):
assert self.project is None
self.project = self._object_map[root_id]
self.project.is_root = True
self.project.node_db = self._node_db
async def setup(self):
await super().setup()

@ -10,6 +10,7 @@ import uuid
from noisicaa import core
from noisicaa.core import ipc
from noisicaa import audioproc
from noisicaa import node_db
from . import project
from . import sheet
@ -65,12 +66,29 @@ class AudioProcClient(
pass
class NodeDBClientImpl(object):
def __init__(self, event_loop, server):
super().__init__()
self.event_loop = event_loop
self.server = server
async def setup(self):
pass
async def cleanup(self):
pass
class NodeDBClient(node_db.NodeDBClientMixin, NodeDBClientImpl):
pass
class ProjectProcessMixin(object):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self._shutting_down = None
self.node_db = None
self.project = None
self.sessions = {}
self.pending_mutations = []
@ -107,8 +125,18 @@ class ProjectProcessMixin(object):
self.server.add_command_handler(
'PLAYER_STOP', self.handle_player_stop)
node_db_address = await self.manager.call(
'CREATE_NODE_DB_PROCESS')
self.node_db = NodeDBClient(self.event_loop, self.server)
await self.node_db.setup()
await self.node_db.connect(node_db_address)
async def cleanup(self):
pass
if self.node_db is None:
self.node_db.close()
self.node_db.cleanup()
self.node_db = None
super().cleanup()
async def run(self):
await self._shutting_down.wait()
@ -198,7 +226,7 @@ class ProjectProcessMixin(object):
await self.publish_mutation(mutation)
def _create_blank_project(self, project_cls):
project = project_cls()
project = project_cls(node_db=self.node_db)
s = sheet.Sheet(name='Sheet 1', num_tracks=0)
project.add_sheet(s)
t = score_track.ScoreTrack(name="Track 1")
@ -224,7 +252,7 @@ class ProjectProcessMixin(object):
async def handle_open(self, path):
assert self.project is None
self.project = project.Project()
self.project = project.Project(node_db=self.node_db)
self.project.open(path)
await self.send_initial_mutations()
self.project.listeners.add(

@ -1 +1,20 @@
from .client import NodeDBClient
from .client import NodeDBClientMixin
from .node_description import (
SystemNodeDescription,
UserNodeDescription,
AudioPortDescription,
EventPortDescription,
PortDirection, PortType,
ParameterType,
InternalParameterDescription,
StringParameterDescription,
PathParameterDescription,
TextParameterDescription,
FloatParameterDescription,
)
from .mutations import (
AddNodeDescription,
RemoveNodeDescription,
)

@ -1,5 +1,66 @@
#!/usr/bin/python3
import logging
class NodeDBClient(object):
pass
from noisicaa import core
from noisicaa.core import ipc
from . import mutations
logger = logging.getLogger(__name__)
class NodeDBClientMixin(object):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self._stub = None
self._session_id = None
self._nodes = {}
self.listeners = core.CallbackRegistry()
@property
def nodes(self):
return sorted(
self._nodes.items(), key=lambda i: i[1].display_name)
def get_node_description(self, uri):
return self._nodes[uri]
async def setup(self):
await super().setup()
self.server.add_command_handler(
'NODEDB_MUTATION', self.handle_mutation)
async def connect(self, address, flags=None):
assert self._stub is None
self._stub = ipc.Stub(self.event_loop, address)
await self._stub.connect()
self._session_id = await self._stub.call(
'START_SESSION', self.server.address, flags)
async def disconnect(self, shutdown=False):
if self._session_id is not None:
await self._stub.call('END_SESSION', self._session_id)
self._session_id = None
if self._stub is not None:
if shutdown:
await self.shutdown()
await self._stub.close()
self._stub = None
async def shutdown(self):
await self._stub.call('SHUTDOWN')
async def start_scan(self):
return await self._stub.call('START_SCAN', self._session_id)
def handle_mutation(self, mutation):
logger.info("Mutation received: %s" % mutation)
if isinstance(mutation, mutations.AddNodeDescription):
assert mutation.uri not in self._nodes
self._nodes[mutation.uri] = mutation.description
else:
raise ValueError(mutation)
self.listeners.call('mutation', mutation)

@ -0,0 +1,73 @@
#!/usr/bin/python3
import asyncio
import time
import unittest
from unittest import mock
import asynctest
from noisicaa import core
from noisicaa.core import ipc
from . import process
from . import client
class TestClientImpl(object):
def __init__(self, event_loop):
super().__init__()
self.event_loop = event_loop
self.server = ipc.Server(self.event_loop, 'client')
async def setup(self):
await self.server.setup()
async def cleanup(self):
await self.server.cleanup()
class TestClient(client.NodeDBClientMixin, TestClientImpl):
pass
class TestProcessImpl(object):
def __init__(self, event_loop):
super().__init__()
self.event_loop = event_loop
self.server = ipc.Server(self.event_loop, 'audioproc')
async def setup(self):
await self.server.setup()
async def cleanup(self):
await self.server.cleanup()
class TestProcess(process.NodeDBProcessMixin, TestProcessImpl):
pass
class NodeDBClientTest(asynctest.TestCase):
async def setUp(self):
self.process = TestProcess(self.loop)
await self.process.setup()
self.process_task = self.loop.create_task(
self.process.run())
self.client = TestClient(self.loop)
await self.client.setup()
await self.client.connect(self.process.server.address)
async def tearDown(self):
await self.client.disconnect(shutdown=True)
await self.client.cleanup()
await asyncio.wait_for(self.process_task, None)
await self.process.cleanup()
async def test_start_scan(self):
await self.client.start_scan()
if __name__ == '__main__':
unittest.main()

@ -0,0 +1,23 @@
#!/usr/bin/python3
class Mutation(object):
pass
class AddNodeDescription(Mutation):
def __init__(self, uri, description):
self.uri = uri
self.description = description
def __str__(self):
return '<AddNodeDescription uri="%s">' % self.uri
class RemoveNodeDescription(Mutation):
def __init__(self, uri):
self.uri = uri
def __str__(self):
return '<RemoveNodeDescription uri="%s">' % self.uri

@ -5,8 +5,9 @@ import os
import os.path
from xml.etree import ElementTree
from noisicaa import core
from noisicaa import constants
from . import node_description
from noisicaa import node_db
logger = logging.getLogger(__name__)
@ -14,17 +15,20 @@ logger = logging.getLogger(__name__)
class NodeDB(object):
def __init__(self):
self._nodes = {}
self.listeners = core.CallbackRegistry()
def setup(self):
self.load_csound_nodes()
@property
def nodes(self):
return sorted(
self._nodes.items(), key=lambda i: i[1].display_name)
def cleanup(self):
pass
def get_node_description(self, uri):
return self._nodes[uri]
def initial_mutations(self):
for uri, node_description in sorted(self._nodes.items()):
yield node_db.AddNodeDescription(uri, node_description)
def start_scan(self):
pass
def load_csound_nodes(self):
rootdir = os.path.join(constants.DATA_DIR, 'csound')
@ -46,12 +50,12 @@ class NodeDB(object):
ports = []
for port_elem in root.find('ports').findall('port'):
port_cls = {
'audio': node_description.AudioPortDescription,
'events': node_description.EventPortDescription,
'audio': node_db.AudioPortDescription,
'events': node_db.EventPortDescription,
}[port_elem.get('type')]
direction = {
'input': node_description.PortDirection.Input,
'output': node_description.PortDirection.Output,
'input': node_db.PortDirection.Input,
'output': node_db.PortDirection.Output,
}[port_elem.get('direction')]
kwargs = {}
@ -73,7 +77,7 @@ class NodeDB(object):
parameters = []
for parameter_elem in root.find('parameters').findall('parameter'):
parameter_cls = {
'float': node_description.FloatParameterDescription,
'float': node_db.FloatParameterDescription,
}[parameter_elem.get('type')]
kwargs = {}
@ -94,13 +98,13 @@ class NodeDB(object):
code = ''.join(root.find('code').itertext())
code = code.strip() + '\n'
parameters.append(
node_description.InternalParameterDescription(
node_db.InternalParameterDescription(
name='code', value=code))
display_name = ''.join(
root.find('display-name').itertext())
node_desc = node_description.UserNodeDescription(
node_desc = node_db.UserNodeDescription(
display_name=display_name,
node_cls='csound_filter',
ports=ports,

@ -2,13 +2,13 @@
import unittest
from . import node_db
from . import db
class NodeDBTest(unittest.TestCase):
def test_load_csound_nodes(self):
db = node_db.NodeDB()
db.load_csound_nodes()
node_db = db.NodeDB()
node_db.load_csound_nodes()
if __name__ == '__main__':

@ -0,0 +1,135 @@
#!/usr/bin/python3
import asyncio
import functools
import logging
import uuid
from noisicaa import core
from noisicaa.core import ipc
from .private import db
logger = logging.getLogger(__name__)
class InvalidSessionError(Exception): pass
class Session(object):
def __init__(self, event_loop, callback_stub, flags):
self.event_loop = event_loop
self.callback_stub = callback_stub
self.flags = flags or set()
self.id = uuid.uuid4().hex
self.pending_mutations = []
def cleanup(self):
pass
def publish_mutation(self, mutation):
if not self.callback_stub.connected:
self.pending_mutations.append(mutation)
return
callback_task = self.event_loop.create_task(
self.callback_stub.call('NODEDB_MUTATION', mutation))
callback_task.add_done_callback(self.publish_mutation_done)
def publish_mutation_done(self, callback_task):
assert callback_task.done()
exc = callback_task.exception()
if exc is not None:
logger.error(
"NODEDB_MUTATION failed with exception: %s", exc)
def callback_stub_connected(self):
assert self.callback_stub.connected
while self.pending_mutations:
self.publish_mutation(self.pending_mutations.pop(0))
class NodeDBProcessMixin(object):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.sessions = {}
self.db = db.NodeDB()
async def setup(self):
await super().setup()
self._shutting_down = asyncio.Event()
self._shutdown_complete = asyncio.Event()
self.server.add_command_handler(
'START_SESSION', self.handle_start_session)
self.server.add_command_handler(
'END_SESSION', self.handle_end_session)
self.server.add_command_handler('SHUTDOWN', self.handle_shutdown)
self.server.add_command_handler(
'START_SCAN', self.handle_start_scan)
self.db.setup()
async def cleanup(self):
self.db.cleanup()
await super().cleanup()
async def run(self):
await self._shutting_down.wait()
logger.info("Shutting down...")
self._shutdown_complete.set()
def get_session(self, session_id):
try:
return self.sessions[session_id]
except KeyError:
raise InvalidSessionError
def publish_mutation(self, mutation):
for session in self.sessions.values():
session.publish_mutation(mutation)
def handle_start_session(self, client_address, flags):
client_stub = ipc.Stub(self.event_loop, client_address)
connect_task = self.event_loop.create_task(client_stub.connect())
session = Session(self.event_loop, client_stub, flags)
connect_task.add_done_callback(
functools.partial(self._client_connected, session))
self.sessions[session.id] = session
# Send initial mutations to build up the current pipeline
# state.
for mutation in self.db.initial_mutations():
session.publish_mutation(mutation)
return session.id
def _client_connected(self, session, connect_task):
assert connect_task.done()
exc = connect_task.exception()
if exc is not None:
logger.error("Failed to connect to callback client: %s", exc)
return
session.callback_stub_connected()
def handle_end_session(self, session_id):
session = self.get_session(session_id)
session.cleanup()
del self.sessions[session_id]
async def handle_shutdown(self):
logger.info("Shutdown received.")
self._shutting_down.set()
logger.info("Waiting for shutdown to complete...")
await self._shutdown_complete.wait()
logger.info("Shutdown complete.")
async def handle_start_scan(self, session_id):
self.get_session(session_id)
return self.db.start_scan()
class NodeDBProcess(NodeDBProcessMixin, core.ProcessImpl):
pass

@ -16,6 +16,7 @@ from PyQt5.QtWidgets import (
)
from noisicaa import audioproc
from noisicaa import node_db
from noisicaa import music
from noisicaa import devices
from ..exceptions import RestartAppException, RestartAppCleanException
@ -81,6 +82,22 @@ class AudioProcClient(
self.__app.onPipelineStatus(status)
class NodeDBClientImpl(object):
def __init__(self, event_loop, server):
super().__init__()
self.event_loop = event_loop
self.server = server
async def setup(self):
pass
async def cleanup(self):
pass
class NodeDBClient(node_db.NodeDBClientMixin, NodeDBClientImpl):
pass
class BaseEditorApp(QApplication):
def __init__(self, process, runtime_settings, settings=None):
super().__init__(['noisicaä'])
@ -105,6 +122,7 @@ class BaseEditorApp(QApplication):
self.midi_hub = None
self.audioproc_client = None
self.audioproc_process = None
self.node_db = None
async def setup(self):
self.default_style = self.style().objectName()
@ -114,8 +132,10 @@ class BaseEditorApp(QApplication):
style = QStyleFactory.create(style_name)
self.setStyle(style)
await self.createNodeDB()
self.project_registry = project_registry.ProjectRegistry(
self.process.event_loop, self.process.manager)
self.process.event_loop, self.process.manager, self.node_db)
self.sequencer = self.createSequencer()
@ -163,6 +183,15 @@ class BaseEditorApp(QApplication):
async def createAudioProcProcess(self):
pass
async def createNodeDB(self):
node_db_address = await self.process.manager.call(
'CREATE_NODE_DB_PROCESS')
self.node_db = NodeDBClient(
self.process.event_loop, self.process.server)
await self.node_db.setup()
await self.node_db.connect(node_db_address)
def dumpSettings(self):
for key in self.settings.allKeys():
value = self.settings.value(key)

@ -3,9 +3,9 @@
import logging
from noisicaa import core
from noisicaa import node_db
from noisicaa.music import model
from noisicaa.music import project_client
from noisicaa.music import node_db
logger = logging.getLogger(__name__)
@ -45,8 +45,7 @@ class Project(model.Project, project_client.ObjectProxy):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.node_db = node_db.NodeDB()
self.node_db.setup()
self.node_db = None
def get_node_description(self, uri):
return self.node_db.get_node_description(uri)

@ -10,8 +10,8 @@ from PyQt5 import QtGui
from PyQt5 import QtWidgets
from noisicaa import music
from noisicaa import node_db
from noisicaa.audioproc import node_types
from noisicaa.music import node_db
from . import ui_base
from . import dock_widget
from . import mute_button
@ -31,7 +31,7 @@ class Port(QtWidgets.QGraphicsRectItem):
self.setRect(0, 0, 45, 15)
self.setBrush(Qt.white)
if self.port_desc.direction == music.PortDirection.Input:
if self.port_desc.direction == node_db.PortDirection.Input:
self.dot_pos = QtCore.QPoint(7, 7)
sym_pos = QtCore.QPoint(45-11, -1)
else:
@ -49,10 +49,10 @@ class Port(QtWidgets.QGraphicsRectItem):
dot.setBrush(Qt.black)
dot.pen().setStyle(Qt.NoPen)
if self.port_desc.port_type == music.PortType.Audio:
if self.port_desc.port_type == node_db.PortType.Audio:
sym = QtWidgets.QGraphicsSimpleTextItem(self)
sym.setText('A')
elif self.port_desc.port_type == music.PortType.Events:
elif self.port_desc.port_type == node_db.PortType.Events:
sym = QtWidgets.QGraphicsSimpleTextItem(self)
sym.setText('E')
else:
@ -62,10 +62,10 @@ class Port(QtWidgets.QGraphicsRectItem):
def getInfoText(self):
return {
(music.PortType.Audio, music.PortDirection.Input): "Audio Input port",
(music.PortType.Audio, music.PortDirection.Output): "Audio Output port",
(music.PortType.Events, music.PortDirection.Input): "Event Input port",
(music.PortType.Events, music.PortDirection.Output): "Event Output port",
(node_db.PortType.Audio, node_db.PortDirection.Input): "Audio Input port",
(node_db.PortType.Audio, node_db.PortDirection.Output): "Audio Output port",
(node_db.PortType.Events, node_db.PortDirection.Input): "Event Input port",
(node_db.PortType.Events, node_db.PortDirection.Output): "Event Output port",
}[(self.port_desc.port_type, self.port_desc.direction)]
def setHighlighted(self, highlighted):
@ -149,8 +149,8 @@ class NodePropertyDock(ui_base.ProjectMixin, dock_widget.DockWidget):
layout.addRow("Name", self._name)
for port in self._node_item.node_description.ports:
if not (port.direction == music.PortDirection.Output
and port.port_type == music.PortType.Audio):
if not (port.direction == node_db.PortDirection.Output
and port.port_type == node_db.PortType.Audio):
continue
port_property_values = dict(
@ -217,7 +217,7 @@ class NodePropertyDock(ui_base.ProjectMixin, dock_widget.DockWidget):
for p in self._node_item.node.parameter_values)
for parameter in self._node_item.node_description.parameters:
if parameter.param_type == music.ParameterType.Float:
if parameter.param_type == node_db.ParameterType.Float:
widget = QtWidgets.QLineEdit(self)
widget.setText(str(parameter_values.get(
parameter.name, parameter.default)))
@ -308,12 +308,12 @@ class NodeItemImpl(QtWidgets.QGraphicsRectItem):
in_y = 25
out_y = 25
for port_desc in self._node.description.ports:
if port_desc.direction == music.PortDirection.Input:
if port_desc.direction == node_db.PortDirection.Input:
x = -5
y = in_y
in_y += 20
elif port_desc.direction == music.PortDirection.Output:
elif port_desc.direction == node_db.PortDirection.Output:
x = 105-45
y = out_y
out_y += 20
@ -342,7 +342,7 @@ class NodeItemImpl(QtWidgets.QGraphicsRectItem):
(p.name, p.value) for p in self._node.parameter_values)
for parameter in self._node.description.parameters:
if parameter.param_type == music.ParameterType.Float:
if parameter.param_type == node_db.ParameterType.Float:
value = parameter_values.get(
parameter.name, parameter.default)
info_lines.append("%s: %s" % (
@ -508,7 +508,7 @@ class DragConnection(QtWidgets.QGraphicsPathItem):
pos1 = self.port.mapToScene(self.port.dot_pos)
pos2 = self.end_pos
if self.port.port_desc.direction == music.PortDirection.Input:
if self.port.port_desc.direction == node_db.PortDirection.Input:
pos1, pos2 = pos2, pos1
cpos = QtCore.QPointF(min(100, abs(pos2.x() - pos1.x()) / 2), 0)
@ -728,11 +728,11 @@ class PipelineGraphGraphicsViewImpl(QtWidgets.QGraphicsView):
self._drag_src_port.setHighlighted(False)
self._drag_dest_port.setHighlighted(False)
if self._drag_src_port.port_desc.direction != music.PortDirection.Output:
if self._drag_src_port.port_desc.direction != node_db.PortDirection.Output:
self._drag_src_port, self._drag_dest_port = self._drag_dest_port, self._drag_src_port
assert self._drag_src_port.port_desc.direction == music.PortDirection.Output
assert self._drag_dest_port.port_desc.direction == music.PortDirection.Input
assert self._drag_src_port.port_desc.direction == node_db.PortDirection.Output
assert self._drag_dest_port.port_desc.direction == node_db.PortDirection.Input
self.send_command_async(
self._sheet.id, 'AddPipelineGraphConnection',
@ -787,11 +787,7 @@ class NodesList(ui_base.CommonMixin, QtWidgets.QListWidget):
self.setDragDropMode(
QtWidgets.QAbstractItemView.DragOnly)
# TODO: should use one globally shared NodeDB.
self.node_db = node_db.NodeDB()
self.node_db.setup()
for uri, node_desc in self.node_db.nodes:
for uri, node_desc in self.app.node_db.nodes:
list_item = QtWidgets.QListWidgetItem()
list_item.setText(node_desc.display_name)
list_item.setData(Qt.UserRole, uri)

@ -12,10 +12,11 @@ logger = logging.getLogger(__name__)
class Project(object):
def __init__(self, path, event_loop, process_manager):
def __init__(self, path, event_loop, process_manager, node_db):
self.path = path
self.event_loop = event_loop
self.process_manager = process_manager
self.node_db = node_db
self.process_address = None
self.client = None
@ -27,7 +28,8 @@ class Project(object):
async def create_process(self):
self.process_address = await self.process_manager.call(
'CREATE_PROJECT_PROCESS', self.path)
self.client = music.ProjectClient(self.event_loop)
self.client = music.ProjectClient(
self.event_loop, node_db=self.node_db)
self.client.cls_map.update(model.cls_map)
await self.client.setup()
await self.client.connect(self.process_address)
@ -50,22 +52,25 @@ class Project(object):
class ProjectRegistry(QtCore.QObject):
projectListChanged = QtCore.pyqtSignal()
def __init__(self, event_loop, process_manager):
def __init__(self, event_loop, process_manager, node_db):
super().__init__()
self.event_loop = event_loop
self.process_manager = process_manager
self.node_db = node_db
self.projects = {}
async def open_project(self, path):
project = Project(path, self.event_loop, self.process_manager)
project = Project(
path, self.event_loop, self.process_manager, self.node_db)
await project.open()
self.projects[path] = project
self.projectListChanged.emit()
return project
async def create_project(self, path):
project = Project(path, self.event_loop, self.process_manager)
project = Project(
path, self.event_loop, self.process_manager, self.node_db)
await project.create()
self.projects[path] = project
self.projectListChanged.emit()

Loading…
Cancel
Save