Recently we came across the need of rendering a flash animation into video directly using linux.
We started doing some searching but nothing stood out as an easy solution. There were, though, a lot of links on how to convert FLV to another video formats (which is a totally different issue).
Then we started to look into the linux open source flash players, and it turns out that Gnash has an experimental feature that allows you to render the animation (including sound) to video and audio files.
Here is explained how to compile Gnash for doing this and how to use some other tools for having an usable video.
This seems to work flawlessly if you don't mind using a hell of disk space since Gnash renders the video as a sequence of uncompressed video frames. Of course we only tried a couple of animations so you may run into some troubles as this feature is supposed to be a bit experimental.
As I said before, this should not be advisable for converting FLV to another video formats (nor to convert animations that use online videos or the like, I guess). There are a lot of easier alternatives to do that (such as ffmpeg).
Hope this helps!
Tuesday, December 8, 2009
Wednesday, July 29, 2009
Wrapping Python methods maintaining the signature (aka wrapping soapmethod)
We lately came across a problem trying to wrap our server side SOAP methods to do some logging.
Looking through the source code of soaplib the problem was clear - it inspects the func_code of the method for it's arguments and we're losing the method signature when wrapping.
Because when you write a wrapper (for logging for example) you generally write a method using *args and **kwargs, for example:
So the catch with this is that the signature that the method callers see is different (basically you can match the method's name, but not much more) - you have lost the parameters of the method.
The soapmethod decorator inspects the func_code of the method to see what arguments it receives. So if you wrap it, you basically break it - something like this:
Our workaround is to create dynamic code that defines a method with the same signature:
This way we make yet another wrapper with the original signature that calls the generic wrapper. You can obviously avoid one layer writing all the code in the dynamically evaluated code block... but I got tired of writing code in a string ;)
Looking through the source code of soaplib the problem was clear - it inspects the func_code of the method for it's arguments and we're losing the method signature when wrapping.
Because when you write a wrapper (for logging for example) you generally write a method using *args and **kwargs, for example:
def wrapMethod(f):
def wrapper(*args, **kwargs):
print "do something before"
#call original method
ret=f(*args, **kwargs)
print "do something after"
return ret
So the catch with this is that the signature that the method callers see is different (basically you can match the method's name, but not much more) - you have lost the parameters of the method.
The soapmethod decorator inspects the func_code of the method to see what arguments it receives. So if you wrap it, you basically break it - something like this:
...
descriptor = func(_soap_descriptor=True,klazz=self.__class__)
File "/usr/lib/python2.5/site-packages/soaplib-0.7.2dev_r27-py2.5.egg/soaplib/service.py", line 39, in explainMethod
in_params = [(_inVariableNames.get(param_names[i],param_names[i]),params[i]) for i in range(0,len(params))]
IndexError: tuple index out of range
Our workaround is to create dynamic code that defines a method with the same signature:
#The original wrapper
def wrapMethod(f):
def wrapper(*args, **kwargs):
print "do something before"
#call original method
ret=f(*args, **kwargs)
print "do something after"
return ret
def literalWrapMethod(f, makeWrapper):
#get the method's parmeters
sargs=", ".join(f.func_code.co_varnames[1:f.func_code.co_argcount])
#dynamic code for the wrapper
code="\
def curryF(f):\n\
def %(origname)s(self, %(args)s):\n\
return f(self, %(args)s)\n\
\n\
return X\
"%{"args":sargs, "origname":f.func_name}
#interpret the method's code
exec(code)
#obtain the wrapper for f
wrp=curryF(makeWrapper(f))
return wrp
#Use the wrapper we wanted to use originally
def logSOAP(f):
return literalWrapMethod(f, wrapMethod)
#Demo on how you'd use this
@soapmethod(soap_types.String,
_returns=soap_types.String)
@logSOAP
def doSomething(inparam):
...
This way we make yet another wrapper with the original signature that calls the generic wrapper. You can obviously avoid one layer writing all the code in the dynamically evaluated code block... but I got tired of writing code in a string ;)
Labels:
co_varnames,
func_code,
howto,
method,
python,
soapmethod,
wrap
Thursday, June 25, 2009
ValueChangeListeners for JSF elements in loops
When you have editable elements in a looping element, like a datable, or a panelSeries making useful valueChangeListeners get's a bit problematic.
In the valueChangeListener you can consult the source, which is the UIComponent that triggered it - but in such a loop the UIComponent is always the same for every iteration.
This means that you can't even make a different binding for each element in the loop - something like:
... because there's only one component and faces won't let you do a binding to a changing element.
But there is one option to retrieve the current value of your iterator variable from the listener, through the ExternalContext's requestMap:
The only drawback of this is that you have to have to force the name of the variable in your loop in the JSP file to the name defined in the valueChangeListener.
<ice:dataTable value="#{myView.serviceList}"
var="service"
id="ServicesTable"
rows="5">
<ice:column id="column1">
<f:facet name="header">
<ice:outputText value="#{msg.name}"></ice:outputText>
</f:facet>
<ice:outputText effect="#{service.effect}" value="#{service.name}" />
</ice:column>
<ice:column id="c_selector">
<f:facet name="header">
<ice:outputText value="#{msg.selected}"/>
</f:facet>
<ice:selectBooleanCheckbox partialSubmit="true" valueChangeListener="#{myView.changeListener}" />
</ice:column>
</ice:dataTable>
In the valueChangeListener you can consult the source, which is the UIComponent that triggered it - but in such a loop the UIComponent is always the same for every iteration.
This means that you can't even make a different binding for each element in the loop - something like:
<ice:selectBooleanCheckbox binding="#{service.checkboxBinding}" partialSubmit="true" valueChangeListener="#{myView.changeListener}" />
... because there's only one component and faces won't let you do a binding to a changing element.
But there is one option to retrieve the current value of your iterator variable from the listener, through the ExternalContext's requestMap:
public class MyView{
public String changeListener(ValueChangeEvent event){
//event.getSource(); will always be the same UIComponent
FacesContext ctx = FacesContext.getCurrentInstance();
//"service" is the name of the "var" attribute of the datatable
ServiceViewObject service=(ServiceViewObject) ctx.getExternalContext().getRequestMap().get("service");
System.out.prinln("You changed the value for: "+service);
return null;
}
}
The only drawback of this is that you have to have to force the name of the variable in your loop in the JSP file to the name defined in the valueChangeListener.
Labels:
current var,
datatable,
externalcontext,
loop,
panelseries,
requestmap,
valuechangelistener
Wednesday, May 27, 2009
Icefaces PanelConfirmation usage example
Hello there...
recently we needed to add confirmation dialogs on some of the user events of our Icefaces application. Luckily, since version 1.8, Icefaces comes with a new component called PanelConfirmation which does the job pretty well and easy.
As I could not find any straight example I decided to write here a little code snippet.
To define the confirmation panel in the very page you need to write the following:
Now you need to bind the dialog with the actions you want to confirm. To do so there is a new property in commandButton and commandLink components. Note the id in the above declaration, it is important to further bind the component. As usual, you will need this id to be unique in the scope.
In the panelConfirmation property you need to put the id of the dialog.
Regrettably there is still not support for this on the rest of the components that trigger user events, such us menuItems. I don't know if this is coming next or there is any implementation reason that prevents the rest of the components to bind to confirmation dialogs.
I still haven't checked whether you can change the dialog properties binding it to it's Java component when the action fires, as it is delayed until the user accepts in the very panel, nor if the dialog properties can be calculated values as in the rest of the components.
In theory you can define the panel anyway in the application as far as it is defined in the context with the proper id.
Hope this helps!
recently we needed to add confirmation dialogs on some of the user events of our Icefaces application. Luckily, since version 1.8, Icefaces comes with a new component called PanelConfirmation which does the job pretty well and easy.
As I could not find any straight example I decided to write here a little code snippet.
To define the confirmation panel in the very page you need to write the following:
<ice:panelConfirmation id="confirmDeletion"
acceptLabel="OK"
cancelLabel="Cancel"
message="You are about to delete. Are you sure?"
title="Confirm delete"
draggable="false"
/>
Now you need to bind the dialog with the actions you want to confirm. To do so there is a new property in commandButton and commandLink components. Note the id in the above declaration, it is important to further bind the component. As usual, you will need this id to be unique in the scope.
<ice:commandButton actionListener="#{myActionListener}" value="Remove" panelConfirmation="confirmDeletion" />
In the panelConfirmation property you need to put the id of the dialog.
Regrettably there is still not support for this on the rest of the components that trigger user events, such us menuItems. I don't know if this is coming next or there is any implementation reason that prevents the rest of the components to bind to confirmation dialogs.
I still haven't checked whether you can change the dialog properties binding it to it's Java component when the action fires, as it is delayed until the user accepts in the very panel, nor if the dialog properties can be calculated values as in the rest of the components.
In theory you can define the panel anyway in the application as far as it is defined in the context with the proper id.
Hope this helps!
Saturday, May 9, 2009
GValueArray Properties
Just a quickie: Want some fancy properties for your gstreamer plugin? For example a GValueArray containing structures? Here it goes...
When describing the property, just specify a GArrayValue object and indicate the GstStructure's GType as the element type (you can specify NULL, if you want it to contain any kind of element)
So basically that's it for specifiying it - now you simply have to create the structures and stuff them into the array:
When describing the property, just specify a GArrayValue object and indicate the GstStructure's GType as the element type (you can specify NULL, if you want it to contain any kind of element)
//spec for the GstStructure
GParamSpec *elem_spec=g_param_spec_boxed("mystructure","...",
"...", g_type_from_name("GstStructure"), G_PARAM_READABLE);
g_object_class_install_property (gobject_class, PROP_N,
g_param_spec_value_array ("somename", "...", "...", elem_spec, G_PARAM_READABLE));
So basically that's it for specifiying it - now you simply have to create the structures and stuff them into the array:
GstStructure *pair = gst_structure_new("mystruct", "one", G_TYPE_STRING, name, "two", G_TYPE_VALUE_ARRAY, pnlist, NULL);
GValue gval;
memset(&gval, 0, sizeof(gval));
//init gval with the structure
g_value_init(&gval, pair->type);
g_value_take_boxed(&gval, pair);
//add it to the property
g_value_array_append(self->property, &gval);
Labels:
complex,
gstreamer,
gststructure,
gtype,
gvaluearray,
property
Wednesday, May 6, 2009
GStreamer Messages
When making applications using Gstreamer, plugging elements blindly together sometimes isn't enough - you may need some communication between those plugins.
In our example, we want to multiplex several MPEG-TS streams. What usually happens is that some streams use the same PID, thus creating the need to remap some of them.
What you can do is implement all this functionality in the Multiplexer or have another element do it. If you do it in two plugins the question on how to communicate the different elements comes up.
We tried to make the application control the elements in the pipeline by the use of properties and signals posted by the elements.
So, when a MPEGTS stream comes in, the remapper sends a message to the app using the pipeline's bus, telling it what PIDs it is using.
The application keeps track of the PIDs of all other streams and can modify the properties to remap some of the colliding PIDs.
So to post a message to the application's bus you simply have to do the following:
A GstMessage simply contains a a structure with the contents - add anything you want - we send an identifier for the event and a GValueArray containing GstStructures (program number and list of PIDs) which maps pretty well to python, too.
If you want to read these messages in a python app, you just have to do the following:
Now you can have a pretty "dumb" element that sends signals, and an application (you can use python for that), that does some of the more difficult logic...
Note: gst-launch also prints out messages with -m option!
In our example, we want to multiplex several MPEG-TS streams. What usually happens is that some streams use the same PID, thus creating the need to remap some of them.
What you can do is implement all this functionality in the Multiplexer or have another element do it. If you do it in two plugins the question on how to communicate the different elements comes up.
We tried to make the application control the elements in the pipeline by the use of properties and signals posted by the elements.
So, when a MPEGTS stream comes in, the remapper sends a message to the app using the pipeline's bus, telling it what PIDs it is using.
The application keeps track of the PIDs of all other streams and can modify the properties to remap some of the colliding PIDs.
So to post a message to the application's bus you simply have to do the following:
GstBus *bus = GST_ELEMENT_BUS(self);
GstStructure *structure=gst_structure_new("mpegmodderevent", "type", G_TYPE_STRING, event_name, "pid_summary", G_TYPE_VALUE_ARRAY, self->input_pids_by_program, NULL);
GstMessage *msg=gst_message_new_custom(GST_MESSAGE_ELEMENT, GST_OBJECT(self), structure);
gst_bus_post(bus, msg);
A GstMessage simply contains a a structure with the contents - add anything you want - we send an identifier for the event and a GValueArray containing GstStructures (program number and list of PIDs) which maps pretty well to python, too.
If you want to read these messages in a python app, you just have to do the following:
def process_signal(bus, message, user_data):
if message.structure!=None and message.structure.get_name()=='mpegmodderevent' and message.structure['type']=='PMT':
print "Signal received: ", message.structure.get_name(), message.structure['type'], message.structure['pid_summary']
return True
pipe=gst.parse_launch(...)
bus=pipe.get_bus()
bus.add_watch(process_signal, None)
#Important to use GMainLoop to process signals
try:
loop=gobject.MainLoop()
loop.run()
except:
pass
Now you can have a pretty "dumb" element that sends signals, and an application (you can use python for that), that does some of the more difficult logic...
Note: gst-launch also prints out messages with -m option!
Labels:
bus,
communication,
gstbus,
gstmessage,
gstreamer,
gststructure,
message,
pipeline,
watch
Subscribe to:
Posts (Atom)