mirror of
https://github.com/go-gst/go-gst.git
synced 2025-10-04 23:52:55 +08:00
pull in upstream interface improvements and add a few more gstreamer interfaces
This commit is contained in:
@@ -36,6 +36,7 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/tinyzimmer/go-glib/glib"
|
||||
"github.com/tinyzimmer/go-gst/gst"
|
||||
)
|
||||
|
||||
@@ -51,7 +52,7 @@ func main() {
|
||||
|
||||
// Create a main loop. This is only required when utilizing signals via the bindings.
|
||||
// In this example, the AddWatch on the pipeline bus requires iterating on the main loop.
|
||||
mainLoop := gst.NewMainLoop(gst.DefaultMainContext(), false)
|
||||
mainLoop := glib.NewMainLoop(glib.MainContextDefault(), false)
|
||||
defer mainLoop.Unref()
|
||||
|
||||
// Build a pipeline string from the cli arguments
|
||||
|
@@ -47,7 +47,7 @@ type pluginConfig struct {
|
||||
}
|
||||
|
||||
type elementConfig struct {
|
||||
Name, Rank, Impl, Subclass string
|
||||
Name, Rank, Impl, Subclass, Interfaces string
|
||||
}
|
||||
|
||||
func buildCfgFromDir(dir string) *libraryConfig {
|
||||
@@ -119,6 +119,9 @@ var pluginTmpl = template.Must(template.New("").Funcs(template.FuncMap{
|
||||
"adjustedName": func(name string) string {
|
||||
return strings.ToLower(strings.Replace(name, "-", "_", -1))
|
||||
},
|
||||
"splitInterfaces": func(ifacesString string) []string {
|
||||
return strings.Split(ifacesString, ",")
|
||||
},
|
||||
"extendsFromBase": func(subclass string) bool {
|
||||
if strings.HasPrefix(subclass, "base.") {
|
||||
return true
|
||||
@@ -163,6 +166,12 @@ var pluginMeta = &gst.PluginMetadata{
|
||||
&{{ .Config.Element.Impl }}{},
|
||||
// The base subclass this element extends
|
||||
{{ .Config.Element.Subclass }},
|
||||
{{- if .Config.Element.Interfaces }}
|
||||
// The interfaces this element implements
|
||||
{{- range $index, $interface := .Config.Element.Interfaces | splitInterfaces }}
|
||||
{{ $interface }},
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
)
|
||||
},
|
||||
}
|
||||
|
@@ -60,7 +60,7 @@ func playbin(mainLoop *glib.MainLoop) error {
|
||||
// Watch state change events
|
||||
case gst.MessageStateChanged:
|
||||
if _, newState := msg.ParseStateChanged(); newState == gst.StatePlaying {
|
||||
bin := gst.BinFromElement(playbin)
|
||||
bin := gst.ToGstBin(playbin)
|
||||
// Generate a dot graph of the pipeline to GST_DEBUG_DUMP_DOT_DIR if defined
|
||||
bin.DebugBinToDotFile(gst.DebugGraphShowAll, "PLAYING")
|
||||
}
|
||||
|
27
examples/plugins/boilerplate/boilerplate.go
Normal file
27
examples/plugins/boilerplate/boilerplate.go
Normal file
@@ -0,0 +1,27 @@
|
||||
//go:generate gst-plugin-gen
|
||||
//
|
||||
// +plugin:Name=boilerplate
|
||||
// +plugin:Description=My plugin written in go
|
||||
// +plugin:Version=v0.0.1
|
||||
// +plugin:License=gst.LicenseLGPL
|
||||
// +plugin:Source=go-gst
|
||||
// +plugin:Package=examples
|
||||
// +plugin:Origin=https://github.com/tinyzimmer/go-gst
|
||||
// +plugin:ReleaseDate=2021-01-18
|
||||
//
|
||||
// +element:Name=myelement
|
||||
// +element:Rank=gst.RankNone
|
||||
// +element:Impl=myelement
|
||||
// +element:Subclass=gst.ExtendsElement
|
||||
//
|
||||
package main
|
||||
|
||||
import "github.com/tinyzimmer/go-glib/glib"
|
||||
|
||||
func main() {}
|
||||
|
||||
type myelement struct{}
|
||||
|
||||
func (g *myelement) New() glib.GoObjectSubclass { return &myelement{} }
|
||||
|
||||
func (g *myelement) ClassInit(klass *glib.ObjectClass) {}
|
27
examples/plugins/gobin/gobin.go
Normal file
27
examples/plugins/gobin/gobin.go
Normal file
@@ -0,0 +1,27 @@
|
||||
//go:generate gst-plugin-gen
|
||||
//
|
||||
// +plugin:Name=gobin
|
||||
// +plugin:Description=A bin element written in go
|
||||
// +plugin:Version=v0.0.1
|
||||
// +plugin:License=gst.LicenseLGPL
|
||||
// +plugin:Source=go-gst
|
||||
// +plugin:Package=examples
|
||||
// +plugin:Origin=https://github.com/tinyzimmer/go-gst
|
||||
// +plugin:ReleaseDate=2021-01-18
|
||||
//
|
||||
// +element:Name=gobin
|
||||
// +element:Rank=gst.RankNone
|
||||
// +element:Impl=gobin
|
||||
// +element:Subclass=gst.ExtendsBin
|
||||
//
|
||||
package main
|
||||
|
||||
import "github.com/tinyzimmer/go-glib/glib"
|
||||
|
||||
func main() {}
|
||||
|
||||
type gobin struct{}
|
||||
|
||||
func (g *gobin) New() glib.GoObjectSubclass { return &gobin{} }
|
||||
|
||||
func (g *gobin) ClassInit(klass *glib.ObjectClass) {}
|
@@ -29,6 +29,8 @@
|
||||
// +element:Rank=gst.RankNone
|
||||
// +element:Impl=fileSink
|
||||
// +element:Subclass=base.ExtendsBaseSink
|
||||
// +element:Interfaces=gst.InterfaceURIHandler
|
||||
//
|
||||
package main
|
||||
|
||||
import (
|
||||
@@ -119,13 +121,6 @@ func (f *fileSink) New() glib.GoObjectSubclass {
|
||||
}
|
||||
}
|
||||
|
||||
// The TypeInit method should register any additional interfaces provided by the element.
|
||||
// In this example we signal to the type system that we also implement the GstURIHandler interface.
|
||||
func (f *fileSink) TypeInit(instance *glib.TypeInstance) {
|
||||
CAT.Log(gst.LevelLog, "Adding URIHandler interface to type")
|
||||
instance.AddInterface(gst.InterfaceURIHandler)
|
||||
}
|
||||
|
||||
// The ClassInit method should specify the metadata for this element and add any pad templates
|
||||
// and properties.
|
||||
func (f *fileSink) ClassInit(klass *glib.ObjectClass) {
|
||||
|
@@ -29,6 +29,8 @@
|
||||
// +element:Rank=gst.RankNone
|
||||
// +element:Impl=fileSrc
|
||||
// +element:Subclass=base.ExtendsBaseSrc
|
||||
// +element:Interfaces=gst.InterfaceURIHandler
|
||||
//
|
||||
package main
|
||||
|
||||
import (
|
||||
@@ -123,13 +125,6 @@ func (f *fileSrc) New() glib.GoObjectSubclass {
|
||||
}
|
||||
}
|
||||
|
||||
// The TypeInit method should register any additional interfaces provided by the element.
|
||||
// In this example we signal to the type system that we also implement the GstURIHandler interface.
|
||||
func (f *fileSrc) TypeInit(instance *glib.TypeInstance) {
|
||||
CAT.Log(gst.LevelLog, "Adding URIHandler interface to type")
|
||||
instance.AddInterface(gst.InterfaceURIHandler)
|
||||
}
|
||||
|
||||
// The ClassInit method should specify the metadata for this element and add any pad templates
|
||||
// and properties.
|
||||
func (f *fileSrc) ClassInit(klass *glib.ObjectClass) {
|
||||
|
2
go.mod
2
go.mod
@@ -4,5 +4,5 @@ go 1.15
|
||||
|
||||
require (
|
||||
github.com/mattn/go-pointer v0.0.1
|
||||
github.com/tinyzimmer/go-glib v0.0.7
|
||||
github.com/tinyzimmer/go-glib v0.0.11
|
||||
)
|
||||
|
4
go.sum
4
go.sum
@@ -1,4 +1,4 @@
|
||||
github.com/mattn/go-pointer v0.0.1 h1:n+XhsuGeVO6MEAp7xyEukFINEa+Quek5psIR/ylA6o0=
|
||||
github.com/mattn/go-pointer v0.0.1/go.mod h1:2zXcozF6qYGgmsG+SeTZz3oAbFLdD3OWqnUbNvJZAlc=
|
||||
github.com/tinyzimmer/go-glib v0.0.7 h1:09SIbhaL+E+5U/4qbZXiM7f6HEDvcxOBuEiSCkT9FNw=
|
||||
github.com/tinyzimmer/go-glib v0.0.7/go.mod h1:zy2cs6eXSTtqqYrv9/UgYMDfr4pWKuYPSzwX87cBGX4=
|
||||
github.com/tinyzimmer/go-glib v0.0.11 h1:+X15JtyglmBhiLu5KXHWxcxhypyc/CEqW+SIFmjZ110=
|
||||
github.com/tinyzimmer/go-glib v0.0.11/go.mod h1:zy2cs6eXSTtqqYrv9/UgYMDfr4pWKuYPSzwX87cBGX4=
|
||||
|
@@ -19,12 +19,14 @@ inline GObjectClass * toGObjectClass (void *p) { return (G_
|
||||
|
||||
inline GstAllocator * toGstAllocator (void *p) { return (GST_ALLOCATOR_CAST(p)); }
|
||||
inline GstBin * toGstBin (void *p) { return (GST_BIN(p)); }
|
||||
inline GstBinClass * toGstBinClass (void *p) { return (GST_BIN_CLASS(p)); }
|
||||
inline GstBufferList * toGstBufferList (void *p) { return (GST_BUFFER_LIST(p)); }
|
||||
inline GstBufferPool * toGstBufferPool (void *p) { return (GST_BUFFER_POOL(p)); }
|
||||
inline GstBuffer * toGstBuffer (void *p) { return (GST_BUFFER(p)); }
|
||||
inline GstBus * toGstBus (void *p) { return (GST_BUS(p)); }
|
||||
inline GstCapsFeatures * toGstCapsFeatures (void *p) { return (GST_CAPS_FEATURES(p)); }
|
||||
inline GstCaps * toGstCaps (void *p) { return (GST_CAPS(p)); }
|
||||
inline GstChildProxy * toGstChildProxy (void *p) { return (GST_CHILD_PROXY(p)); }
|
||||
inline GstClock * toGstClock (void *p) { return (GST_CLOCK(p)); }
|
||||
inline GstContext * toGstContext (void *p) { return (GST_CONTEXT_CAST(p)); }
|
||||
inline GstDevice * toGstDevice (void *p) { return (GST_DEVICE_CAST(p)); }
|
||||
|
141
gst/gst_bin.go
141
gst/gst_bin.go
@@ -1,6 +1,73 @@
|
||||
package gst
|
||||
|
||||
// #include "gst.go.h"
|
||||
/*
|
||||
#include "gst.go.h"
|
||||
|
||||
gboolean
|
||||
binParentAddElement (GstBin * bin, GstElement * element)
|
||||
{
|
||||
GObjectClass * this_class = G_OBJECT_GET_CLASS(G_OBJECT(bin));
|
||||
GstBinClass * parent = toGstBinClass(g_type_class_peek_parent(this_class));
|
||||
return parent->add_element(bin, element);
|
||||
}
|
||||
|
||||
void
|
||||
binParentDeepElementAdded (GstBin * bin, GstBin * subbin, GstElement * element)
|
||||
{
|
||||
GObjectClass * this_class = G_OBJECT_GET_CLASS(G_OBJECT(bin));
|
||||
GstBinClass * parent = toGstBinClass(g_type_class_peek_parent(this_class));
|
||||
parent->deep_element_added(bin, subbin, element);
|
||||
}
|
||||
|
||||
void
|
||||
binParentDeepElementRemoved (GstBin * bin, GstBin * subbin, GstElement * element)
|
||||
{
|
||||
GObjectClass * this_class = G_OBJECT_GET_CLASS(G_OBJECT(element));
|
||||
GstBinClass * parent = toGstBinClass(g_type_class_peek_parent(this_class));
|
||||
parent->deep_element_removed(bin, subbin, element);
|
||||
}
|
||||
|
||||
gboolean
|
||||
binParentDoLatency (GstBin * bin)
|
||||
{
|
||||
GObjectClass * this_class = G_OBJECT_GET_CLASS(G_OBJECT(bin));
|
||||
GstBinClass * parent = toGstBinClass(g_type_class_peek_parent(this_class));
|
||||
return parent->do_latency(bin);
|
||||
}
|
||||
|
||||
void
|
||||
binParentElementAdded (GstBin * bin, GstElement * element)
|
||||
{
|
||||
GObjectClass * this_class = G_OBJECT_GET_CLASS(G_OBJECT(bin));
|
||||
GstBinClass * parent = toGstBinClass(g_type_class_peek_parent(this_class));
|
||||
parent->element_added(bin, element);
|
||||
}
|
||||
|
||||
void
|
||||
binParentElementRemoved (GstBin * bin, GstElement * element)
|
||||
{
|
||||
GObjectClass * this_class = G_OBJECT_GET_CLASS(G_OBJECT(bin));
|
||||
GstBinClass * parent = toGstBinClass(g_type_class_peek_parent(this_class));
|
||||
parent->element_removed(bin, element);
|
||||
}
|
||||
|
||||
void
|
||||
binParentHandleMessage (GstBin * bin, GstMessage * message)
|
||||
{
|
||||
GObjectClass * this_class = G_OBJECT_GET_CLASS(G_OBJECT(bin));
|
||||
GstBinClass * parent = toGstBinClass(g_type_class_peek_parent(this_class));
|
||||
parent->handle_message(bin, message);
|
||||
}
|
||||
|
||||
gboolean
|
||||
binParentRemoveElement (GstBin * bin, GstElement * element)
|
||||
{
|
||||
GObjectClass * this_class = G_OBJECT_GET_CLASS(G_OBJECT(bin));
|
||||
GstBinClass * parent = toGstBinClass(g_type_class_peek_parent(this_class));
|
||||
return parent->remove_element(bin, element);
|
||||
}
|
||||
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
@@ -22,14 +89,18 @@ func NewBin(name string) *Bin {
|
||||
return wrapBin(&glib.Object{GObject: glib.ToGObject(unsafe.Pointer(bin))})
|
||||
}
|
||||
|
||||
// BinFromElement wraps the given Element in a Bin reference. This only works for elements
|
||||
// that implement their own Bin, such as playbin. If the provided element does not implement
|
||||
// a Bin then nil is returned.
|
||||
func BinFromElement(elem *Element) *Bin {
|
||||
if C.toGstBin(elem.Unsafe()) == nil {
|
||||
return nil
|
||||
// ToGstBin wraps the given glib.Object, gst.Object, or gst.Element in a Bin instance. Only
|
||||
// works for objects that implement their own Bin.
|
||||
func ToGstBin(obj interface{}) *Bin {
|
||||
switch obj := obj.(type) {
|
||||
case *Object:
|
||||
return &Bin{&Element{Object: obj}}
|
||||
case *Element:
|
||||
return &Bin{obj}
|
||||
case *glib.Object:
|
||||
return &Bin{&Element{Object: &Object{InitiallyUnowned: &glib.InitiallyUnowned{Object: obj}}}}
|
||||
}
|
||||
return &Bin{elem}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Instance returns the underlying GstBin instance.
|
||||
@@ -95,10 +166,10 @@ func (b *Bin) GetElementsSorted() ([]*Element, error) {
|
||||
// element is found, it returns the element. You can cast this element to the given interface afterwards.
|
||||
// If you want all elements that implement the interface, use GetAllByInterface. This function recurses
|
||||
// into child bins.
|
||||
func (b *Bin) GetByInterface(iface glib.Type) (*Element, error) {
|
||||
elem := C.gst_bin_get_by_interface(b.Instance(), C.GType(iface))
|
||||
func (b *Bin) GetByInterface(iface glib.Interface) (*Element, error) {
|
||||
elem := C.gst_bin_get_by_interface(b.Instance(), C.GType(iface.Type()))
|
||||
if elem == nil {
|
||||
return nil, fmt.Errorf("Could not find any elements implementing %s", iface.Name())
|
||||
return nil, fmt.Errorf("Could not find any elements implementing %s", iface.Type().Name())
|
||||
}
|
||||
return wrapElement(toGObject(unsafe.Pointer(elem))), nil
|
||||
}
|
||||
@@ -106,8 +177,8 @@ func (b *Bin) GetByInterface(iface glib.Type) (*Element, error) {
|
||||
// GetAllByInterface looks for all elements inside the bin that implements the given interface. You can
|
||||
// safely cast all returned elements to the given interface. The function recurses inside child bins.
|
||||
// The function will return a series of Elements that should be unreffed after use.
|
||||
func (b *Bin) GetAllByInterface(iface glib.Type) ([]*Element, error) {
|
||||
iterator := C.gst_bin_iterate_all_by_interface(b.Instance(), C.GType(iface))
|
||||
func (b *Bin) GetAllByInterface(iface glib.Interface) ([]*Element, error) {
|
||||
iterator := C.gst_bin_iterate_all_by_interface(b.Instance(), C.GType(iface.Type()))
|
||||
return iteratorToElementSlice(iterator)
|
||||
}
|
||||
|
||||
@@ -123,7 +194,7 @@ func (b *Bin) GetAllByInterface(iface glib.Type) ([]*Element, error) {
|
||||
// Add adds an element to the bin.
|
||||
func (b *Bin) Add(elem *Element) error {
|
||||
if ok := C.gst_bin_add((*C.GstBin)(b.Instance()), (*C.GstElement)(elem.Instance())); !gobool(ok) {
|
||||
return fmt.Errorf("Failed to add element to pipeline: %s", elem.Name())
|
||||
return fmt.Errorf("Failed to add element to pipeline: %s", elem.GetName())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -141,7 +212,7 @@ func (b *Bin) AddMany(elems ...*Element) error {
|
||||
// Remove removes an element from the Bin.
|
||||
func (b *Bin) Remove(elem *Element) error {
|
||||
if ok := C.gst_bin_remove((*C.GstBin)(b.Instance()), (*C.GstElement)(elem.Instance())); !gobool(ok) {
|
||||
return fmt.Errorf("Failed to add element to pipeline: %s", elem.Name())
|
||||
return fmt.Errorf("Failed to add element to pipeline: %s", elem.GetName())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -257,3 +328,43 @@ func iteratorToElementSlice(iterator *C.GstIterator) ([]*Element, error) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ParentAddElement chains up to the parent AddElement handler.
|
||||
func (b *Bin) ParentAddElement(element *Element) bool {
|
||||
return gobool(C.binParentAddElement(b.Instance(), element.Instance()))
|
||||
}
|
||||
|
||||
// ParentDeepElementAdded chains up to the parent DeepElementAdded handler.
|
||||
func (b *Bin) ParentDeepElementAdded(subbin *Bin, element *Element) {
|
||||
C.binParentDeepElementAdded(b.Instance(), subbin.Instance(), element.Instance())
|
||||
}
|
||||
|
||||
// ParentDeepElementRemoved chains up to the parent DeepElementRemoved handler.
|
||||
func (b *Bin) ParentDeepElementRemoved(subbin *Bin, element *Element) {
|
||||
C.binParentDeepElementRemoved(b.Instance(), subbin.Instance(), element.Instance())
|
||||
}
|
||||
|
||||
// ParentDoLatency chains up to the parent DoLatency handler.
|
||||
func (b *Bin) ParentDoLatency() bool {
|
||||
return gobool(C.binParentDoLatency(b.Instance()))
|
||||
}
|
||||
|
||||
// ParentElementAdded chains up to the parent ElementAdded handler.
|
||||
func (b *Bin) ParentElementAdded(element *Element) {
|
||||
C.binParentElementAdded(b.Instance(), element.Instance())
|
||||
}
|
||||
|
||||
// ParentElementRemoved chains up to the parent ElementRemoved handler.
|
||||
func (b *Bin) ParentElementRemoved(element *Element) {
|
||||
C.binParentElementRemoved(b.Instance(), element.Instance())
|
||||
}
|
||||
|
||||
// ParentHandleMessage chains up to the parent HandleMessage handler.
|
||||
func (b *Bin) ParentHandleMessage(message *Message) {
|
||||
C.binParentHandleMessage(b.Instance(), message.Instance())
|
||||
}
|
||||
|
||||
// ParentRemoveElement chains up to the parent RemoveElement handler.
|
||||
func (b *Bin) ParentRemoveElement(element *Element) bool {
|
||||
return gobool(C.binParentRemoveElement(b.Instance(), element.Instance()))
|
||||
}
|
||||
|
91
gst/gst_bin_exports.go
Normal file
91
gst/gst_bin_exports.go
Normal file
@@ -0,0 +1,91 @@
|
||||
package gst
|
||||
|
||||
/*
|
||||
#include "gst.go.h"
|
||||
*/
|
||||
import "C"
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
"github.com/tinyzimmer/go-glib/glib"
|
||||
)
|
||||
|
||||
func cbWrapBin(bin *C.GstBin) *Bin {
|
||||
return wrapBin(&glib.Object{GObject: glib.ToGObject(unsafe.Pointer(bin))})
|
||||
}
|
||||
|
||||
func cbWrapElement(elem *C.GstElement) *Element {
|
||||
return wrapElement(&glib.Object{GObject: glib.ToGObject(unsafe.Pointer(elem))})
|
||||
}
|
||||
|
||||
//export goGstBinAddElement
|
||||
func goGstBinAddElement(bin *C.GstBin, element *C.GstElement) C.gboolean {
|
||||
elem := glib.FromObjectUnsafePrivate(unsafe.Pointer(bin))
|
||||
caller := elem.(interface {
|
||||
AddElement(self *Bin, element *Element) bool
|
||||
})
|
||||
return gboolean(caller.AddElement(cbWrapBin(bin), cbWrapElement(element)))
|
||||
}
|
||||
|
||||
//export goGstBinDeepElementAdded
|
||||
func goGstBinDeepElementAdded(bin *C.GstBin, subbin *C.GstBin, child *C.GstElement) {
|
||||
elem := glib.FromObjectUnsafePrivate(unsafe.Pointer(bin))
|
||||
caller := elem.(interface {
|
||||
DeepElementAdded(self *Bin, subbin *Bin, child *Element)
|
||||
})
|
||||
caller.DeepElementAdded(cbWrapBin(bin), cbWrapBin(subbin), cbWrapElement(child))
|
||||
}
|
||||
|
||||
//export goGstBinDeepElementRemoved
|
||||
func goGstBinDeepElementRemoved(bin *C.GstBin, subbin *C.GstBin, child *C.GstElement) {
|
||||
elem := glib.FromObjectUnsafePrivate(unsafe.Pointer(bin))
|
||||
caller := elem.(interface {
|
||||
DeepElementRemoved(self *Bin, subbin *Bin, child *Element)
|
||||
})
|
||||
caller.DeepElementRemoved(cbWrapBin(bin), cbWrapBin(subbin), cbWrapElement(child))
|
||||
}
|
||||
|
||||
//export goGstBinDoLatency
|
||||
func goGstBinDoLatency(bin *C.GstBin) C.gboolean {
|
||||
elem := glib.FromObjectUnsafePrivate(unsafe.Pointer(bin))
|
||||
caller := elem.(interface {
|
||||
DoLatency(self *Bin) bool
|
||||
})
|
||||
return gboolean(caller.DoLatency(cbWrapBin(bin)))
|
||||
}
|
||||
|
||||
//export goGstBinElementAdded
|
||||
func goGstBinElementAdded(bin *C.GstBin, child *C.GstElement) {
|
||||
elem := glib.FromObjectUnsafePrivate(unsafe.Pointer(bin))
|
||||
caller := elem.(interface {
|
||||
ElementAdded(self *Bin, child *Element)
|
||||
})
|
||||
caller.ElementAdded(cbWrapBin(bin), cbWrapElement(child))
|
||||
}
|
||||
|
||||
//export goGstBinElementRemoved
|
||||
func goGstBinElementRemoved(bin *C.GstBin, child *C.GstElement) {
|
||||
elem := glib.FromObjectUnsafePrivate(unsafe.Pointer(bin))
|
||||
caller := elem.(interface {
|
||||
ElementRemoved(self *Bin, child *Element)
|
||||
})
|
||||
caller.ElementRemoved(cbWrapBin(bin), cbWrapElement(child))
|
||||
}
|
||||
|
||||
//export goGstBinHandleMessage
|
||||
func goGstBinHandleMessage(bin *C.GstBin, message *C.GstMessage) {
|
||||
elem := glib.FromObjectUnsafePrivate(unsafe.Pointer(bin))
|
||||
caller := elem.(interface {
|
||||
HandleMessage(self *Bin, msg *Message)
|
||||
})
|
||||
caller.HandleMessage(cbWrapBin(bin), wrapMessage(message))
|
||||
}
|
||||
|
||||
//export goGstBinRemoveElement
|
||||
func goGstBinRemoveElement(bin *C.GstBin, element *C.GstElement) C.gboolean {
|
||||
elem := glib.FromObjectUnsafePrivate(unsafe.Pointer(bin))
|
||||
caller := elem.(interface {
|
||||
RemoveElement(self *Bin, element *Element) bool
|
||||
})
|
||||
return gboolean(caller.RemoveElement(cbWrapBin(bin), cbWrapElement(element)))
|
||||
}
|
106
gst/gst_bin_impl.go
Normal file
106
gst/gst_bin_impl.go
Normal file
@@ -0,0 +1,106 @@
|
||||
package gst
|
||||
|
||||
/*
|
||||
#include "gst.go.h"
|
||||
|
||||
extern gboolean goGstBinAddElement (GstBin * bin, GstElement * element);
|
||||
extern void goGstBinDeepElementAdded (GstBin * bin, GstBin * subbin, GstElement * child);
|
||||
extern void goGstBinDeepElementRemoved (GstBin * bin, GstBin * subbin, GstElement * child);
|
||||
extern gboolean goGstBinDoLatency (GstBin * bin);
|
||||
extern void goGstBinElementAdded (GstBin * bin, GstElement * child);
|
||||
extern void goGstBinElementRemoved (GstBin * bin, GstElement * child);
|
||||
extern void goGstBinHandleMessage (GstBin * bin, GstMessage * message);
|
||||
extern gboolean goGstBinRemoveElement (GstBin * bin, GstElement * element);
|
||||
|
||||
void setGstBinAddElement (GstBinClass * klass) { klass->add_element = goGstBinAddElement; };
|
||||
void setGstBinDeepElementAdded (GstBinClass * klass) { klass->deep_element_added = goGstBinDeepElementAdded; };
|
||||
void setGstBinDeepElementRemoved (GstBinClass * klass) { klass->deep_element_removed = goGstBinDeepElementRemoved; };
|
||||
void setGstBinDoLatency (GstBinClass * klass) { klass->do_latency = goGstBinDoLatency; };
|
||||
void setGstBinElementAdded (GstBinClass * klass) { klass->element_added = goGstBinElementAdded; };
|
||||
void setGstBinElementRemoved (GstBinClass * klass) { klass->element_removed = goGstBinElementRemoved; };
|
||||
void setGstBinHandleMessage (GstBinClass * klass) { klass->handle_message = goGstBinHandleMessage; };
|
||||
void setGstBinRemoveElement (GstBinClass * klass) { klass->remove_element = goGstBinRemoveElement; };
|
||||
|
||||
*/
|
||||
import "C"
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
"github.com/tinyzimmer/go-glib/glib"
|
||||
)
|
||||
|
||||
// ExtendsBin implements an Extendable object based on a GstBin.
|
||||
var ExtendsBin glib.Extendable = &extendsBin{parent: ExtendsElement}
|
||||
|
||||
// BinImpl is the reference interface for Go elements extending a Bin. You only need to
|
||||
// implement the methods that interest you.
|
||||
type BinImpl interface {
|
||||
AddElement(self *Bin, element *Element) bool
|
||||
DeepElementAdded(self *Bin, subbin *Bin, child *Element)
|
||||
DeepElementRemoved(self *Bin, subbin *Bin, child *Element)
|
||||
DoLatency(self *Bin) bool
|
||||
ElementAdded(self *Bin, child *Element)
|
||||
ElementRemoved(self *Bin, child *Element)
|
||||
HandleMessage(self *Bin, msg *Message)
|
||||
RemoveElement(self *Bin, element *Element) bool
|
||||
}
|
||||
|
||||
type extendsBin struct{ parent glib.Extendable }
|
||||
|
||||
func (e *extendsBin) Type() glib.Type { return glib.Type(C.gst_bin_get_type()) }
|
||||
func (e *extendsBin) ClassSize() int64 { return int64(C.sizeof_GstBinClass) }
|
||||
func (e *extendsBin) InstanceSize() int64 { return int64(C.sizeof_GstBin) }
|
||||
|
||||
func (e *extendsBin) InitClass(klass unsafe.Pointer, elem glib.GoObjectSubclass) {
|
||||
e.parent.InitClass(klass, elem)
|
||||
|
||||
class := C.toGstBinClass(klass)
|
||||
|
||||
if _, ok := elem.(interface {
|
||||
AddElement(self *Bin, element *Element) bool
|
||||
}); ok {
|
||||
C.setGstBinAddElement(class)
|
||||
}
|
||||
|
||||
if _, ok := elem.(interface {
|
||||
DeepElementAdded(self *Bin, subbin *Bin, child *Element)
|
||||
}); ok {
|
||||
C.setGstBinDeepElementAdded(class)
|
||||
}
|
||||
|
||||
if _, ok := elem.(interface {
|
||||
DeepElementRemoved(self *Bin, subbin *Bin, child *Element)
|
||||
}); ok {
|
||||
C.setGstBinDeepElementRemoved(class)
|
||||
}
|
||||
|
||||
if _, ok := elem.(interface {
|
||||
DoLatency(self *Bin) bool
|
||||
}); ok {
|
||||
C.setGstBinDoLatency(class)
|
||||
}
|
||||
|
||||
if _, ok := elem.(interface {
|
||||
ElementAdded(self *Bin, child *Element)
|
||||
}); ok {
|
||||
C.setGstBinElementAdded(class)
|
||||
}
|
||||
|
||||
if _, ok := elem.(interface {
|
||||
ElementRemoved(self *Bin, child *Element)
|
||||
}); ok {
|
||||
C.setGstBinElementRemoved(class)
|
||||
}
|
||||
|
||||
if _, ok := elem.(interface {
|
||||
HandleMessage(self *Bin, msg *Message)
|
||||
}); ok {
|
||||
C.setGstBinHandleMessage(class)
|
||||
}
|
||||
|
||||
if _, ok := elem.(interface {
|
||||
RemoveElement(self *Bin, element *Element) bool
|
||||
}); ok {
|
||||
C.setGstBinRemoveElement(class)
|
||||
}
|
||||
}
|
222
gst/gst_child_proxy.go
Normal file
222
gst/gst_child_proxy.go
Normal file
@@ -0,0 +1,222 @@
|
||||
package gst
|
||||
|
||||
/*
|
||||
#include "gst.go.h"
|
||||
|
||||
extern void goGstChildProxyChildAdded (GstChildProxy * parent, GObject * child, const gchar * name);
|
||||
extern void goGstChildProxyChildRemoved (GstChildProxy * parent, GObject * child, const gchar * name);
|
||||
extern GObject * goGstChildProxyGetChildByIndex (GstChildProxy * parent, guint idx);
|
||||
extern GObject * goGstChildProxyGetChildByName (GstChildProxy * parent, const gchar * name);
|
||||
extern guint goGstChildProxyGetChildrenCount (GstChildProxy * parent);
|
||||
|
||||
void setGstChildProxyChildAdded (gpointer iface) { ((GstChildProxyInterface*)iface)->child_added = goGstChildProxyChildAdded; }
|
||||
void setGstChildProxyChildRemoved (gpointer iface) { ((GstChildProxyInterface*)iface)->child_removed = goGstChildProxyChildRemoved; }
|
||||
void setGstChildProxyGetChildByIndex (gpointer iface) { ((GstChildProxyInterface*)iface)->get_child_by_index = goGstChildProxyGetChildByIndex; }
|
||||
void setGstChildProxyGetChildByName (gpointer iface) { ((GstChildProxyInterface*)iface)->get_child_by_name = goGstChildProxyGetChildByName; }
|
||||
void setGstChildProxyGetChildrenCount (gpointer iface) { ((GstChildProxyInterface*)iface)->get_children_count = goGstChildProxyGetChildrenCount; }
|
||||
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
"github.com/tinyzimmer/go-glib/glib"
|
||||
)
|
||||
|
||||
// InterfaceChildProxy represents the GstChildProxy interface. Use this when querying bins
|
||||
// for elements that implement GstChildProxy, or when signaling that a GoObjectSubclass
|
||||
// provides this interface.
|
||||
var InterfaceChildProxy glib.Interface = &interfaceChildProxy{}
|
||||
|
||||
type interfaceChildProxy struct{ glib.Interface }
|
||||
|
||||
func (i *interfaceChildProxy) Type() glib.Type { return glib.Type(C.GST_TYPE_CHILD_PROXY) }
|
||||
func (i *interfaceChildProxy) InitFunc() glib.InterfaceInitFunc {
|
||||
return func(instance *glib.TypeInstance) {
|
||||
goobj := instance.GoType
|
||||
|
||||
if _, ok := goobj.(interface {
|
||||
ChildAdded(self *ChildProxy, child *glib.Object, name string)
|
||||
}); ok {
|
||||
C.setGstChildProxyChildAdded((C.gpointer)(instance.GTypeInstance))
|
||||
}
|
||||
|
||||
if _, ok := goobj.(interface {
|
||||
ChildRemoved(self *ChildProxy, child *glib.Object, name string)
|
||||
}); ok {
|
||||
C.setGstChildProxyChildRemoved((C.gpointer)(instance.GTypeInstance))
|
||||
}
|
||||
|
||||
if _, ok := goobj.(interface {
|
||||
GetChildByIndex(self *ChildProxy, idx uint) *glib.Object
|
||||
}); ok {
|
||||
C.setGstChildProxyGetChildByIndex((C.gpointer)(instance.GTypeInstance))
|
||||
}
|
||||
|
||||
if _, ok := goobj.(interface {
|
||||
GetChildByName(self *ChildProxy, name string) *glib.Object
|
||||
}); ok {
|
||||
C.setGstChildProxyGetChildByName((C.gpointer)(instance.GTypeInstance))
|
||||
}
|
||||
|
||||
if _, ok := goobj.(interface {
|
||||
GetChildrenCount(self *ChildProxy) uint
|
||||
}); ok {
|
||||
C.setGstChildProxyGetChildrenCount((C.gpointer)(instance.GTypeInstance))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ChildProxyImpl is the reference implementation for a ChildProxy implemented by a Go object.
|
||||
type ChildProxyImpl interface {
|
||||
ChildAdded(self *ChildProxy, child *glib.Object, name string)
|
||||
ChildRemoved(self *ChildProxy, child *glib.Object, name string)
|
||||
GetChildByIndex(self *ChildProxy, idx uint) *glib.Object
|
||||
GetChildByName(self *ChildProxy, name string) *glib.Object
|
||||
GetChildrenCount(self *ChildProxy) uint
|
||||
}
|
||||
|
||||
// ChildProxy is an interface that abstracts handling of property sets for
|
||||
// elements with children. They all have multiple GstPad or some kind of voice
|
||||
// objects. Another use case are container elements like GstBin. The element
|
||||
// implementing the interface acts as a parent for those child objects.
|
||||
//
|
||||
// Property names are written as "child-name::property-name". The whole naming
|
||||
// scheme is recursive. Thus "child1::child2::property" is valid too, if "child1"
|
||||
// and "child2" implement the GstChildProxy interface.
|
||||
type ChildProxy struct{ ptr *C.GstChildProxy }
|
||||
|
||||
// ToChildProxy returns a ChildProxy for the given element. If the element does not implement
|
||||
// a ChildProxy it returns nil.
|
||||
func ToChildProxy(elem *Element) *ChildProxy {
|
||||
if proxy := C.toGstChildProxy(elem.Unsafe()); proxy != nil {
|
||||
return &ChildProxy{proxy}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Instance returns the underlying GstChildProxy instance.
|
||||
func (c *ChildProxy) Instance() *C.GstChildProxy {
|
||||
return C.toGstChildProxy(unsafe.Pointer(c.ptr))
|
||||
}
|
||||
|
||||
// ChildAdded emits the "child-added" signal.
|
||||
func (c *ChildProxy) ChildAdded(child *glib.Object, name string) {
|
||||
cname := C.CString(name)
|
||||
defer C.free(unsafe.Pointer(cname))
|
||||
C.gst_child_proxy_child_added(
|
||||
c.Instance(),
|
||||
(*C.GObject)(child.Unsafe()),
|
||||
(*C.gchar)(unsafe.Pointer(cname)),
|
||||
)
|
||||
}
|
||||
|
||||
// ChildRemoved emits the "child-removed" signal.
|
||||
func (c *ChildProxy) ChildRemoved(child *glib.Object, name string) {
|
||||
cname := C.CString(name)
|
||||
defer C.free(unsafe.Pointer(cname))
|
||||
C.gst_child_proxy_child_removed(
|
||||
c.Instance(),
|
||||
(*C.GObject)(child.Unsafe()),
|
||||
(*C.gchar)(unsafe.Pointer(cname)),
|
||||
)
|
||||
}
|
||||
|
||||
// Get gets properties of the parent object and its children. This is a direct alias to looping
|
||||
// over GetProperty and returning the results in the order of the arguments. If any of the results
|
||||
// returns nil from an allocation error, nil is returned for the entire slice.
|
||||
func (c *ChildProxy) Get(names ...string) []*glib.Value {
|
||||
out := make([]*glib.Value, len(names))
|
||||
for i, name := range names {
|
||||
val := c.GetProperty(name)
|
||||
if val == nil {
|
||||
return nil
|
||||
}
|
||||
out[i] = val
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// GetChildByIndex fetches a child by its number. This function can return nil if the object is not
|
||||
// found. Unref after usage.
|
||||
func (c *ChildProxy) GetChildByIndex(idx uint) *glib.Object {
|
||||
gobj := C.gst_child_proxy_get_child_by_index(c.Instance(), C.guint(idx))
|
||||
if gobj == nil {
|
||||
return nil
|
||||
}
|
||||
return &glib.Object{GObject: glib.ToGObject(unsafe.Pointer(gobj))}
|
||||
}
|
||||
|
||||
// GetChildByName fetches a child by name. The virtual method's default implementation uses Object
|
||||
// together with Object.GetName. If the interface is to be used with GObjects, this method needs
|
||||
// to be overridden.
|
||||
//
|
||||
// This function can return nil if the object is not found. Unref after usage.
|
||||
func (c *ChildProxy) GetChildByName(name string) *glib.Object {
|
||||
cname := C.CString(name)
|
||||
defer C.free(unsafe.Pointer(cname))
|
||||
gobj := C.gst_child_proxy_get_child_by_name(c.Instance(), (*C.gchar)(unsafe.Pointer(cname)))
|
||||
if gobj == nil {
|
||||
return nil
|
||||
}
|
||||
return &glib.Object{GObject: glib.ToGObject(unsafe.Pointer(gobj))}
|
||||
}
|
||||
|
||||
// GetChildrenCount returns the number of child objects the parent contains.
|
||||
func (c *ChildProxy) GetChildrenCount() uint {
|
||||
return uint(C.gst_child_proxy_get_children_count(c.Instance()))
|
||||
}
|
||||
|
||||
// GetProperty gets a single property using the ChildProxy mechanism. The bindings
|
||||
// take care of freeing the value when it leaves the user's scope. This function
|
||||
// can return nil if a failure happens trying to allocate GValues.
|
||||
func (c *ChildProxy) GetProperty(name string) *glib.Value {
|
||||
value, err := glib.ValueAlloc()
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
cname := C.CString(name)
|
||||
defer C.free(unsafe.Pointer(cname))
|
||||
C.gst_child_proxy_get_property(c.Instance(), (*C.gchar)(unsafe.Pointer(cname)), (*C.GValue)(unsafe.Pointer(value.GValue)))
|
||||
return value
|
||||
}
|
||||
|
||||
// Lookup looks up which object and and parameter would be affected by the given name.
|
||||
// If ok is false, the targets could not be found and this function returned nil.
|
||||
// Unref target after usage.
|
||||
func (c *ChildProxy) Lookup(name string) (ok bool, target *glib.Object, param *glib.ParamSpec) {
|
||||
var gtarget *C.GObject
|
||||
var gspec *C.GParamSpec
|
||||
cname := C.CString(name)
|
||||
defer C.free(unsafe.Pointer(cname))
|
||||
ok = gobool(C.gst_child_proxy_lookup(
|
||||
c.Instance(),
|
||||
(*C.gchar)(unsafe.Pointer(cname)),
|
||||
>arget, &gspec,
|
||||
))
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
target = &glib.Object{GObject: glib.ToGObject(unsafe.Pointer(gtarget))}
|
||||
param = glib.ToParamSpec(unsafe.Pointer(gspec))
|
||||
return
|
||||
}
|
||||
|
||||
// Set takes a map of names to values and applies them using the ChildProxy mechanism.
|
||||
func (c *ChildProxy) Set(values map[string]*glib.Value) {
|
||||
for name, value := range values {
|
||||
c.SetProperty(name, value)
|
||||
}
|
||||
}
|
||||
|
||||
// SetProperty sets a single property using the ChildProxy mechanism.
|
||||
func (c *ChildProxy) SetProperty(name string, value *glib.Value) {
|
||||
cname := C.CString(name)
|
||||
defer C.free(unsafe.Pointer(cname))
|
||||
C.gst_child_proxy_set_property(
|
||||
c.Instance(),
|
||||
(*C.gchar)(unsafe.Pointer(cname)),
|
||||
(*C.GValue)(unsafe.Pointer(value.GValue)),
|
||||
)
|
||||
}
|
74
gst/gst_child_proxy_exports.go
Normal file
74
gst/gst_child_proxy_exports.go
Normal file
@@ -0,0 +1,74 @@
|
||||
package gst
|
||||
|
||||
/*
|
||||
#include "gst.go.h"
|
||||
*/
|
||||
import "C"
|
||||
import (
|
||||
"unsafe"
|
||||
|
||||
"github.com/tinyzimmer/go-glib/glib"
|
||||
)
|
||||
|
||||
func wrapParent(parent *C.GstChildProxy) *ChildProxy { return &ChildProxy{ptr: parent} }
|
||||
|
||||
//export goGstChildProxyChildAdded
|
||||
func goGstChildProxyChildAdded(parent *C.GstChildProxy, child *C.GObject, name *C.gchar) {
|
||||
iface := glib.FromObjectUnsafePrivate(unsafe.Pointer(parent))
|
||||
caller := iface.(interface {
|
||||
ChildAdded(self *ChildProxy, child *glib.Object, name string)
|
||||
})
|
||||
caller.ChildAdded(
|
||||
wrapParent(parent),
|
||||
&glib.Object{GObject: glib.ToGObject(unsafe.Pointer(child))},
|
||||
C.GoString(name),
|
||||
)
|
||||
}
|
||||
|
||||
//export goGstChildProxyChildRemoved
|
||||
func goGstChildProxyChildRemoved(parent *C.GstChildProxy, child *C.GObject, name *C.gchar) {
|
||||
iface := glib.FromObjectUnsafePrivate(unsafe.Pointer(parent))
|
||||
caller := iface.(interface {
|
||||
ChildRemoved(self *ChildProxy, child *glib.Object, name string)
|
||||
})
|
||||
caller.ChildRemoved(
|
||||
wrapParent(parent),
|
||||
&glib.Object{GObject: glib.ToGObject(unsafe.Pointer(child))},
|
||||
C.GoString(name),
|
||||
)
|
||||
}
|
||||
|
||||
//export goGstChildProxyGetChildByIndex
|
||||
func goGstChildProxyGetChildByIndex(parent *C.GstChildProxy, idx C.guint) *C.GObject {
|
||||
iface := glib.FromObjectUnsafePrivate(unsafe.Pointer(parent))
|
||||
caller := iface.(interface {
|
||||
GetChildByIndex(self *ChildProxy, idx uint) *glib.Object
|
||||
})
|
||||
obj := caller.GetChildByIndex(wrapParent(parent), uint(idx))
|
||||
if obj == nil {
|
||||
return nil
|
||||
}
|
||||
return (*C.GObject)(unsafe.Pointer(obj.GObject))
|
||||
}
|
||||
|
||||
//export goGstChildProxyGetChildByName
|
||||
func goGstChildProxyGetChildByName(parent *C.GstChildProxy, name *C.gchar) *C.GObject {
|
||||
iface := glib.FromObjectUnsafePrivate(unsafe.Pointer(parent))
|
||||
caller := iface.(interface {
|
||||
GetChildByName(self *ChildProxy, name string) *glib.Object
|
||||
})
|
||||
obj := caller.GetChildByName(wrapParent(parent), C.GoString(name))
|
||||
if obj == nil {
|
||||
return nil
|
||||
}
|
||||
return (*C.GObject)(unsafe.Pointer(obj.GObject))
|
||||
}
|
||||
|
||||
//export goGstChildProxyGetChildrenCount
|
||||
func goGstChildProxyGetChildrenCount(parent *C.GstChildProxy) C.guint {
|
||||
iface := glib.FromObjectUnsafePrivate(unsafe.Pointer(parent))
|
||||
caller := iface.(interface {
|
||||
GetChildrenCount(self *ChildProxy) uint
|
||||
})
|
||||
return C.guint(caller.GetChildrenCount(wrapParent(parent)))
|
||||
}
|
@@ -70,7 +70,7 @@ func (d *Device) HasClasses(classes []string) bool {
|
||||
// while in the PLAYING state.
|
||||
func (d *Device) ReconfigureElement(elem *Element) error {
|
||||
if ok := gobool(C.gst_device_reconfigure_element(d.Instance(), elem.Instance())); !ok {
|
||||
return fmt.Errorf("Failed to reconfigure element %s", elem.Name())
|
||||
return fmt.Errorf("Failed to reconfigure element %s", elem.GetName())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@@ -29,40 +29,6 @@ GstStateChangeReturn elementParentChangeState (GstElement * element, GstStateCha
|
||||
return parent->change_state(element, transition);
|
||||
}
|
||||
|
||||
extern GstStateChangeReturn goGstElementClassChangeState (GstElement * element, GstStateChange change);
|
||||
extern GstStateChangeReturn goGstElementClassGetState (GstElement * element, GstState * state, GstState * pending, GstClockTime timeout);
|
||||
extern void goGstElementClassNoMorePads (GstElement * element);
|
||||
extern void goGstElementClassPadAdded (GstElement * element, GstPad * pad);
|
||||
extern void goGstElementClassPadRemoved (GstElement * element, GstPad * pad);
|
||||
extern gboolean goGstElementClassPostMessage (GstElement * element, GstMessage * msg);
|
||||
extern GstClock * goGstElementClassProvideClock (GstElement * element);
|
||||
extern gboolean goGstElementClassQuery (GstElement * element, GstQuery * query);
|
||||
extern void goGstElementClassReleasePad (GstElement * element, GstPad * pad);
|
||||
extern GstPad * goGstElementClassRequestNewPad (GstElement * element, GstPadTemplate * templ, const gchar * name, const GstCaps * caps);
|
||||
extern gboolean goGstElementClassSendEvent (GstElement * element, GstEvent * event);
|
||||
extern void goGstElementClassSetBus (GstElement * element, GstBus * bus);
|
||||
extern gboolean goGstElementClassSetClock (GstElement * element, GstClock * clock);
|
||||
extern void goGstElementClassSetContext (GstElement * element, GstContext * ctx);
|
||||
extern GstStateChangeReturn goGstElementClassSetState (GstElement * element, GstState state);
|
||||
extern void goGstElementClassStateChanged (GstElement * element, GstState old, GstState new, GstState pending);
|
||||
|
||||
void setGstElementClassChangeState (GstElementClass * klass) { klass->change_state = goGstElementClassChangeState; }
|
||||
void setGstElementClassGetState (GstElementClass * klass) { klass->get_state = goGstElementClassGetState; }
|
||||
void setGstElementClassNoMorePads (GstElementClass * klass) { klass->no_more_pads = goGstElementClassNoMorePads; }
|
||||
void setGstElementClassPadAdded (GstElementClass * klass) { klass->pad_added = goGstElementClassPadAdded; }
|
||||
void setGstElementClassPadRemoved (GstElementClass * klass) { klass->pad_removed = goGstElementClassPadRemoved; }
|
||||
void setGstElementClassPostMessage (GstElementClass * klass) { klass->post_message = goGstElementClassPostMessage; }
|
||||
void setGstElementClassProvideClock (GstElementClass * klass) { klass->provide_clock = goGstElementClassProvideClock; }
|
||||
void setGstElementClassQuery (GstElementClass * klass) { klass->query = goGstElementClassQuery; }
|
||||
void setGstElementClassReleasePad (GstElementClass * klass) { klass->release_pad = goGstElementClassReleasePad; }
|
||||
void setGstElementClassRequestNewPad (GstElementClass * klass) { klass->request_new_pad = goGstElementClassRequestNewPad; }
|
||||
void setGstElementClassSendEvent (GstElementClass * klass) { klass->send_event = goGstElementClassSendEvent; }
|
||||
void setGstElementClassSetBus (GstElementClass * klass) { klass->set_bus = goGstElementClassSetBus; }
|
||||
void setGstElementClassSetClock (GstElementClass * klass) { klass->set_clock = goGstElementClassSetClock; }
|
||||
void setGstElementClassSetContext (GstElementClass * klass) { klass->set_context = goGstElementClassSetContext; }
|
||||
void setGstElementClassSetState (GstElementClass * klass) { klass->set_state = goGstElementClassSetState; }
|
||||
void setGstElementClassStateChanged (GstElementClass * klass) { klass->state_changed = goGstElementClassStateChanged; }
|
||||
|
||||
*/
|
||||
import "C"
|
||||
|
||||
@@ -70,7 +36,6 @@ import (
|
||||
"fmt"
|
||||
"path"
|
||||
"runtime"
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
gopointer "github.com/mattn/go-pointer"
|
||||
@@ -117,12 +82,12 @@ const (
|
||||
|
||||
// RegisterElement creates a new elementfactory capable of instantiating objects of the given GoElement
|
||||
// and adds the factory to the plugin. A higher rank means more importance when autoplugging.
|
||||
func RegisterElement(plugin *Plugin, name string, rank Rank, elem glib.GoObjectSubclass, extends glib.Extendable) bool {
|
||||
func RegisterElement(plugin *Plugin, name string, rank Rank, elem glib.GoObjectSubclass, extends glib.Extendable, interfaces ...glib.Interface) bool {
|
||||
return gobool(C.gst_element_register(
|
||||
plugin.Instance(),
|
||||
C.CString(name),
|
||||
C.guint(rank),
|
||||
C.GType(glib.RegisterGoType(name, elem, extends)),
|
||||
C.GType(glib.RegisterGoType(name, elem, extends, interfaces...)),
|
||||
))
|
||||
}
|
||||
|
||||
@@ -340,7 +305,7 @@ func (e *Element) IsURIHandler() bool {
|
||||
// Link wraps gst_element_link and links this element to the given one.
|
||||
func (e *Element) Link(elem *Element) error {
|
||||
if ok := C.gst_element_link((*C.GstElement)(e.Instance()), (*C.GstElement)(elem.Instance())); !gobool(ok) {
|
||||
return fmt.Errorf("Failed to link %s to %s", e.Name(), elem.Name())
|
||||
return fmt.Errorf("Failed to link %s to %s", e.GetName(), elem.GetName())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -349,7 +314,7 @@ func (e *Element) Link(elem *Element) error {
|
||||
// using the provided sink caps.
|
||||
func (e *Element) LinkFiltered(elem *Element, caps *Caps) error {
|
||||
if ok := C.gst_element_link_filtered((*C.GstElement)(e.Instance()), (*C.GstElement)(elem.Instance()), (*C.GstCaps)(caps.Instance())); !gobool(ok) {
|
||||
return fmt.Errorf("Failed to link %s to %s with provider caps", e.Name(), elem.Name())
|
||||
return fmt.Errorf("Failed to link %s to %s with provided caps", e.GetName(), elem.GetName())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -459,152 +424,3 @@ func (e *Element) URIHandler() URIHandler {
|
||||
}
|
||||
return &gstURIHandler{ptr: e.Instance()}
|
||||
}
|
||||
|
||||
// ExtendsElement signifies a GoElement that extends a GstElement.
|
||||
var ExtendsElement glib.Extendable = &extendElement{parent: glib.ExtendsObject}
|
||||
|
||||
// ElementImpl is an interface containing go quivalents of the virtual methods that can be
|
||||
// overridden by a plugin extending an Element.
|
||||
type ElementImpl interface {
|
||||
// ChangeState is called by SetState to perform an incremental state change.
|
||||
ChangeState(*Element, StateChange) StateChangeReturn
|
||||
// GetState should return the states of the element
|
||||
GetState(self *Element, timeout time.Duration) (ret StateChangeReturn, current, pending State)
|
||||
// NoMorePads is called when there are no more pads on the element.
|
||||
NoMorePads(*Element)
|
||||
// PadAdded is called to add a pad to the element.
|
||||
PadAdded(*Element, *Pad)
|
||||
// PadRemoved is called to remove a pad from the element.
|
||||
PadRemoved(*Element, *Pad)
|
||||
// PostMessage is called when a message is posted to the element. Call Element.ParentPostMessage
|
||||
// to have it posted on the bus after processing.
|
||||
PostMessage(*Element, *Message) bool
|
||||
// ProvideClock is called to retrieve the clock provided by the element.
|
||||
ProvideClock(*Element) *Clock
|
||||
// Query is called to perform a query on the element.
|
||||
Query(*Element, *Query) bool
|
||||
// ReleasePad is called when a request pad is to be released.
|
||||
ReleasePad(*Element, *Pad)
|
||||
// RequestNewPad is called when a new pad is requested from the element.
|
||||
RequestNewPad(self *Element, templ *PadTemplate, name string, caps *Caps) *Pad
|
||||
// SendEvent is called to send an event to the element.
|
||||
SendEvent(*Element, *Event) bool
|
||||
// SetBus is called to set the Bus on the element.
|
||||
SetBus(*Element, *Bus)
|
||||
// SetClock is called to set the clock on the element.
|
||||
SetClock(*Element, *Clock) bool
|
||||
// SetContext is called to set the Context on the element.
|
||||
SetContext(*Element, *Context)
|
||||
// SetState is called to set a new state on the element.
|
||||
SetState(*Element, State) StateChangeReturn
|
||||
// StateChanged is called immediately after a new state was set.
|
||||
StateChanged(self *Element, old, new, pending State)
|
||||
}
|
||||
|
||||
type extendElement struct{ parent glib.Extendable }
|
||||
|
||||
func (e *extendElement) Type() glib.Type { return glib.Type(C.gst_element_get_type()) }
|
||||
func (e *extendElement) ClassSize() int64 { return int64(C.sizeof_GstElementClass) }
|
||||
func (e *extendElement) InstanceSize() int64 { return int64(C.sizeof_GstElement) }
|
||||
|
||||
func (e *extendElement) InitClass(klass unsafe.Pointer, elem glib.GoObjectSubclass) {
|
||||
e.parent.InitClass(klass, elem)
|
||||
|
||||
elemClass := C.toGstElementClass(klass)
|
||||
|
||||
if _, ok := elem.(interface {
|
||||
ChangeState(*Element, StateChange) StateChangeReturn
|
||||
}); ok {
|
||||
C.setGstElementClassChangeState(elemClass)
|
||||
}
|
||||
|
||||
if _, ok := elem.(interface {
|
||||
GetState(self *Element, timeout time.Duration) (ret StateChangeReturn, current, pending State)
|
||||
}); ok {
|
||||
C.setGstElementClassGetState(elemClass)
|
||||
}
|
||||
|
||||
if _, ok := elem.(interface {
|
||||
NoMorePads(*Element)
|
||||
}); ok {
|
||||
C.setGstElementClassNoMorePads(elemClass)
|
||||
}
|
||||
|
||||
if _, ok := elem.(interface {
|
||||
PadAdded(*Element, *Pad)
|
||||
}); ok {
|
||||
C.setGstElementClassPadAdded(elemClass)
|
||||
}
|
||||
|
||||
if _, ok := elem.(interface {
|
||||
PadRemoved(*Element, *Pad)
|
||||
}); ok {
|
||||
C.setGstElementClassPadRemoved(elemClass)
|
||||
}
|
||||
|
||||
if _, ok := elem.(interface {
|
||||
PostMessage(*Element, *Message) bool
|
||||
}); ok {
|
||||
C.setGstElementClassPostMessage(elemClass)
|
||||
}
|
||||
|
||||
if _, ok := elem.(interface {
|
||||
ProvideClock(*Element) *Clock
|
||||
}); ok {
|
||||
C.setGstElementClassProvideClock(elemClass)
|
||||
}
|
||||
|
||||
if _, ok := elem.(interface {
|
||||
Query(*Element, *Query) bool
|
||||
}); ok {
|
||||
C.setGstElementClassQuery(elemClass)
|
||||
}
|
||||
|
||||
if _, ok := elem.(interface {
|
||||
ReleasePad(*Element, *Pad)
|
||||
}); ok {
|
||||
C.setGstElementClassReleasePad(elemClass)
|
||||
}
|
||||
|
||||
if _, ok := elem.(interface {
|
||||
RequestNewPad(self *Element, templ *PadTemplate, name string, caps *Caps) *Pad
|
||||
}); ok {
|
||||
C.setGstElementClassRequestNewPad(elemClass)
|
||||
}
|
||||
|
||||
if _, ok := elem.(interface {
|
||||
SendEvent(*Element, *Event) bool
|
||||
}); ok {
|
||||
C.setGstElementClassSendEvent(elemClass)
|
||||
}
|
||||
|
||||
if _, ok := elem.(interface {
|
||||
SetBus(*Element, *Bus)
|
||||
}); ok {
|
||||
C.setGstElementClassSetBus(elemClass)
|
||||
}
|
||||
|
||||
if _, ok := elem.(interface {
|
||||
SetClock(*Element, *Clock) bool
|
||||
}); ok {
|
||||
C.setGstElementClassSetClock(elemClass)
|
||||
}
|
||||
|
||||
if _, ok := elem.(interface {
|
||||
SetContext(*Element, *Context)
|
||||
}); ok {
|
||||
C.setGstElementClassSetContext(elemClass)
|
||||
}
|
||||
|
||||
if _, ok := elem.(interface {
|
||||
SetState(*Element, State) StateChangeReturn
|
||||
}); ok {
|
||||
C.setGstElementClassSetState(elemClass)
|
||||
}
|
||||
|
||||
if _, ok := elem.(interface {
|
||||
StateChanged(self *Element, old, new, pending State)
|
||||
}); ok {
|
||||
C.setGstElementClassStateChanged(elemClass)
|
||||
}
|
||||
}
|
||||
|
@@ -14,11 +14,23 @@ import (
|
||||
// This is meant for internal usage and is exported for visibility to other packages.
|
||||
func FromGstElementUnsafe(elem unsafe.Pointer) *Element { return wrapElement(toGObject(elem)) }
|
||||
|
||||
// NewElement is a generic wrapper around `gst_element_factory_make`.
|
||||
func NewElement(name string) (*Element, error) {
|
||||
elemName := C.CString(name)
|
||||
// NewElement creates a new element using the factory of the given name.
|
||||
func NewElement(factory string) (*Element, error) {
|
||||
return NewElementWithName(factory, "")
|
||||
}
|
||||
|
||||
// NewElementWithName creates a new element and sets it's name to the given value.
|
||||
func NewElementWithName(factory string, name string) (*Element, error) {
|
||||
elemName := C.CString(factory)
|
||||
defer C.free(unsafe.Pointer(elemName))
|
||||
elem := C.gst_element_factory_make((*C.gchar)(elemName), nil)
|
||||
var elem *C.GstElement
|
||||
if name == "" {
|
||||
elem = C.gst_element_factory_make((*C.gchar)(elemName), nil)
|
||||
} else {
|
||||
cname := C.CString(name)
|
||||
defer C.free(unsafe.Pointer(cname))
|
||||
elem = C.gst_element_factory_make((*C.gchar)(elemName), (*C.gchar)(cname))
|
||||
}
|
||||
if elem == nil {
|
||||
return nil, fmt.Errorf("Could not create element: %s", name)
|
||||
}
|
||||
|
196
gst/gst_element_impl.go
Normal file
196
gst/gst_element_impl.go
Normal file
@@ -0,0 +1,196 @@
|
||||
package gst
|
||||
|
||||
/*
|
||||
#include "gst.go.h"
|
||||
|
||||
extern GstStateChangeReturn goGstElementClassChangeState (GstElement * element, GstStateChange change);
|
||||
extern GstStateChangeReturn goGstElementClassGetState (GstElement * element, GstState * state, GstState * pending, GstClockTime timeout);
|
||||
extern void goGstElementClassNoMorePads (GstElement * element);
|
||||
extern void goGstElementClassPadAdded (GstElement * element, GstPad * pad);
|
||||
extern void goGstElementClassPadRemoved (GstElement * element, GstPad * pad);
|
||||
extern gboolean goGstElementClassPostMessage (GstElement * element, GstMessage * msg);
|
||||
extern GstClock * goGstElementClassProvideClock (GstElement * element);
|
||||
extern gboolean goGstElementClassQuery (GstElement * element, GstQuery * query);
|
||||
extern void goGstElementClassReleasePad (GstElement * element, GstPad * pad);
|
||||
extern GstPad * goGstElementClassRequestNewPad (GstElement * element, GstPadTemplate * templ, const gchar * name, const GstCaps * caps);
|
||||
extern gboolean goGstElementClassSendEvent (GstElement * element, GstEvent * event);
|
||||
extern void goGstElementClassSetBus (GstElement * element, GstBus * bus);
|
||||
extern gboolean goGstElementClassSetClock (GstElement * element, GstClock * clock);
|
||||
extern void goGstElementClassSetContext (GstElement * element, GstContext * ctx);
|
||||
extern GstStateChangeReturn goGstElementClassSetState (GstElement * element, GstState state);
|
||||
extern void goGstElementClassStateChanged (GstElement * element, GstState old, GstState new, GstState pending);
|
||||
|
||||
void setGstElementClassChangeState (GstElementClass * klass) { klass->change_state = goGstElementClassChangeState; }
|
||||
void setGstElementClassGetState (GstElementClass * klass) { klass->get_state = goGstElementClassGetState; }
|
||||
void setGstElementClassNoMorePads (GstElementClass * klass) { klass->no_more_pads = goGstElementClassNoMorePads; }
|
||||
void setGstElementClassPadAdded (GstElementClass * klass) { klass->pad_added = goGstElementClassPadAdded; }
|
||||
void setGstElementClassPadRemoved (GstElementClass * klass) { klass->pad_removed = goGstElementClassPadRemoved; }
|
||||
void setGstElementClassPostMessage (GstElementClass * klass) { klass->post_message = goGstElementClassPostMessage; }
|
||||
void setGstElementClassProvideClock (GstElementClass * klass) { klass->provide_clock = goGstElementClassProvideClock; }
|
||||
void setGstElementClassQuery (GstElementClass * klass) { klass->query = goGstElementClassQuery; }
|
||||
void setGstElementClassReleasePad (GstElementClass * klass) { klass->release_pad = goGstElementClassReleasePad; }
|
||||
void setGstElementClassRequestNewPad (GstElementClass * klass) { klass->request_new_pad = goGstElementClassRequestNewPad; }
|
||||
void setGstElementClassSendEvent (GstElementClass * klass) { klass->send_event = goGstElementClassSendEvent; }
|
||||
void setGstElementClassSetBus (GstElementClass * klass) { klass->set_bus = goGstElementClassSetBus; }
|
||||
void setGstElementClassSetClock (GstElementClass * klass) { klass->set_clock = goGstElementClassSetClock; }
|
||||
void setGstElementClassSetContext (GstElementClass * klass) { klass->set_context = goGstElementClassSetContext; }
|
||||
void setGstElementClassSetState (GstElementClass * klass) { klass->set_state = goGstElementClassSetState; }
|
||||
void setGstElementClassStateChanged (GstElementClass * klass) { klass->state_changed = goGstElementClassStateChanged; }
|
||||
|
||||
*/
|
||||
import "C"
|
||||
import (
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"github.com/tinyzimmer/go-glib/glib"
|
||||
)
|
||||
|
||||
// ExtendsElement implements an Extendable object based on a GstElement.
|
||||
var ExtendsElement glib.Extendable = &extendElement{parent: glib.ExtendsObject}
|
||||
|
||||
// ElementImpl is an interface containing go equivalents of the virtual methods that can be
|
||||
// overridden by a plugin extending an Element.
|
||||
type ElementImpl interface {
|
||||
// ChangeState is called by SetState to perform an incremental state change.
|
||||
ChangeState(*Element, StateChange) StateChangeReturn
|
||||
// GetState should return the states of the element
|
||||
GetState(self *Element, timeout time.Duration) (ret StateChangeReturn, current, pending State)
|
||||
// NoMorePads is called when there are no more pads on the element.
|
||||
NoMorePads(*Element)
|
||||
// PadAdded is called to add a pad to the element.
|
||||
PadAdded(*Element, *Pad)
|
||||
// PadRemoved is called to remove a pad from the element.
|
||||
PadRemoved(*Element, *Pad)
|
||||
// PostMessage is called when a message is posted to the element. Call Element.ParentPostMessage
|
||||
// to have it posted on the bus after processing.
|
||||
PostMessage(*Element, *Message) bool
|
||||
// ProvideClock is called to retrieve the clock provided by the element.
|
||||
ProvideClock(*Element) *Clock
|
||||
// Query is called to perform a query on the element.
|
||||
Query(*Element, *Query) bool
|
||||
// ReleasePad is called when a request pad is to be released.
|
||||
ReleasePad(*Element, *Pad)
|
||||
// RequestNewPad is called when a new pad is requested from the element.
|
||||
RequestNewPad(self *Element, templ *PadTemplate, name string, caps *Caps) *Pad
|
||||
// SendEvent is called to send an event to the element.
|
||||
SendEvent(*Element, *Event) bool
|
||||
// SetBus is called to set the Bus on the element.
|
||||
SetBus(*Element, *Bus)
|
||||
// SetClock is called to set the clock on the element.
|
||||
SetClock(*Element, *Clock) bool
|
||||
// SetContext is called to set the Context on the element.
|
||||
SetContext(*Element, *Context)
|
||||
// SetState is called to set a new state on the element.
|
||||
SetState(*Element, State) StateChangeReturn
|
||||
// StateChanged is called immediately after a new state was set.
|
||||
StateChanged(self *Element, old, new, pending State)
|
||||
}
|
||||
|
||||
type extendElement struct{ parent glib.Extendable }
|
||||
|
||||
func (e *extendElement) Type() glib.Type { return glib.Type(C.gst_element_get_type()) }
|
||||
func (e *extendElement) ClassSize() int64 { return int64(C.sizeof_GstElementClass) }
|
||||
func (e *extendElement) InstanceSize() int64 { return int64(C.sizeof_GstElement) }
|
||||
|
||||
func (e *extendElement) InitClass(klass unsafe.Pointer, elem glib.GoObjectSubclass) {
|
||||
e.parent.InitClass(klass, elem)
|
||||
|
||||
elemClass := C.toGstElementClass(klass)
|
||||
|
||||
if _, ok := elem.(interface {
|
||||
ChangeState(*Element, StateChange) StateChangeReturn
|
||||
}); ok {
|
||||
C.setGstElementClassChangeState(elemClass)
|
||||
}
|
||||
|
||||
if _, ok := elem.(interface {
|
||||
GetState(self *Element, timeout time.Duration) (ret StateChangeReturn, current, pending State)
|
||||
}); ok {
|
||||
C.setGstElementClassGetState(elemClass)
|
||||
}
|
||||
|
||||
if _, ok := elem.(interface {
|
||||
NoMorePads(*Element)
|
||||
}); ok {
|
||||
C.setGstElementClassNoMorePads(elemClass)
|
||||
}
|
||||
|
||||
if _, ok := elem.(interface {
|
||||
PadAdded(*Element, *Pad)
|
||||
}); ok {
|
||||
C.setGstElementClassPadAdded(elemClass)
|
||||
}
|
||||
|
||||
if _, ok := elem.(interface {
|
||||
PadRemoved(*Element, *Pad)
|
||||
}); ok {
|
||||
C.setGstElementClassPadRemoved(elemClass)
|
||||
}
|
||||
|
||||
if _, ok := elem.(interface {
|
||||
PostMessage(*Element, *Message) bool
|
||||
}); ok {
|
||||
C.setGstElementClassPostMessage(elemClass)
|
||||
}
|
||||
|
||||
if _, ok := elem.(interface {
|
||||
ProvideClock(*Element) *Clock
|
||||
}); ok {
|
||||
C.setGstElementClassProvideClock(elemClass)
|
||||
}
|
||||
|
||||
if _, ok := elem.(interface {
|
||||
Query(*Element, *Query) bool
|
||||
}); ok {
|
||||
C.setGstElementClassQuery(elemClass)
|
||||
}
|
||||
|
||||
if _, ok := elem.(interface {
|
||||
ReleasePad(*Element, *Pad)
|
||||
}); ok {
|
||||
C.setGstElementClassReleasePad(elemClass)
|
||||
}
|
||||
|
||||
if _, ok := elem.(interface {
|
||||
RequestNewPad(self *Element, templ *PadTemplate, name string, caps *Caps) *Pad
|
||||
}); ok {
|
||||
C.setGstElementClassRequestNewPad(elemClass)
|
||||
}
|
||||
|
||||
if _, ok := elem.(interface {
|
||||
SendEvent(*Element, *Event) bool
|
||||
}); ok {
|
||||
C.setGstElementClassSendEvent(elemClass)
|
||||
}
|
||||
|
||||
if _, ok := elem.(interface {
|
||||
SetBus(*Element, *Bus)
|
||||
}); ok {
|
||||
C.setGstElementClassSetBus(elemClass)
|
||||
}
|
||||
|
||||
if _, ok := elem.(interface {
|
||||
SetClock(*Element, *Clock) bool
|
||||
}); ok {
|
||||
C.setGstElementClassSetClock(elemClass)
|
||||
}
|
||||
|
||||
if _, ok := elem.(interface {
|
||||
SetContext(*Element, *Context)
|
||||
}); ok {
|
||||
C.setGstElementClassSetContext(elemClass)
|
||||
}
|
||||
|
||||
if _, ok := elem.(interface {
|
||||
SetState(*Element, State) StateChangeReturn
|
||||
}); ok {
|
||||
C.setGstElementClassSetState(elemClass)
|
||||
}
|
||||
|
||||
if _, ok := elem.(interface {
|
||||
StateChanged(self *Element, old, new, pending State)
|
||||
}); ok {
|
||||
C.setGstElementClassStateChanged(elemClass)
|
||||
}
|
||||
}
|
@@ -72,11 +72,11 @@ func (m *Message) String() string {
|
||||
|
||||
case MessageStructureChange:
|
||||
chgType, elem, busy := m.ParseStructureChange()
|
||||
msg += fmt.Sprintf("Structure change of type %s from %s. (in progress: %v)", chgType.String(), elem.Name(), busy)
|
||||
msg += fmt.Sprintf("Structure change of type %s from %s. (in progress: %v)", chgType.String(), elem.GetName(), busy)
|
||||
|
||||
case MessageStreamStatus:
|
||||
statusType, elem := m.ParseStreamStatus()
|
||||
msg += fmt.Sprintf("Stream status from %s: %s", elem.Name(), statusType.String())
|
||||
msg += fmt.Sprintf("Stream status from %s: %s", elem.GetName(), statusType.String())
|
||||
|
||||
case MessageApplication:
|
||||
msg += "Message posted by the application, possibly via an application-specific element."
|
||||
@@ -165,7 +165,7 @@ func (m *Message) String() string {
|
||||
if obj != nil && propVal != nil {
|
||||
goval, err := propVal.GoValue()
|
||||
if err != nil {
|
||||
msg += fmt.Sprintf("Object %s had property '%s' changed to %+v", obj.Name(), propName, goval)
|
||||
msg += fmt.Sprintf("Object %s had property '%s' changed to %+v", obj.GetName(), propName, goval)
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -4,6 +4,7 @@ package gst
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"time"
|
||||
"unsafe"
|
||||
|
||||
"github.com/tinyzimmer/go-glib/glib"
|
||||
@@ -14,70 +15,36 @@ type Object struct{ *glib.InitiallyUnowned }
|
||||
|
||||
// FromGstObjectUnsafe returns an Object wrapping the given pointer. It meant for internal
|
||||
// usage and exported for visibility to other packages.
|
||||
func FromGstObjectUnsafe(ptr unsafe.Pointer) *Object {
|
||||
return wrapObject(toGObject(ptr))
|
||||
}
|
||||
|
||||
// Unsafe returns the unsafe pointer to the underlying object. This method is primarily
|
||||
// for internal usage and is exposed for visibility in other packages.
|
||||
func (o *Object) Unsafe() unsafe.Pointer {
|
||||
if o == nil || o.GObject == nil {
|
||||
return nil
|
||||
}
|
||||
return unsafe.Pointer(o.GObject)
|
||||
}
|
||||
func FromGstObjectUnsafe(ptr unsafe.Pointer) *Object { return wrapObject(toGObject(ptr)) }
|
||||
|
||||
// Instance returns the native C GstObject.
|
||||
func (o *Object) Instance() *C.GstObject { return C.toGstObject(o.Unsafe()) }
|
||||
|
||||
// BaseObject returns this object for embedding structs.
|
||||
// BaseObject is a convenience method for retrieving this object from embedded structs.
|
||||
func (o *Object) BaseObject() *Object { return o }
|
||||
|
||||
// GstObject is an alias to Instance on the underlying GstObject of any extending struct.
|
||||
func (o *Object) GstObject() *C.GstObject { return C.toGstObject(o.Unsafe()) }
|
||||
|
||||
// Class returns the GObjectClass of this instance.
|
||||
func (o *Object) Class() *C.GObjectClass { return C.getGObjectClass(o.Unsafe()) }
|
||||
// GObject returns the underlying GObject instance.
|
||||
func (o *Object) GObject() *glib.Object { return o.InitiallyUnowned.Object }
|
||||
|
||||
// Name returns the name of this object.
|
||||
func (o *Object) Name() string {
|
||||
// GetName returns the name of this object.
|
||||
func (o *Object) GetName() string {
|
||||
cName := C.gst_object_get_name((*C.GstObject)(o.Instance()))
|
||||
defer C.free(unsafe.Pointer(cName))
|
||||
return C.GoString(cName)
|
||||
}
|
||||
|
||||
// Interfaces returns the interfaces associated with this object.
|
||||
func (o *Object) Interfaces() []string {
|
||||
var size C.guint
|
||||
ifaces := C.g_type_interfaces(C.gsize(o.TypeFromInstance()), &size)
|
||||
if int(size) == 0 {
|
||||
// GetValue retrieves the value for the given controlled property at the given timestamp.
|
||||
func (o *Object) GetValue(property string, timestamp time.Duration) *glib.Value {
|
||||
cprop := C.CString(property)
|
||||
defer C.free(unsafe.Pointer(cprop))
|
||||
gval := C.gst_object_get_value(o.Instance(), (*C.gchar)(cprop), C.GstClockTime(timestamp.Nanoseconds()))
|
||||
if gval == nil {
|
||||
return nil
|
||||
}
|
||||
defer C.g_free((C.gpointer)(ifaces))
|
||||
out := make([]string, int(size))
|
||||
for _, t := range (*[1 << 30]int)(unsafe.Pointer(ifaces))[:size:size] {
|
||||
out = append(out, glib.Type(t).Name())
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// ListProperties returns a list of the properties associated with this object.
|
||||
// The default values assumed in the parameter spec reflect the values currently
|
||||
// set in this object, or their defaults.
|
||||
//
|
||||
// Unref after usage.
|
||||
func (o *Object) ListProperties() []*glib.ParamSpec {
|
||||
var size C.guint
|
||||
props := C.g_object_class_list_properties((*C.GObjectClass)(o.Class()), &size)
|
||||
if props == nil {
|
||||
return nil
|
||||
}
|
||||
defer C.g_free((C.gpointer)(props))
|
||||
out := make([]*glib.ParamSpec, 0)
|
||||
for _, prop := range (*[1 << 30]*C.GParamSpec)(unsafe.Pointer(props))[:size:size] {
|
||||
out = append(out, glib.ToParamSpec(unsafe.Pointer(prop)))
|
||||
}
|
||||
return out
|
||||
return glib.ValueFromNative(unsafe.Pointer(gval))
|
||||
}
|
||||
|
||||
// Log logs a message to the given category from this object using the currently registered
|
||||
@@ -85,3 +52,25 @@ func (o *Object) ListProperties() []*glib.ParamSpec {
|
||||
func (o *Object) Log(cat *DebugCategory, level DebugLevel, message string) {
|
||||
cat.logDepth(level, message, 2, (*C.GObject)(o.Unsafe()))
|
||||
}
|
||||
|
||||
// Clear will will clear all references to this object. If the reference is already null
|
||||
// the the function does nothing. Otherwise the reference count is decreased and the pointer
|
||||
// set to null.
|
||||
func (o *Object) Clear() {
|
||||
if ptr := o.Unsafe(); ptr != nil {
|
||||
C.gst_clear_object((**C.GstObject)(unsafe.Pointer(&ptr)))
|
||||
}
|
||||
}
|
||||
|
||||
// Ref increments the reference count on object. This function does not take the lock on object
|
||||
// because it relies on atomic refcounting. For convenience the same object is returned.
|
||||
func (o *Object) Ref() *Object {
|
||||
C.gst_object_ref((C.gpointer)(o.Unsafe()))
|
||||
return o
|
||||
}
|
||||
|
||||
// Unref decrements the reference count on object. If reference count hits zero, destroy object.
|
||||
// This function does not take the lock on object as it relies on atomic refcounting.
|
||||
func (o *Object) Unref() {
|
||||
C.gst_object_unref((C.gpointer)(o.Unsafe()))
|
||||
}
|
||||
|
@@ -9,8 +9,15 @@ import (
|
||||
)
|
||||
|
||||
// InterfaceTagSetter represents the GstTagsetter interface GType. Use this when querying bins
|
||||
// for elements that implement a TagSetter.
|
||||
var InterfaceTagSetter = glib.Type(C.GST_TYPE_TAG_SETTER)
|
||||
// for elements that implement a TagSetter. Extending this interface is not yet implemented.
|
||||
var InterfaceTagSetter glib.Interface = &interfaceTagSetter{}
|
||||
|
||||
type interfaceTagSetter struct{}
|
||||
|
||||
func (i *interfaceTagSetter) Type() glib.Type { return glib.Type(C.GST_TYPE_TAG_SETTER) }
|
||||
func (i *interfaceTagSetter) InitFunc() glib.InterfaceInitFunc {
|
||||
return func(instance *glib.TypeInstance) {}
|
||||
}
|
||||
|
||||
// TagSetter is an interface that elements can implement to provide Tag writing capabilities.
|
||||
type TagSetter interface {
|
||||
|
@@ -27,21 +27,18 @@ import (
|
||||
)
|
||||
|
||||
// InterfaceURIHandler represents the GstURIHandler interface GType. Use this when querying bins
|
||||
// for elements that implement a URIHandler, or when signaling that a GoElement provides this
|
||||
// interface.
|
||||
// for elements that implement a URIHandler, or when signaling that a GoObjectSubclass provides this
|
||||
// interface. Note that the way this interface is implemented, it can only be used once per plugin.
|
||||
var InterfaceURIHandler glib.Interface = &interfaceURIHandler{}
|
||||
|
||||
type interfaceURIHandler struct {
|
||||
glib.Interface
|
||||
}
|
||||
type interfaceURIHandler struct{ glib.Interface }
|
||||
|
||||
func (i *interfaceURIHandler) Type() glib.Type {
|
||||
return glib.Type(C.GST_TYPE_URI_HANDLER)
|
||||
}
|
||||
|
||||
func (i *interfaceURIHandler) InitFunc(t *glib.TypeInstance) unsafe.Pointer {
|
||||
globalURIHdlr = t.GoType.(URIHandler)
|
||||
return unsafe.Pointer(C.uriHandlerInit)
|
||||
func (i *interfaceURIHandler) Type() glib.Type { return glib.Type(C.GST_TYPE_URI_HANDLER) }
|
||||
func (i *interfaceURIHandler) InitFunc() glib.InterfaceInitFunc {
|
||||
return func(instance *glib.TypeInstance) {
|
||||
globalURIHdlr = instance.GoType.(URIHandler)
|
||||
C.uriHandlerInit((C.gpointer)(instance.GTypeInstance), nil)
|
||||
}
|
||||
}
|
||||
|
||||
// URIHandler represents an interface that elements can implement to provide URI handling
|
||||
|
Reference in New Issue
Block a user