signal handling from java

357 views
Skip to first unread message

Farkas Levente

unread,
Mar 27, 2008, 12:45:55 PM3/27/08
to gstream...@googlegroups.com
hi,
in gstreamer if a filter would like to notify the application then it
can use signals in c. unfortunately is not well documented:
http://gstreamer.freedesktop.org/data/doc/gstreamer/head/pwg/html/chapter-building-signals.html
but for me it seem this functionality has not a gstreamer-java binding.
or do i missed something? eg. we'd like to notify the application when
we recognize motion or even give back the center and direction of the
motion in a given video.
how can we call a function (add a java listener) from an element?
how can we pass data any more complicated structure from c to java?
or if it's currently not implemented where we should add this functionality?
thanks in advance.

--
Levente
"The only thing worse than not knowing the truth is
ruining the bliss of ignorance."

Wayne Meissner

unread,
Mar 27, 2008, 1:32:45 PM3/27/08
to gstream...@googlegroups.com
The signal connect/disconnect mechanics are there, just not pretty and
not documented.

Have a look at org.gstreamer.GObject.connect()

To use it, you have to implement a Callback.
e.g.

If in C, your callback signature looks something like:

void (*callback)(GObject *obj, int param1, int param2, void *data);

Then in java you need to create:
interface MyCallback extends org.gstreamer.lowlevel.GstAPI.GstCallback {
public void callback(GObject obj, int param1, int param2, Pointer data);
}

You should then be able to connect the signal with:

Element e = ... // however you create the element
MyCallback cb = new MyCallback() {
public void callback(GObject obj, int param1, int param2, Pointer data) {
/// insert signal handling code here
}
};
e.connect("my-motion-signal", MyCallback.class, cb, cb);

I have not actually tried that on anything other than the standard
gstreamer signals, but thats pretty much how they're implemented in
gstreamer-java.

As for passing data, you could create a new Structure class that
matches your C structure, and pass a pointer to that as one of the
callback parameters.

A couple of things to note about all of this:
1) Its all largely undocumented and untested, so you could be in for
some fun/pain.

2) make sure the Callback signature matches the C callback signature,
otherwise you can crash the JVM.

3) Make sure your callback interface extends GstCallback - this makes
sure JNA does auto-conversion of the arguments - e.g. it will map
GObject, Element, etc arguments to those gstreamer-java types.

4) Be careful about the lifetime of the GstCallback instances - if you
let them go out of scope, they may get garbage collected and get
disconnected.

Farkas Levente

unread,
May 16, 2008, 6:25:38 AM5/16/08
to gstream...@googlegroups.com
hi,
we try it but we've got a small problem.
The C side in the class_init function of our custom filter:

klass->signaltest_signal = g_signal_new("signaltest",
GST_TYPE_SIGNALTEST,
G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
0,
NULL /* accumulator */,
NULL /* accu_data */,
g_cclosure_marshal_VOID__INT,
G_TYPE_NONE /* return_type */,
1 /* n_params */,
G_TYPE_INT /* param_types */);

And in the chain function we have:

int i;
g_signal_emit(filter, klass->signaltest_signal, 0, i);


Java side:

Iterface:

interface MyCallback extends org.gstreamer.lowlevel.GstAPI.GstCallback {
public void callback(GObject source, int data);
}

Pipeline creation:

MyCallback cb = new MyCallback() {

public void callback(GObject source, int data){
System.err.println("Callback data: "+ data);
}
};

Element signaltest = ElementFactory.make("signaltest", "signaltest1");

signaltest.connect("signaltest", MyCallback.class, cb, cb);

but if we try to compile it we've got a compile time error:
-------------------------------------------------------------
Exception in thread "main" java.lang.IllegalArgumentException: Callback
argument class org.gstreamer.GObject requires custom type conversion
at com.sun.jna.CallbackReference.<init>(CallbackReference.java:120)
at
com.sun.jna.CallbackReference.getFunctionPointer(CallbackReference.java:212)
at com.sun.jna.Function.convertArgument(Function.java:383)
at com.sun.jna.Function.invoke(Function.java:203)
at com.sun.jna.Library$Handler.invoke(Library.java:204)
at $Proxy18.g_signal_connect_data(Unknown Source)
at org.gstreamer.GObject.g_signal_connect(Unknown Source)
at org.gstreamer.GObject$SignalCallback.<init>(Unknown Source)
at org.gstreamer.GObject.connect(Unknown Source)
-------------------------------------------------------------

