diff --git a/element.go b/element.go index a5ea2f1..f9a20b8 100644 --- a/element.go +++ b/element.go @@ -3,26 +3,18 @@ package gst /* #cgo pkg-config: gstreamer-1.0 gstreamer-app-1.0 #include "gst.h" +typedef void (*closure)(); */ import "C" import ( "errors" "fmt" - "math/rand" "reflect" "runtime" - "sync" "unsafe" ) -var ( - mutex sync.Mutex - callbackStore = map[uint64]*Element{} -) - -type PadAddedCallback func(element *Element, pad *Pad) - type StateOptions int const ( @@ -34,9 +26,10 @@ const ( ) type Element struct { - GstElement *C.GstElement - onPadAdded PadAddedCallback - callbackID uint64 + GstElement *C.GstElement + callbackFunc interface{} + // Do not change the order of the above two elements + // It matches ElementUserData in gst.h on purpose } func (e *Element) Name() (name string) { @@ -235,63 +228,27 @@ func (e *Element) SetObject(name string, value interface{}) { } } -func (e *Element) cleanCallback() { - - if e.onPadAdded == nil { - return - } - - mutex.Lock() - defer mutex.Unlock() - - delete(callbackStore, e.callbackID) -} - -//export go_callback_new_pad -func go_callback_new_pad(CgstElement *C.GstElement, CgstPad *C.GstPad, callbackID C.guint64) { - - mutex.Lock() - element := callbackStore[uint64(callbackID)] - mutex.Unlock() - - if element == nil { - return - } - - callback := element.onPadAdded - - pad := &Pad{ - pad: CgstPad, - } - - callback(element, pad) -} - -func (e *Element) SetPadAddedCallback(callback PadAddedCallback) { - e.onPadAdded = callback +func (e *Element) SetCallback(signal string, callback interface{}) { + e.callbackFunc = callback - var callbackID uint64 - mutex.Lock() - for { - callbackID = rand.Uint64() - if callbackStore[callbackID] != nil { - continue - } - callbackStore[callbackID] = e - break - } - mutex.Unlock() - - e.callbackID = callbackID - - detailedSignal := (*C.gchar)(C.CString("pad-added")) + detailedSignal := (*C.gchar)(C.CString(signal)) defer C.free(unsafe.Pointer(detailedSignal)) + flags := 0 // TODO: use GConnectFlags enum + notify := 0 // TODO: confirm null correctly used - runtime.SetFinalizer(e, func(e *Element) { - e.cleanCallback() - }) + user_data_e := &Element{ + callbackFunc: e.callbackFunc, + GstElement: e.GstElement, + } - C.X_g_signal_connect(e.GstElement, detailedSignal, C.guint64(callbackID)) + C.X_g_signal_connect_data( + (C.gpointer)(unsafe.Pointer(e.GstElement)), + detailedSignal, + C.closure(callback.(unsafe.Pointer)), + (C.gpointer)(unsafe.Pointer(user_data_e)), + C.closure(unsafe.Pointer(¬ify)), + (C.GConnectFlags)(flags), + ) } func ElementFactoryMake(factoryName string, name string) (e *Element, err error) { diff --git a/gst.c b/gst.c index 4e70dc1..4191205 100644 --- a/gst.c +++ b/gst.c @@ -65,25 +65,29 @@ void X_gst_g_object_setv(GObject *object, guint n_properties, const gchar *names //g_object_setv(object, n_properties, names, value); } - -void cb_new_pad(GstElement *element, GstPad *pad, gpointer data) { - ElementUserData *d = (ElementUserData *)data; - go_callback_new_pad(element, pad, d->callbackId); +void cb_func(GstElement *element, gpointer data, gpointer data2) { + ElementUserData *d; + if(data2){ + d= data2; + printf("[ GST ] cb_func invoking callback arity:3"); + ((void (*)(GstElement* element,gpointer v, gpointer v2))(d->callbackFunc))(element,data,data2); + }else { + d= data; + printf("[ GST ] cb_func invoking callback arity:2"); + ((void (*)(GstElement* element,gpointer v))(d->callbackFunc))(element,data); + } } - void X_g_signal_connect(GstElement* element, gchar* detailed_signal, guint64 callbackId) { printf("[ GST ] g_signal_connect called with signal %s\n", detailed_signal); - ElementUserData *d = calloc(1, sizeof(ElementUserData)); - d->callbackId = callbackId; - - g_signal_connect(element, detailed_signal, G_CALLBACK(cb_new_pad), d); + g_signal_connect(element, detailed_signal, G_CALLBACK(cb_func), d); } + void X_g_signal_connect_data(gpointer instance, const gchar *detailed_signal, void (*f)(GstElement*, GstBus*, GstMessage*, gpointer), gpointer data, GClosureNotify destroy_data, GConnectFlags connect_flags) { printf("[ GST ] g_signal_connect_data called\n"); - g_signal_connect_data(instance, detailed_signal, G_CALLBACK(f), data, destroy_data, connect_flags); + g_signal_connect_data(instance, detailed_signal, G_CALLBACK(cb_func), data, destroy_data, connect_flags); } GstElement *X_gst_bin_get_by_name(GstElement* element, const gchar* name) { diff --git a/gst.h b/gst.h index 074c05d..c13c241 100644 --- a/gst.h +++ b/gst.h @@ -8,13 +8,14 @@ typedef struct ElementUserData { - guint64 callbackId; + GstElement *GstElement; + gpointer interfaceItable; + gpointer callbackFunc; } ElementUserData; -extern void go_callback_new_pad(GstElement *element,GstPad *pad, guint64 callbackId); extern void X_gst_shim_init(); @@ -29,7 +30,6 @@ extern void X_gst_g_object_set(GstElement* e, const gchar* p_name, const GValue* extern void X_gst_g_object_set_structure(GstElement *e, const gchar* p_name, const GstStructure *p_value); extern void X_gst_g_object_setv(GObject* object, guint n_properties, const gchar* names[], const GValue value[]); extern void X_g_signal_connect(GstElement* element, gchar* detailed_signal, guint64 callbackId); -extern void cb_new_pad(GstElement* element, GstPad* pad, gpointer data); extern gboolean cb_pad_event(GstPad *pad, GstObject *parent, GstEvent *event); extern GstElement *X_gst_bin_get_by_name(GstElement* element, const gchar* name); extern GstElementClass *X_GST_ELEMENT_GET_CLASS(GstElement *element);