Tuesday, January 1, 2013
Site moved!!
The new feed is http://canvoki.net/coder/blog/atom.xml
Update your links!
Saturday, March 10, 2012
deansi: ANSI colors to html in Python
Let me introduce you deansi, a python module to convert ansi terminal codes to html.
Lately, I am doing some refactorings, enhancements and fixes on TestFarm which lacked of care from us, regardless we use it for CLAM, for our daily work at Barcelona Media, and even to control the status of the unit tests of our students assignments. The testing framework we use for our tests, MiniCppUnit, relies on ANSI colors to highlight the important bits at the terminal output. Sadly, ANSI codes have the opposite effect when you look at that output from the Testfarm summary pages, it gets all quite screwed up.
I gave from granted that there were a common python library or recipe to convert ANSI color codes to html i could use. But i just found this recipe and, in fact, I modified Testfarm to use it, but it seems it is not that reliable and the code had to be extended to do quite basic things. So I decided to spike a test driven developed converter.
I made the module available at GitHub. Its features are:
- Supports most 'm' codes (colors and attributes).
- Fully stylable. It generates a default stylesheet but you can redefine the rules in many ways. For example you can make the colors be different in different containers within the same page (a case i need for TestFarm) or setting style properties for combination of active attributes.
- It is test driven developed and back2back tested, so it is quite reliable, and in the long term features can be extended being quite sure we are not breaking existing functionality.
- Unlike the recipe i found, it does not expect a given pair of starting and closing codes. It is implemented as an state machine, a new span tag is created at every attribute set change having as many html classes as attributes are active at that moment.
- You can use it as module or as a command line tool although command line usage is quite minimal (pipe or single input file parameter)
How it works? If you use it as a python module, you can use it that way:
import deansiYou can change the colors displayed adding style rules after the default ones, for example if you want to change the yellow color when the ansi bright attribute apply, and not to apply bold font (the default) you can say:
html_template = """\
<style>
.ansi_terminal {{ background-color: #222; color: #cfc; }}
{defaultStyle}
</style>
<div class="ansi_terminal">{ansiText}</div>
"""
ansiInput = "\033[31mHello World!!\033[m"
print html_template.format(
defaultStyle = deansi.styleSheet(),
ansiText = deansi.deansi(ansiInput),
)
.ansi_yellow.ansi_bright { color: #FF7; font-weight: inherit; }
If you want several behaviours in the same html you can use css magic like that:
.my_own_ansi_enviroment .ansi_inverse { font-style: italic; border: none; }
I look forward applying it to TestFarm soon so all the miss-conversions are fixed.
Update: During my first search i didn't notice ansi2html. It is quite similar to deansi.
Update 2: Now its applied to testfarm, take a look at the output by clicking on one of the red executions (which should not exist but shit happens).
Labels: ansi colors, python, testfarm
Tuesday, September 6, 2011
CLAM binders, ipyclam and PyQt
I just finished a pair programming session with Xavier Serra. He is going to defend his Final Career Project on Friday and we are preparing some cool demos involving binding ipyclam and pyqt. It has been an exciting session because as we debunked one by one the show stoppers that we were finding, we realized that the potential of the tool mix is wider than we thought.
What we can do now is to build a network with ipyclam, building an interface by combining pyqt and ui files and binding them to that network, all that either in live by using the interactive shell or using a written script. This formula adds the flexibility of scripting to CLAM prototyping system, raising the ceiling of what you can do without raising too much the learning threshold.
For example, let's play a file in a loop with ipyclam:
import ipyclam n=ipyclam.Network(ipyclam.Clam_NetworkProxy()) n.file = n.types.MonoAudioFileReader n.out = n.types.AudioSink n.file.Loop = 1 n.file.SourceFile = "jaume-voice.mp3" n.file > n.out n.backend="PortAudio" n.play()
Then you can instantiate an Oscilloscope, bind it and play:
from PyQt4 import QtCore, QtGui a=QtGui.QApplication([]) w=n.createWidget("Oscilloscope") w.show() w.setProperty("clamOutPort", "file.Samples Read") n.stop() n.bindUi(w) n.play()
You can also load an UI file and bind it simultaneously..
w2 = n.loadUi("myui.ui") w2.show() n.stop() n.bindUi(w2) n.play()
Adding a tonal analysis and some related views
n.stop() n.tonal = n.types.TonalAnalysis n.file > n.tonal w3 = n.createWidget("CLAM::VM::KeySpace") w3.setProperty("clamOutPort", "tonal.Chord Correlation") n.bindUi(w3) w3.show() n.play()
The enabler of the mix has been the new binder architecture in CLAM. Until 1.4, the Prototyper used what we call 'binders' to relate processing elements with user interface elements. Each binder concentrates in a given kind of binding: oscilloscopes, control sliders, transport buttons...
For the upcomming CLAM 1.5 the binder interface (CLAM::QtBinder) has been redefined and moved out from the Prototyper to the qtmonitors module. So now you can use them in any CLAM application. The bindings are now based on Qt dynamic properties which provide more flexibility than former QObject name mangling.
Currently there are several binders implemented:
* Action/Button -> launch a configurator dialog on some processing
* Action/Button -> launch a open dialog for a MonoFileReader
* Checkable -> Send a bool, or a bistable float control
* Slider -> maped float/int control
* Any Monitor -> outPort to monitor
* ControlSurface -> Send pair of controls
* Slider -> ProgressControl or a MonoFileReader or similar to control
Now you can extend those binder by means of plugins as we extended processings. You can use Qt dynamic properties in the interface elements to specify how the binding is done.
The abstract interface provides the static method QtBinder::bindAllBinders() which is the one called by python bindUi. This looks for every ui element in the QObject hierarchy, looks for every registered binder and if they match it is applied.
To implement your own handle you just have to rewrite the bool handles(QObject*) method that returns true if the object managed by the binder (type, name, presence of properties...) and the bool bind(QObject * uiElement, Network & network, QStringList & errors) which does the actual binding. To register the binder, you just have to instanciate one as static variable of a cxx file in your library.
All that is still being building up but its potential seems clear, so i hope that this new way of claming will be useful to you all.
Saturday, February 26, 2011
ipyclam: interactive python console for CLAM networks manipulation
Xavier Serra (not the MTG head, but an homonym student at the UPF) is about to reach an interesting milestone on his Final Career Project related to CLAM. He is developing an interactive Python console for CLAM named ipyclam. It is a text based interface to explore and manipulate CLAM networks. Hopefully this will end being a dock widget within the Network Editor but it is also useful as interactive text console tool and as programming interface, which are the first useful outputs Xavi is about to get. ipyclam comes to cover the need of manipulating complex networks in cases when point and click is just tedious and also that of generating parametrized networks.
Let's make clear that it is not a full wrapper for the CLAM API like Hernan's pyclam, ipyclam just enables high level operations you usually do with Network Editor: instantiating, connecting, configuring and playing modules. Moreover we have intentionally decoupled ipyclam API to any existing CLAM API in order to define the most pythonic, convenient, and clean API we could think. For example the code to build an stereo cable would be:
net = Network() net.processing1 = net.types.AudioSource net.processing1.NOuputs = 2 net.processing2 = net.types.AudioSink net.processing2.NInputs = 2 net.processing1.Output1 > net.processing2.Input1 net.processing1.Output2 > net.processing2.Input2 net.play()
An interesting feature, is that network.code() just returns an string with similar python code, so a network knows how to regenerate itself. This opens the door to python based format for CLAM networks. Bye bye XML!.
Convenience? Yes, please. Connections can be done in batch, broadcasting connections from all the connectors in one processing to all or to a single connection of another:
net.processing1 > net.processing2 # all to all net.processing1.Output1 > net.processing2 # one to all net.processing1 > net.processing2.Input1 # all to one
Convenience is good but all things should be doable. Often most convenient solution is not the best suited for all the cases. Accessing configuration parameters and connectors of any kind directly from proccessing is quite convenient but names can collide, to solve that some special attributes are provided to restrict the name scope.
network.processing1._config.NOutputs network.processing1._inports.InPort1 network.processing1._outports.OutPort1 network.processing1._incontrols.InControl1 network.processing1._outcontrols.OutControl1
Connection names can have spaces, and attributes cannot, so we also provide an alternative subscript syntax.
net.processing1['Output 1']
One of the features I like the more is tab key exploration.
- network.[tab] and you get the list of processings
- network.processing._inports[tab] and you get the list of input ports
- network.processing._config[tab] and you get the list of configuration parameters
- network.processing.[tab] and you get connectors and cofiguration parameters
- network.types.[tab] and you get the list of available processing types
It works for interactive console with tab completion like ipython. We also provide ipyclam_console, an ipython based shell conveniently importing modules and adding a network to start playing with.
For more details on the API just check this document.
The implementation
ipyclam is defined in two layers. The front-end layer, purely written in python, makes the convenient API happen: Exploration, dynamic object attributes, many interfaces to similar operations... This upper layer, relies on the lower, less pythonic and more purpose oriented one, the network proxy layer, which provides access to the state and operations of the actual network with quite fewer entry points.
Xavi defined the front-end layer while evolving, in parallel, a dummy proxy layer simulating network status with basic python structures. That gave us the flexibility to explore and evolve both the frond-end and the proxy interface without bothering about the actual CLAM implementation that would have made such exploration quite rigid.
Two layers approach is also convenient because by defining the ops in the network proxy layer, we are able to reuse the front-end API with any other patching like environment. I am thinking on JACK or environments like ingen.
Status and road map
Xavi just finished most important bits of the API: Inspection, module creation, module type enumeration and module inter-connection. Currently we still rely on a dummy network proxy, but a CLAM based proxy will arrive during next week. Configuration API seems to be controversial and we are holding it until we have something implemented with CLAM.
Once we have a full CLAM based proxy the next big goal is to integrate the console in NetworkEditor. We need a console widget for Qt which is able to execute a python interpret. We found some candidates:
- qconsole which already has a python wrapper
- qtermwidget a more robust console (based on KDE Konsole) but without direct support for python, and
- ipython qt frontend quite experimental and using a weird threading model, but still interesting as ipyclam_console already uses ipython and it is awesome
So either candidate seems to require some work on our side.
Well, I hope you will find this new CLAM feature as amusing as I do. Xavier is really doing quite a good job, congrats and keep it that high.
Wednesday, February 16, 2011
Numpy arrays to video
I found some examples on how to generate video with python by piping frames to external programs like ffmpeg or mencoder. All those snippets encode each frame as a given image format (png, jpg...) by using PIL, matplotlib.. to get them. Besides the dependency, building figures or encoding images can be quite slow. I finally found a way of piping raw numpy buffers as frames to mencoder. You can use the following code:
import subprocess
import numpy as np
class VideoSink(object) :
def __init__( self, size, filename="output", rate=10, byteorder="bgra" ) :
self.size = size
cmdstring = ('mencoder',
'/dev/stdin',
'-demuxer', 'rawvideo',
'-rawvideo', 'w=%i:h=%i'%size[::-1]+":fps=%i:format=%s"%(rate,byteorder),
'-o', filename+'.avi',
'-ovc', 'lavc',
)
self.p = subprocess.Popen(cmdstring, stdin=subprocess.PIPE, shell=False)
def run(self, image) :
assert image.shape == self.size
# image.tofile(self.p.stdin) # should be faster but it is indeed slower
self.p.stdin.write(image.tostring())
def close(self) :
self.p.stdin.close()
It is a tenth faster than the PIL based one. And there is no fair comparison to the matplotlib one. I got it working with mencoder but I could not figure out how to make it with ffmpeg.
You can find that code with an usage example there. Being based on other public domain snippets consider it also public domain.
I am using that class to save the output of my Freenect based project. More on that on next entries.
Monday, January 25, 2010
Libraries becoming plugins, plugins becoming libraries
Let me post about some of the latest changes on the CLAM build system.
The CLAM project has been distributing two kinds of shared libraries: the main library modules (core, audioio and processing) and a set of plugins which are optional (spacialization, osc, guitareffects...). Plugins are very convenient since programs like the NetworkEditor can be extended without recompile and enable third party extensions. They are so convenient that we were seriously considering splitting processing and auidioio as plugins.
But the use of content of a clam plugin is limited to abstract Processing interface. No other symbols are visible from other components. That has a serious impact on the flexibility to define plugin boundaries. For example, if a plugin defines a new data token type, any processings managing that token type should be in that same plugin. To use symbols of one plugin from another implies installing headers, provide soname, linker name and so on. That is, building a module library.
So, if plugins want to be libraries and libraries want to be plugins, let them all be both. Each module will be compiled as library (libclam_mymodule.so.X.Y.Z), with soname (libclam_mymodule.so.X.Y), linker link (libclam_mymodule.so), headers (include/CLAM/mymodule/*), pc file... and it will also provide a plugin library (libclam_mymodule_plugin.so) which has no symbol by itself but is linked against the module library. When a program loads such a plugin, all the processings in the module library become available via the abstract interface. On the other side, if program or a module needs to use explicitly the symbols of another module, it just has to include the headers and link against the module library.
I just applied the changes to the plugins and seems to work nicely. Adapting the main modules will be harder because the old sconstruct file, but it is a matter of days and we can split them. I moved a lot of common SCons code to the clam.py scons tool. There is a cute environment method called ClamModule which generates a clam module including the module library, soname, linker name, plugin, pkg-config, and install targets. I also added some build system freebies for the modules and applications:
- All the intermediate generated code apart in a 'generated' directory
- Non verbose command line
- Colour command line
- Enhanced scanning methods with black lists
Well, do not rely too much on the current clam scons tool API. Changes are still flowing through the subversion. Of course, warn me if I broke something. ;-)
Labels: build system, clam, plugins, scons
Friday, January 15, 2010
Boolean Controls in CLAM
After a long refactoring to get typed controls into clam without breaking anything, we already have them. Kudos for this achievement go also to Francisco (who started the whole thing as its GSoC project), Hernan, Nael and Pau.
Now controls are defined just like ports with a type. So for example, you can define an out control being the type OutControl<MyType>
. As a side effect, control callbacks came in natural way. Instead of using a different class (formerly InControlCallback<MyType, HostProcessingType>
), now you just have to pass a processing method to the control constructor. Templates do the magic too, but that is hidden from the processing programmer API which is cool. See, some example bellow.
So, once we enabled typed controls working, now is time to have more than just float controls. The main problem now is that in order to get some useful new control type you have to modify the network editor and the prototyper to make them useful.
Although the most demanding needs are for enum and integer controls, I started with simpler bool controls. My goal is you don't have to modify the NetworkEditor or the Prototyper to introduce a new control type. That is, a plugin could add new control senders, control displays, default connected processings (double clicking on a control) and binders for the prototyper (to locate ui elements to link to processing controls). So i wanted a new simple use case not being float to explore a feasible API.
Below you can see a network with a BoolControlSender
(widget hxx/cxx, processing hxx,cxx) and a BinaryCounter
(hxx,cxx) outputing into two BoolControlDisplay
(widget hxx/cxx, processing hxx,cxx). Maybe is a little late for using CLAM for your Christmas lights, i guess ;-)
Currently, instead of bools we use floats considering a threshold for being true or false. A new ControlGate
processing provides a transition by doing such translation:
So now is time to look to the code I had to add and see what can be enhanced to ease adding new control types:
- One of the things I didn't liked during the implementation is having to add an entry into a long list of 'if' statements in ProcessingBoxEmbededWidget.cxx. This is clamming for a refactoring into a Factory.
- Also the menu entry filling (to connect to new processing) and the default create-and-connect action become a list of if clauses with the type as parameter.
- Both, prototyper binders and embedded widgets had to duplicate the control sending code. That could be generalized into a binder object that both use.
So, it is clear that there is room for a lot of enhancement and it looks like those enhancements could also be applied to ports as well :-)