--
Levente
"The only thing worse than not knowing the truth is
ruining the bliss of ignorance."
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.
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).
> 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.
2008/5/16 Farkas Levente <lfa...@gmail.com>:
You can probably stop the error by declaring the first argument to the
> Java side:
>
> Iterface:
>
> interface MyCallback extends org.gstreamer.lowlevel.GstAPI.GstCallback {
> public void callback(GObject source, int data);
> }
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);
Hmm. Interesting. How many people do you think are going to be
> 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).
writing plugins in C and using them from java?
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>:
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);
-------------------------------
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>:
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.