Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Arbitrary callbacks #6

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 22 additions & 65 deletions element.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
Expand All @@ -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) {
Expand Down Expand Up @@ -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(&notify)),
(C.GConnectFlags)(flags),
)
}

func ElementFactoryMake(factoryName string, name string) (e *Element, err error) {
Expand Down
24 changes: 14 additions & 10 deletions gst.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
6 changes: 3 additions & 3 deletions gst.h
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -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);
Expand Down