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:


<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)


//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);

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:


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!