if we change the two GObject in the java code to int then everything is
working although it's not right solution.
what can be the problem?
thank you for your help in advance.
yours.

ps. as you ask what kind of tutorial would be useful before 1.0 imho a C
to Java callback tutorial would be useful since it's not so trivial.
if you like we can put together a little gstreamer plug in which just
call a simple callback (eg one it like in the above example).

Wayne Meissner

unread,
May 18, 2008, 10:54:35 PM5/18/08
to gstream...@googlegroups.com
2008/5/16 Farkas Levente <lfa...@gmail.com>:

> Java side:
>
> Iterface:
>
> interface MyCallback extends org.gstreamer.lowlevel.GstAPI.GstCallback {
> public void callback(GObject source, int data);
> }

You can probably stop the error by declaring the first argument to the
callback to be a GstObject or Element (assuming it is a subclass of
GstObject or Element - and I'm pretty sure all plugins are subclasses
of at least GstObject). If you don't actually need the argument, use
a com.sun.jna.Pointer as the argument type.

i.e. the signature for callback could be:

public void callback(GstObject source, int data);

> ps. as you ask what kind of tutorial would be useful before 1.0 imho a C
> to Java callback tutorial would be useful since it's not so trivial.
> if you like we can put together a little gstreamer plug in which just
> call a simple callback (eg one it like in the above example).

Hmm. Interesting. How many people do you think are going to be
writing plugins in C and using them from java?

The whole signal handling is probably in need of a revamp - it was
done the way it was to just support common plugins in as simple a way
as possible.

Levente Farkas

unread,
May 19, 2008, 11:35:11 AM5/19/08
to gstream...@googlegroups.com
On Mon, May 19, 2008 at 4:54 AM, Wayne Meissner <wmei...@gmail.com> wrote:

2008/5/16 Farkas Levente <lfa...@gmail.com>:

> Java side:
>
> Iterface:
>
> interface MyCallback extends org.gstreamer.lowlevel.GstAPI.GstCallback {
>        public void callback(GObject source, int data);
> }

You can probably stop the error by declaring the first argument to the
callback to be a GstObject or Element (assuming it is a subclass of
GstObject or Element - and I'm pretty sure all plugins are subclasses
of at least GstObject).   If you don't actually need the argument, use
a com.sun.jna.Pointer as the argument type. 

i.e. the signature for callback could be:

   public void callback(GstObject source, int data);

none of them working (except the Pointer), but i assume you see it's not a solution:-(


> ps. as you ask what kind of tutorial would be useful before 1.0 imho a C
> to Java callback tutorial would be useful since it's not so trivial.
> if you like we can put together a little gstreamer plug in which just
> call a simple callback (eg one it like in the above example).

Hmm.  Interesting.  How many people do you think are going to be
writing plugins in C and using them from java?

