Files
go-gst/gst/gst_element.go

171 lines
5.3 KiB
Go

package gst
// #include "gst.go.h"
import "C"
import (
"fmt"
"unsafe"
"github.com/gotk3/gotk3/glib"
)
// Element is a Go wrapper around a GstElement.
type Element struct{ *Object }
// ElementLinkMany is a go implementation of `gst_element_link_many` to compensate for
// no variadic functions in cgo.
func ElementLinkMany(elems ...*Element) error {
for idx, elem := range elems {
if idx == 0 {
// skip the first one as the loop always links previous to current
continue
}
if err := elems[idx-1].Link(elem); err != nil {
return err
}
}
return nil
}
// Instance returns the underlying GstElement instance.
func (e *Element) Instance() *C.GstElement { return C.toGstElement(e.unsafe()) }
// 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 nil
}
// LinkFiltered wraps gst_element_link_filtered and link this element to the given one
// 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 nil
}
// GetBus returns the GstBus for retrieving messages from this element. This function returns
// nil unless the element is a Pipeline.
func (e *Element) GetBus() *Bus {
bus := C.gst_element_get_bus((*C.GstElement)(e.Instance()))
if bus == nil {
return nil
}
return wrapBus(glib.Take(unsafe.Pointer(bus)))
}
// GetClock returns the Clock for this element. This is the clock as was last set with gst_element_set_clock.
// Elements in a pipeline will only have their clock set when the pipeline is in the PLAYING state.
func (e *Element) GetClock() *Clock {
cClock := C.gst_element_get_clock((*C.GstElement)(e.Instance()))
if cClock == nil {
return nil
}
return wrapClock(glib.Take(unsafe.Pointer(cClock)))
}
// GetState returns the current state of this element.
func (e *Element) GetState() State {
return State(e.Instance().current_state)
}
// SetState sets the target state for this element.
func (e *Element) SetState(state State) error {
stateRet := C.gst_element_set_state((*C.GstElement)(e.Instance()), C.GstState(state))
if stateRet == C.GST_STATE_CHANGE_FAILURE {
return fmt.Errorf("Failed to change state to %s", state.String())
}
return nil
}
// BlockSetState is like SetState except it will block until the transition
// is complete.
func (e *Element) BlockSetState(state State) error {
stateRet := C.gst_element_set_state((*C.GstElement)(e.Instance()), C.GST_STATE_PLAYING)
if stateRet == C.GST_STATE_CHANGE_FAILURE {
return fmt.Errorf("Failed to change state to %s", state.String())
}
var curState C.GstState
C.gst_element_get_state(
(*C.GstElement)(e.Instance()),
(*C.GstState)(unsafe.Pointer(&curState)),
(*C.GstState)(unsafe.Pointer(&state)),
C.GST_CLOCK_TIME_NONE,
)
return nil
}
// GetFactory returns the factory that created this element. No refcounting is needed.
func (e *Element) GetFactory() *ElementFactory {
factory := C.gst_element_get_factory((*C.GstElement)(e.Instance()))
if factory == nil {
return nil
}
return wrapElementFactory(glib.Take(unsafe.Pointer(factory)))
}
// GetPads retrieves a list of pads associated with the element.
func (e *Element) GetPads() []*Pad {
goList := glib.WrapList(uintptr(unsafe.Pointer(e.Instance().pads)))
out := make([]*Pad, 0)
goList.Foreach(func(item interface{}) {
pt := item.(unsafe.Pointer)
out = append(out, wrapPad(glib.Take(pt)))
})
return out
}
// GetPadTemplates retrieves a list of the pad templates associated with this element.
// The list must not be modified by the calling code.
func (e *Element) GetPadTemplates() []*PadTemplate {
glist := C.gst_element_get_pad_template_list((*C.GstElement)(e.Instance()))
if glist == nil {
return nil
}
goList := glib.WrapList(uintptr(unsafe.Pointer(glist)))
out := make([]*PadTemplate, 0)
goList.Foreach(func(item interface{}) {
pt := item.(unsafe.Pointer)
out = append(out, wrapPadTemplate(glib.Take(pt)))
})
return out
}
// Has returns true if this element has the given flags.
func (e *Element) Has(flags ElementFlags) bool {
return gobool(C.gstObjectFlagIsSet(C.toGstObject(e.unsafe()), C.GstElementFlags(flags)))
}
// IsURIHandler returns true if this element can handle URIs.
func (e *Element) IsURIHandler() bool {
return gobool(C.gstElementIsURIHandler(e.Instance()))
}
func (e *Element) uriHandler() *C.GstURIHandler { return C.toGstURIHandler(e.unsafe()) }
// GetURIType returns the type of URI this element can handle.
func (e *Element) GetURIType() URIType {
if !e.IsURIHandler() {
return URIUnknown
}
ty := C.gst_uri_handler_get_uri_type((*C.GstURIHandler)(e.uriHandler()))
return URIType(ty)
}
// GetURIProtocols returns the protocols this element can handle.
func (e *Element) GetURIProtocols() []string {
if !e.IsURIHandler() {
return nil
}
protocols := C.gst_uri_handler_get_protocols((*C.GstURIHandler)(e.uriHandler()))
if protocols == nil {
return nil
}
size := C.sizeOfGCharArray(protocols)
return goStrings(size, protocols)
}