An open source DAW for GNU/Linux, inspired by modular synths. http://noisicaa.odahoda.de/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

255 lines
9.7 KiB

#!/usr/bin/python3
# @begin:license
#
# Copyright (c) 2015-2019, Benjamin Niemann <pink@odahoda.de>
#
# 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
import asyncio
import logging
import urllib.parse
from noisicaa import core
from noisicaa import editor_main_pb2
from noisicaa.core import empty_message_pb2
from noisicaa.core import ipc
from noisicaa.constants import TEST_OPTS
from noisicaa.node_db.private import db as node_db
logger = logging.getLogger(__name__)
class ServerMixin(object):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.server = None
async def setup_testcase(self):
self.server = ipc.Server(self.loop, 'test', socket_dir=TEST_OPTS.TMP_DIR)
await self.server.setup()
async def cleanup_testcase(self):
if self.server is not None:
await self.server.cleanup()
class NodeDBMixin(object):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.node_db = None
def setup_testcase(self):
self.node_db = node_db.NodeDB()
self.node_db.setup()
def cleanup_testcase(self):
if self.node_db is not None:
self.node_db.cleanup()
class ProcessManagerMixin(object):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.process_manager = None
self.process_manager_client = None
self.__node_db_address = None
self.__node_db_lock = None
self.__instrument_db_address = None
self.__instrument_db_lock = None
self.__urid_mapper_address = None
self.__urid_mapper_lock = None
async def setup_testcase(self):
self.process_manager = core.ProcessManager(event_loop=self.loop, tmp_dir=TEST_OPTS.TMP_DIR)
await self.process_manager.setup()
async def shutdown_process(request, response):
await self.process_manager.shutdown_process(request.address)
self.process_manager.server['main'].add_handler(
'SHUTDOWN_PROCESS', shutdown_process,
editor_main_pb2.ShutdownProcessRequest, empty_message_pb2.EmptyMessage)
self.process_manager_client = ipc.Stub(
self.loop, self.process_manager.server.address)
await self.process_manager_client.connect()
self.__node_db_lock = asyncio.Lock(loop=self.loop)
self.__instrument_db_lock = asyncio.Lock(loop=self.loop)
self.__urid_mapper_lock = asyncio.Lock(loop=self.loop)
async def __shutdown_process(self, address):
if address is None:
return
p = urllib.parse.urlparse(address)
control_address = 'ipc://control@%s' % p.path
try:
stub = ipc.Stub(self.loop, control_address)
try:
await stub.connect()
await stub.call('SHUTDOWN')
finally:
await stub.close()
except ipc.Error as exc:
logger.info("Failed to send SHUTDOWN to %s", address)
async def cleanup_testcase(self):
await self.__shutdown_process(self.__instrument_db_address)
await self.__shutdown_process(self.__node_db_address)
await self.__shutdown_process(self.__urid_mapper_address)
if self.process_manager_client is not None:
await self.process_manager_client.close()
if self.process_manager is not None:
await self.process_manager.cleanup()
async def __create_node_db_process(self, inline, request, response):
async with self.__node_db_lock:
if self.__node_db_address is None:
if inline:
proc = await self.process_manager.start_inline_process(
name='node_db',
entry='noisicaa.node_db.process.NodeDBProcess')
self.__node_db_address = proc.address
else:
raise NotImplementedError
response.address = self.__node_db_address
def setup_node_db_process(self, *, inline):
async def wrap(request, response):
return await self.__create_node_db_process(inline, request, response)
self.process_manager.server['main'].add_handler(
'CREATE_NODE_DB_PROCESS', wrap,
empty_message_pb2.EmptyMessage, editor_main_pb2.CreateProcessResponse)
async def __create_instrument_db_process(self, inline, request, response):
async with self.__instrument_db_lock:
if self.__instrument_db_address is None:
if inline:
proc = await self.process_manager.start_inline_process(
name='instrument_db',
entry='noisicaa.instrument_db.process.InstrumentDBProcess')
self.__instrument_db_address = proc.address
else:
raise NotImplementedError
response.address = self.__instrument_db_address
def setup_instrument_db_process(self, *, inline):
async def wrap(request, response):
await self.__create_instrument_db_process(inline, request, response)
self.process_manager.server['main'].add_handler(
'CREATE_INSTRUMENT_DB_PROCESS', wrap,
empty_message_pb2.EmptyMessage, editor_main_pb2.CreateProcessResponse)
async def __create_urid_mapper_process(self, inline, request, response):
async with self.__urid_mapper_lock:
if self.__urid_mapper_address is None:
if inline:
proc = await self.process_manager.start_inline_process(
name='urid_mapper',
entry='noisicaa.lv2.urid_mapper_process.URIDMapperProcess')
else:
proc = await self.process_manager.start_subprocess(
name='urid_mapper',
entry='noisicaa.lv2.urid_mapper_process.URIDMapperSubprocess')
self.__urid_mapper_address = proc.address
response.address = self.__urid_mapper_address
def setup_urid_mapper_process(self, *, inline):
async def wrap(request, response):
await self.__create_urid_mapper_process(inline, request, response)
self.process_manager.server['main'].add_handler(
'CREATE_URID_MAPPER_PROCESS', wrap,
empty_message_pb2.EmptyMessage, editor_main_pb2.CreateProcessResponse)
async def __create_audioproc_process(self, inline, request, response):
if inline:
proc = await self.process_manager.start_inline_process(
name=request.name,
entry='noisicaa.audioproc.audioproc_process.AudioProcProcess',
block_size=(
request.host_parameters.block_size
if request.host_parameters.HasField('block_size')
else None),
sample_rate=(
request.host_parameters.sample_rate
if request.host_parameters.HasField('sample_rate')
else None))
response.address = proc.address
else:
raise NotImplementedError
def setup_audioproc_process(self, *, inline):
async def wrap(request, response):
return await self.__create_audioproc_process(inline, request, response)
self.process_manager.server['main'].add_handler(
'CREATE_AUDIOPROC_PROCESS', wrap,
editor_main_pb2.CreateAudioProcProcessRequest, editor_main_pb2.CreateProcessResponse)
async def __create_plugin_host_process(self, inline, request, response):
if inline:
proc = await self.process_manager.start_inline_process(
name='plugin_host',
entry='noisicaa.audioproc.engine.plugin_host_process.PluginHostProcess')
else:
proc = await self.process_manager.start_subprocess(
name='plugin_host',
entry='noisicaa.audioproc.engine.plugin_host_process.PluginHostSubprocess')
response.address = proc.address
def setup_plugin_host_process(self, *, inline):
async def wrap(request, response):
return await self.__create_plugin_host_process(inline, request, response)
self.process_manager.server['main'].add_handler(
'CREATE_PLUGIN_HOST_PROCESS', wrap,
empty_message_pb2.EmptyMessage, editor_main_pb2.CreateProcessResponse)
async def __create_project_process(self, inline, request, response):
if inline:
proc = await self.process_manager.start_inline_process(
name=request.uri,
entry='noisicaa.music.project_process.ProjectProcess')
response.address = proc.address
else:
raise NotImplementedError
def setup_project_process(self, *, inline):
async def wrap(request, response):
return await self.__create_project_process(inline, request, response)
self.process_manager.server['main'].add_handler(
'CREATE_PROJECT_PROCESS', wrap,
editor_main_pb2.CreateProjectProcessRequest, editor_main_pb2.CreateProcessResponse)