imho it's not just our problem. there are signals already in gstreamer.
just see the identity filter (gst-inspect identity) and the attached example.
it's pure java use nothing else just gstreamer-java and core elements
and try to register to the handoff signal (off course you shouldn't have to use
video identity works for all kind of data). and it's also gives error.
element signals are basic part of gstreamer so imho it'd have to supported in
gstreamer-java 1.0. i don't know whether it's our fault or and just use gstreamer-java
in a wrong way or not (that's why we request for help:-)
thanks in advance.
yours.




--
Levente "Si vis pacem para bellum!"
stest.java

Wayne Meissner

unread,
May 19, 2008, 10:03:03 PM5/19/08
to gstream...@googlegroups.com
Instead of declaring an interface, try declaring MyCallback as an
abstract class.
e.g.
abstract public class MyCallback implements
org.gstreamer.lowlevel.GstAPI.GstCallback {
abstract public void callback(GstObject source, int data);
}

This is needed due to the way that JNA looks up the interface to use
for type conversion, its not using GstCallback, but MyCallback - which
doesn't have custom type conversions.

As for stest.java, do you have a another example? Handoff signals are
better handled via:

identity.connect(new Element.HANDOFF() { ... });

you also need to set the 'signal-handoffs' property to true.


2008/5/20 Levente Farkas <lfa...@gmail.com>:

Farkas Levente

unread,
May 20, 2008, 5:24:46 AM5/20/08
to gstream...@googlegroups.com
Wayne Meissner wrote:
> Instead of declaring an interface, try declaring MyCallback as an
> abstract class.
> e.g.
> abstract public class MyCallback implements
> org.gstreamer.lowlevel.GstAPI.GstCallback {
> abstract public void callback(GstObject source, int data);
> }
>
> This is needed due to the way that JNA looks up the interface to use
> for type conversion, its not using GstCallback, but MyCallback - which
> doesn't have custom type conversions.

we try this also but doesn't work for us either:-(
see the attached source and this error:


Exception in thread "main" java.lang.IllegalArgumentException: Callback

argument class org.gstreamer.Element requires custom type conversion


at com.sun.jna.CallbackReference.<init>(CallbackReference.java:120)
at
com.sun.jna.CallbackReference.getFunctionPointer(CallbackReference.java:212)
at com.sun.jna.Function.convertArgument(Function.java:383)
at com.sun.jna.Function.invoke(Function.java:203)
at com.sun.jna.Library$Handler.invoke(Library.java:204)

at $Proxy19.g_signal_connect_data(Unknown Source)


at org.gstreamer.GObject.g_signal_connect(Unknown Source)
at org.gstreamer.GObject$SignalCallback.<init>(Unknown Source)
at org.gstreamer.GObject.connect(Unknown Source)

at stest.main(stest.java:34)

> As for stest.java, do you have a another example? Handoff signals are
> better handled via:
>
> identity.connect(new Element.HANDOFF() { ... });
>
> you also need to set the 'signal-handoffs' property to true.

for me this command:
# for i in `gst-inspect|egrep -v typefind|cut -f2 -d ":"|sort|uniq` ; do
gst-inspect $i ; done|grep "Element Signals"|wc -l
gives 33 result so in the current gstreamer packages there are 33
element which has signals.
eg. cdaudio's track-change which is very useful is someone like to write
a cd player.
-------------------------------
Element Signals:
"track-change" : void user_function (GstElement* object,
gint arg0,
gpointer user_data);
-------------------------------

MySCallback.java
stest.java

Wayne Meissner

unread,
May 21, 2008, 9:29:49 PM5/21/08
to gstream...@googlegroups.com
Alright, I implemented generic signals - you get no type checking, and
if you get the arguments wrong and/or it crashes the jvm, you're on
your own.

Example:
To connect to the "handoff" signal on an Element, you do:

Element e = ...;
e.connect("handoff", new Closure() {
public void invoke(Element element, Buffer buffer, Pad pad) {
// user code goes here
}
});

Note the lack of any 'user_data' parameter - since it doesn't make
sense with java, it is chopped off internally.

I might implement some form of type checking later on using the
gobject signal introspection facilities.

2008/5/20 Farkas Levente <lfa...@gmail.com>:

Levente Farkas

unread,
May 22, 2008, 6:23:55 AM5/22/08
to gstream...@googlegroups.com
many thanks.
it's worth for version 0.8:-)

lfarkas

unread,
May 23, 2008, 9:27:43 AM5/23/08
to gstreamer-java
hi,
the strange thing it's not working for our filter:-(
first of all in your handoff example what is the last "Pad pad"
parameter?
from where it's comes? or it's just a typo?
the strange thing it's working even if we delete this last parameter
and if not also!?
another note in the comment:
-------------------------------------
// The closure does not have a 'user_data' pointer, so push it in as
the
// first arg. The first arg will be skipped later in callback()
-------------------------------------
^^^^^^^
isn't it last arg?
and later also:
-------------------------------------
// Skip the first arg - it is the 'user_data' pointer
-------------------------------------

anuway. after looking into you diff should this ClosureProxy handle
only pointer
(ie. class arguments) and not buildin types like int?
out signal is like cdaudio's track-change signal which has one int
argument (beside the
GstElement and the user_data). when we rewrite it's argument to
anything else the buildin
type then it's working.
do you think the current code should handle this ans just we made some
mistake or not?
thanks in advance.
yours.


On May 22, 12:23 pm, "Levente Farkas" <lfar...@gmail.com> wrote:
> many thanks.
> it's worth for version 0.8:-)
>
>
>
> On Thu, May 22, 2008 at 3:29 AM, Wayne Meissner <wmeiss...@gmail.com> wrote:
>
> > Alright, I implemented generic signals - you get no type checking, and
> > if you get the arguments wrong and/or it crashes the jvm, you're on
> > your own.
>
> > Example:
> > To connect to the "handoff" signal on an Element, you do:
>
> > Element e = ...;
> > e.connect("handoff", new Closure() {
> > public void invoke(Element element, Buffer buffer, Pad pad) {
> > // user code goes here
> > }
> > });
>
> > Note the lack of any 'user_data' parameter - since it doesn't make
> > sense with java, it is chopped off internally.
>
> > I might implement some form of type checking later on using the
> > gobject signal introspection facilities.
>
> > 2008/5/20 Farkas Levente <lfar...@gmail.com>:
> > >> 2008/5/20 Levente Farkas <lfar...@gmail.com>:
> > >>> On Mon, May 19, 2008 at 4:54 AM, Wayne Meissner <wmeiss...@gmail.com>
> > wrote:
> > >>>> 2008/5/16 Farkas Levente <lfar...@gmail.com>:

Wayne Meissner

unread,
May 23, 2008, 2:50:52 PM5/23/08
to gstream...@googlegroups.com
2008/5/23 lfarkas <lfa...@gmail.com>:

>
> hi,
> the strange thing it's not working for our filter:-(
> first of all in your handoff example what is the last "Pad pad"
> parameter?
> from where it's comes? or it's just a typo?

It comes from the fakesrc/fakesink handoff example I was testing with.
Strangely, the identity handoff has a different callback signature to
those elements.

> the strange thing it's working even if we delete this last parameter
> and if not also!?

Deleting a parameter will generally work ok - at least on x86 machines
- but adding an extra param could crash the JVM.

> another note in the comment:
> -------------------------------------
> // The closure does not have a 'user_data' pointer, so push it in as
> the
> // first arg. The first arg will be skipped later in callback()
> -------------------------------------
> ^^^^^^^
> isn't it last arg?
> and later also:
> -------------------------------------
> // Skip the first arg - it is the 'user_data' pointer
> -------------------------------------

I was using G_CONNECT_SWAPPED - that swaps the instance and user_data
params around (so user_data is first). I thought it would make the
argument munging easier, but it doesn't, so I changed it back to the
default order.

>
> anuway. after looking into you diff should this ClosureProxy handle
> only pointer
> (ie. class arguments) and not buildin types like int?

Primitive types (int, long, etc) should be converted by JNA at a lower level.

> out signal is like cdaudio's track-change signal which has one int
> argument (beside the
> GstElement and the user_data). when we rewrite it's argument to
> anything else the buildin
> type then it's working.
> do you think the current code should handle this ans just we made some
> mistake or not?

It _should_ handle it, but I haven't tested it. If you can, track
down another standard element signal that has similar primitive types
- and one that doesn't depend on a hardware device like cdaudio - and
code up a test and post it if it doesn't work.

That way I can debug it if its not working.

Levente Farkas

unread,
May 26, 2008, 10:16:14 AM5/26/08
to gstream...@googlegroups.com
hi,
we checkout your laast changes from the repo and with the last changes already the native is working.
thanks.
Reply all
Reply to author
Forward
0 new messages