JACK engine for ipyclam
Here you have a cute alternative to QJackCtl if you have it plenty of ardour multichannel ports connected in fancy ways. Auto-completion, broadcasting and Python slices on ports will be your friends.
ipyclam design enables other modular systems than CLAM to be controlled with the same interactive API just by reimplementing the internal engine. This could be exploited to provide interactive consoles for system such as Galan, Patchage… But a JACK engine is not just a proof of concept but also something that is useful within the CLAM NetworkEditor work-flow. You can explore and handle external JACK connections from the new NetworkEditor console in a similar way you can handle internal CLAM connections.
The screenshot is an independent ipyclam qtconsole with a simple session. Notice how quick is to get a description of the system status and how visual and replicable it is. Unit creation, deletion and renaming has no sense (maybe for testing), so I decide to ignore those messages. Transport control is not implemented either regardless it has sense.
Other changes on ipyclam
JACK engine has been a milestone of a set of changes I did this week to wrap-up ipyclam for the Linux Audio Conference 2013. Let me summarize them here:
Separate UI module
Now ui related methods are no more part of the Engine. They have been moved away and separated in independent modules for PyQt4 and PySide. Besides making the engines independent of Qt/Clam specifics splitting PyQt4 and PySide in two modules finally achieves the goal of having code which is independent of the Python binding, just by changing the imports.
if usePyQt : import ipyclam.ui.PyQt4 as ui from PyQt4 import QtGui, QtCore else: import ipyclam.ui.PySide as ui from PySide import QtGui, QtCore # using ui, QtGui and QtCore freely app = QtGui.QApplication([]) w1 = ui.createWidget("Oscilloscope") w2 = ui.loadUi("file.ui") ...
Engines are engines
Let’s forget about terms like ‘back-end’ and ‘network proxy’.
‘Back-end’ was a ambiguous term because we used it in CLAM for other purposes:
Audio back-ends for JACK, PortAudio, LASDPA…
Moreover, the corresponding classes had a nasty legacy name: XXX_NetworkProxy
.
So I started calling them engines and the classes XXX_Engine
.
Now we have Clam_Engine
, Dummy_Engine
and the brand new Jack_Engine
.
The class naming is not definitive. I would like to make a submodule per engine with the same classes inside, including the Engine and the configuration wrapper. The goal should be having code like this:
from ipyclam.engines.clam import Engine as Clam_Engine, Config as Clam_Config from ipyclam.engines.dummy import Engine as Dummy_Engine, Config as Dummy_Config
But I still I have to figure out how to implement it and it is not a priority.
CLAM and Dummy engines have been unified
They were meant to be analogous but it was clear they weren’t as I tried to pass one engine tests with other’s. It has been the harder task of this week but the good news is that once they were unified, implementing the JACK engine has been a one evening task.
Now all the tests are shared with some required divergences explicitly extracted. Still most about configuration is to be done.
Consistent connection broadcasting
There were incoherences, even within a single engine, about the behaviour of connections when one of the sides was not a single connector.
There are three kind of connectible sides:
- A simple connector
- A connector set:
_inports
,_outports
… and slices - A processing
The behaviour has been defined as follows:
set1 > set2 # is equivalent to ordered one to one connection for connector1,connector2 in zip(set1,set2) : connector1 > connector2 connector > set2 # is equivalent to one to many connection for connector2 in set2 : connector > connector2 processing1 > processing2 # is equivalent to processing1._outcontrols > processing2._incontrols processing1._outports > processing2._inports # for cases like processing > set # or processing > connector # the processing is substituted by the matching set # _inports, _outports, _incontrols or _outcontrols
Angle operator now always check connector directions.
connect
method doesn’t, although when sides are processing units
forward direction is implied.
a > b b < a a.connect(b)
This is very nice!
One question, you mention slices as connectable entity. How does it works? How does a user connect a slice/subrange of a processing ports? Thanks
You are right, I forgot an example on the more interesting feature. If ports are named InPort1, InPort2...
should be equivalent to
Broadcasting rules for connector sets apply to them.
Maybe you tried something more intuitive like:
This is NOT implemented but it could have sense, by taking the direction from the operator, and, either implicitly understanding that we are connecting ports, not controls, or using some heuristic I can not figure out right now.
What do you think? Should we implement that?