mirror of
https://github.com/go-gst/go-gst.git
synced 2025-10-05 07:56:51 +08:00
add tag/toc examples and general cleanup
This commit is contained in:
@@ -243,10 +243,12 @@ func printURIHandlerInfo(elem *gst.Element) {
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
colorOrange.print("URI handling capabilities:\n")
|
||||
colorLightGray.printfIndent(2, "Element can act as %s.\n", strings.ToLower(elem.GetURIType().String()))
|
||||
uriHandler := elem.URIHandler()
|
||||
|
||||
protos := elem.GetURIProtocols()
|
||||
colorOrange.print("URI handling capabilities:\n")
|
||||
colorLightGray.printfIndent(2, "Element can act as %s.\n", strings.ToLower(uriHandler.GetURIType().String()))
|
||||
|
||||
protos := uriHandler.GetURIProtocols()
|
||||
|
||||
if len(protos) == 0 {
|
||||
fmt.Println()
|
||||
|
97
examples/tagsetter/main.go
Normal file
97
examples/tagsetter/main.go
Normal file
@@ -0,0 +1,97 @@
|
||||
// This example demonstrates how to set and store metadata using GStreamer.
|
||||
//
|
||||
// Some elements support setting tags on a media stream. An example would be
|
||||
// id3v2mux. The element signals this by implementing The GstTagsetter interface.
|
||||
// You can query any element implementing this interface from the pipeline, and
|
||||
// then tell the returned implementation of GstTagsetter what tags to apply to
|
||||
// the media stream.
|
||||
//
|
||||
// This example's pipeline creates a new flac file from the testaudiosrc
|
||||
// that the example application will add tags to using GstTagsetter.
|
||||
// The operated pipeline looks like this:
|
||||
//
|
||||
// {audiotestsrc} - {flacenc} - {filesink}
|
||||
//
|
||||
// For example for pipelines that transcode a multimedia file, the input
|
||||
// already has tags. For cases like this, the GstTagsetter has the merge
|
||||
// setting, which the application can configure to tell the element
|
||||
// implementing the interface whether to merge newly applied tags to the
|
||||
// already existing ones, or if all existing ones should replace, etc.
|
||||
// (More modes of operation are possible, see: gst.TagMergeMode)
|
||||
// This merge-mode can also be supplied to any method that adds new tags.
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/tinyzimmer/go-gst/examples"
|
||||
"github.com/tinyzimmer/go-gst/gst"
|
||||
)
|
||||
|
||||
func tagsetter() error {
|
||||
gst.Init(nil)
|
||||
|
||||
pipeline, err := gst.NewPipelineFromString(
|
||||
"audiotestsrc wave=white-noise num-buffers=10000 ! flacenc ! filesink location=test.flac",
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer pipeline.Destroy()
|
||||
|
||||
// Query the pipeline for elements implementing the GstTagsetter interface.
|
||||
// In our case, this will return the flacenc element.
|
||||
element, err := pipeline.GetByInterface(gst.InterfaceTagSetter)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// We actually just retrieved a *gst.Element with the above call. We can retrieve
|
||||
// the underying TagSetter interface like this.
|
||||
tagsetter := element.TagSetter()
|
||||
|
||||
// Tell the element implementing the GstTagsetter interface how to handle already existing
|
||||
// metadata.
|
||||
tagsetter.SetTagMergeMode(gst.TagMergeKeepAll)
|
||||
|
||||
// Set the "title" tag to "Special randomized white-noise".
|
||||
//
|
||||
// The first parameter gst.TagMergeAppend tells the tagsetter to append this title
|
||||
// if there already is one.
|
||||
tagsetter.AddTagValue(gst.TagMergeAppend, gst.TagTitle, "Special randomized white-noise")
|
||||
|
||||
pipeline.SetState(gst.StatePlaying)
|
||||
|
||||
var cont bool
|
||||
var pipelineErr error
|
||||
for {
|
||||
msg := pipeline.GetPipelineBus().TimedPop(time.Duration(-1))
|
||||
if msg == nil {
|
||||
break
|
||||
}
|
||||
if cont, pipelineErr = handleMessage(msg); pipelineErr != nil || !cont {
|
||||
pipeline.SetState(gst.StateNull)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return pipelineErr
|
||||
}
|
||||
|
||||
func handleMessage(msg *gst.Message) (bool, error) {
|
||||
defer msg.Unref()
|
||||
switch msg.Type() {
|
||||
case gst.MessageTag:
|
||||
fmt.Println(msg) // Prirnt our tags
|
||||
case gst.MessageEOS:
|
||||
return false, nil
|
||||
case gst.MessageError:
|
||||
return false, msg.ParseError()
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
examples.Run(tagsetter)
|
||||
}
|
171
examples/toc/main.go
Normal file
171
examples/toc/main.go
Normal file
@@ -0,0 +1,171 @@
|
||||
// This example demonstrates the use of GStreamer's ToC API.
|
||||
//
|
||||
// This API is used to manage a table of contents contained in the handled media stream.
|
||||
// Chapters within a matroska file would be an example of a scenario for using
|
||||
// this API. Elements that can parse ToCs from a stream (such as matroskademux)
|
||||
// notify all elements in the pipeline when they encountered a ToC.
|
||||
// For this, the example operates the following pipeline:
|
||||
//
|
||||
// /-{queue} - {fakesink}
|
||||
// {filesrc} - {decodebin} - {queue} - {fakesink}
|
||||
// \- ...
|
||||
//
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/tinyzimmer/go-gst/examples"
|
||||
"github.com/tinyzimmer/go-gst/gst"
|
||||
)
|
||||
|
||||
func tagsetter(mainLoop *gst.MainLoop) error {
|
||||
gst.Init(nil)
|
||||
|
||||
if len(os.Args) < 2 {
|
||||
return errors.New("Usage: toc <file>")
|
||||
}
|
||||
|
||||
pipeline, err := gst.NewPipeline("")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer pipeline.Destroy()
|
||||
|
||||
src, err := gst.NewElement("filesrc")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
decodebin, err := gst.NewElement("decodebin")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
src.SetProperty("location", os.Args[1])
|
||||
|
||||
pipeline.AddMany(src, decodebin)
|
||||
gst.ElementLinkMany(src, decodebin)
|
||||
|
||||
// Connect to decodebin's pad-added signal, that is emitted whenever it found another stream
|
||||
// from the input file and found a way to decode it to its raw format.
|
||||
decodebin.Connect("pad-added", func(_ *gst.Element, srcPad *gst.Pad) {
|
||||
|
||||
// In this example, we are only interested about parsing the ToC, so
|
||||
// we simply pipe every encountered stream into a fakesink, essentially
|
||||
// throwing away the data.
|
||||
elems, err := gst.NewElementMany("queue", "fakesink")
|
||||
if err != nil {
|
||||
fmt.Println("Could not create decodebin pipeline")
|
||||
return
|
||||
}
|
||||
pipeline.AddMany(elems...)
|
||||
gst.ElementLinkMany(elems...)
|
||||
for _, e := range elems {
|
||||
e.SyncStateWithParent()
|
||||
}
|
||||
|
||||
queue := elems[0]
|
||||
sinkPad := queue.GetStaticPad("sink")
|
||||
if sinkPad == nil {
|
||||
fmt.Println("Could not get static pad from sink")
|
||||
return
|
||||
}
|
||||
|
||||
srcPad.
|
||||
Link(sinkPad)
|
||||
})
|
||||
|
||||
if err := pipeline.SetState(gst.StatePaused); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Instead of using the main loop, we manually iterate over GStreamer's bus messages
|
||||
// in this example. We don't need any special functionality like timeouts or GLib socket
|
||||
// notifications, so this is sufficient. The bus is manually operated by repeatedly calling
|
||||
// timed_pop on the bus with the desired timeout for when to stop waiting for new messages.
|
||||
// (-1 = Wait forever)
|
||||
for {
|
||||
msg := pipeline.GetPipelineBus().TimedPop(time.Duration(-1))
|
||||
switch msg.Type() {
|
||||
|
||||
// When we use this method of popping from the bus (instead of a Watch), we own a
|
||||
// reference to every message received (this may be abstracted later).
|
||||
default:
|
||||
// fmt.Println(msg)
|
||||
msg.Unref()
|
||||
|
||||
// End of stream
|
||||
case gst.MessageEOS:
|
||||
msg.Unref()
|
||||
break
|
||||
|
||||
// Errors from any elements
|
||||
case gst.MessageError:
|
||||
gerr := msg.ParseError()
|
||||
if debug := gerr.DebugString(); debug != "" {
|
||||
fmt.Println("go-gst-debug:", debug)
|
||||
}
|
||||
msg.Unref()
|
||||
return gerr
|
||||
|
||||
// Some element found a ToC in the current media stream and told
|
||||
// us by posting a message to GStreamer's bus.
|
||||
case gst.MessageTOC:
|
||||
// Parse the toc from the message
|
||||
toc, updated := msg.ParseTOC()
|
||||
msg.Unref()
|
||||
fmt.Printf("Received toc: %s - updated %v\n", toc.GetScope(), updated)
|
||||
// Get a list of tags that are ToC specific.
|
||||
if tags := toc.GetTags(); tags != nil {
|
||||
fmt.Println("- tags:", tags)
|
||||
}
|
||||
// ToCs do not have a fixed structure. Depending on the format that
|
||||
// they were parsed from, they might have different tree-like structures,
|
||||
// so applications that want to support ToCs (for example in the form
|
||||
// of jumping between chapters in a video) have to try parsing and
|
||||
// interpreting the ToC manually.
|
||||
// In this example, we simply want to print the ToC structure, so
|
||||
// we iterate everything and don't try to interpret anything.
|
||||
for _, entry := range toc.GetEntries() {
|
||||
// Every entry in a ToC has its own type. One type could for
|
||||
// example be Chapter.
|
||||
fmt.Printf("\t%s - %s\n", entry.GetEntryTypeString(), entry.GetUID())
|
||||
|
||||
// Every ToC entry can have a set of timestamps (start, stop).
|
||||
if ok, start, stop := entry.GetStartStopTimes(); ok {
|
||||
startDur := time.Duration(start) * time.Nanosecond
|
||||
stopDur := time.Duration(stop) * time.Nanosecond
|
||||
fmt.Printf("\t- start: %s, stop: %s\n", startDur, stopDur)
|
||||
}
|
||||
|
||||
// Every ToC entry can have tags to it.
|
||||
if tags := entry.GetTags(); tags != nil {
|
||||
fmt.Println("\t- tags:", tags)
|
||||
}
|
||||
|
||||
// Every ToC entry can have a set of child entries.
|
||||
// With this structure, you can create trees of arbitrary depth.
|
||||
for _, subEntry := range entry.GetSubEntries() {
|
||||
fmt.Printf("\n\t\t%s - %s\n", subEntry.GetEntryTypeString(), subEntry.GetUID())
|
||||
if ok, start, stop := entry.GetStartStopTimes(); ok {
|
||||
startDur := time.Duration(start) * time.Nanosecond
|
||||
stopDur := time.Duration(stop) * time.Nanosecond
|
||||
fmt.Printf("\t\t- start: %s, stop: %s\n", startDur, stopDur)
|
||||
}
|
||||
if tags := entry.GetTags(); tags != nil {
|
||||
fmt.Println("\t\t- tags:", tags)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
toc.Unref()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
examples.RunLoop(tagsetter)
|
||||
}
|
@@ -806,6 +806,17 @@ const (
|
||||
TOCScopeCurrent TOCScope = C.GST_TOC_SCOPE_CURRENT
|
||||
)
|
||||
|
||||
// String implements a stringer on a TOCScope
|
||||
func (t TOCScope) String() string {
|
||||
switch t {
|
||||
case TOCScopeGlobal:
|
||||
return "global"
|
||||
case TOCScopeCurrent:
|
||||
return "current"
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// TOCLoopType represents a GstTocLoopType
|
||||
type TOCLoopType int
|
||||
|
||||
|
@@ -91,6 +91,26 @@ func (b *Bin) GetElementsSorted() ([]*Element, error) {
|
||||
return iteratorToElementSlice(iterator)
|
||||
}
|
||||
|
||||
// GetByInterface looks for an element inside the bin that implements the given interface. If such an
|
||||
// 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))
|
||||
if elem == nil {
|
||||
return nil, fmt.Errorf("Could not find any elements implementing %s", iface.Name())
|
||||
}
|
||||
return wrapElement(toGObject(unsafe.Pointer(elem))), nil
|
||||
}
|
||||
|
||||
// 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))
|
||||
return iteratorToElementSlice(iterator)
|
||||
}
|
||||
|
||||
// // GetElementsByFactoryName returns a list of the elements in this bin created from the given factory
|
||||
// // name.
|
||||
// func (b *Bin) GetElementsByFactoryName(name string) ([]*Element, error) {
|
||||
|
@@ -174,30 +174,14 @@ func (e *Element) IsURIHandler() bool {
|
||||
return gobool(C.gstElementIsURIHandler(e.Instance()))
|
||||
}
|
||||
|
||||
// TODO: Go back over URI and implement as interface
|
||||
|
||||
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() {
|
||||
// URIHandler returns a URIHandler interface if implemented by this element. Otherwise it
|
||||
// returns nil. Currently this only supports elements built through this package, however,
|
||||
// inner application elements could still use the interface as a reference implementation.
|
||||
func (e *Element) URIHandler() URIHandler {
|
||||
if C.toGstURIHandler(e.Unsafe()) == nil {
|
||||
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)
|
||||
return &gstURIHandler{ptr: e.Instance()}
|
||||
}
|
||||
|
||||
// TOCSetter returns a TOCSetter interface if implemented by this element. Otherwise it
|
||||
|
@@ -205,14 +205,14 @@ func (e *Event) ParseSegmentDone() (Format, int64) {
|
||||
|
||||
// ParseSelectStreams parses the SELECT_STREAMS event and retrieve the contained streams.
|
||||
func (e *Event) ParseSelectStreams() []*Stream {
|
||||
outList := &C.GList{}
|
||||
var outList *C.GList
|
||||
C.gst_event_parse_select_streams(e.Instance(), &outList)
|
||||
return glistToStreamSlice(outList)
|
||||
}
|
||||
|
||||
// ParseSinkMessage parses the sink-message event. Unref msg after usage.
|
||||
func (e *Event) ParseSinkMessage() *Message {
|
||||
msg := &C.GstMessage{}
|
||||
var msg *C.GstMessage
|
||||
C.gst_event_parse_sink_message(e.Instance(), &msg)
|
||||
return wrapMessage(msg)
|
||||
}
|
||||
@@ -229,7 +229,7 @@ func (e *Event) ParseStep() (format Format, amount uint64, rate float64, flush,
|
||||
|
||||
// ParseStream parses a stream-start event and extract the GstStream from it.
|
||||
func (e *Event) ParseStream() *Stream {
|
||||
stream := &C.GstStream{}
|
||||
var stream *C.GstStream
|
||||
C.gst_event_parse_stream(e.Instance(), &stream)
|
||||
return wrapStream(&glib.Object{GObject: glib.ToGObject(unsafe.Pointer(stream))})
|
||||
}
|
||||
@@ -265,14 +265,14 @@ func (e *Event) ParseStreamStart() string {
|
||||
// ParseTag parses a tag event and stores the results in the given taglist location. Do not modify or free the returned
|
||||
// tag list.
|
||||
func (e *Event) ParseTag() *TagList {
|
||||
out := &C.GstTagList{}
|
||||
var out *C.GstTagList
|
||||
C.gst_event_parse_tag(e.Instance(), &out)
|
||||
return wrapTagList(out)
|
||||
}
|
||||
|
||||
// ParseTOC parses a TOC event and store the results in the given toc and updated locations.
|
||||
func (e *Event) ParseTOC() (toc *TOC, updated bool) {
|
||||
out := &C.GstToc{}
|
||||
var out *C.GstToc
|
||||
var gupdated C.gboolean
|
||||
C.gst_event_parse_toc(e.Instance(), &out, &gupdated)
|
||||
return wrapTOC(out), gobool(gupdated)
|
||||
|
@@ -144,6 +144,15 @@ func (m *Message) ParseTags() *TagList {
|
||||
return wrapTagList(tagList)
|
||||
}
|
||||
|
||||
// ParseTOC extracts the TOC from the GstMessage. The TOC returned in the output argument is
|
||||
// a copy; the caller must free it with Unref when done.
|
||||
func (m *Message) ParseTOC() (toc *TOC, updated bool) {
|
||||
var gtoc *C.GstToc
|
||||
var gupdated C.gboolean
|
||||
C.gst_message_parse_toc(m.Instance(), >oc, &gupdated)
|
||||
return wrapTOC(gtoc), gobool(gupdated)
|
||||
}
|
||||
|
||||
// ParseStreamStatus parses the stream status type of the message as well as the element
|
||||
// that produced it. The element returned should NOT be unrefed.
|
||||
func (m *Message) ParseStreamStatus() (StreamStatusType, *Element) {
|
||||
|
@@ -8,13 +8,17 @@ import (
|
||||
"github.com/gotk3/gotk3/glib"
|
||||
)
|
||||
|
||||
// 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)
|
||||
|
||||
// TagSetter is an interface that elements can implement to provide Tag writing capabilities.
|
||||
type TagSetter interface {
|
||||
// Returns the current list of tags the setter uses. The list should not be modified or freed.
|
||||
GetTagList() *TagList
|
||||
// Adds the given tag/value pair using the given merge mode. If the tag value cannot be coerced
|
||||
// to a GValue when dealing with C elements, nothing will happen.
|
||||
AddTagValue(mergeMode TagMergeMode, tagKey string, tagValue interface{})
|
||||
AddTagValue(mergeMode TagMergeMode, tagKey Tag, tagValue interface{})
|
||||
// Merges a tag list with the given merge mode
|
||||
MergeTags(*TagList, TagMergeMode)
|
||||
// Resets the internal tag list. Elements should call this from within the state-change handler.
|
||||
@@ -42,8 +46,8 @@ func (t *gstTagSetter) GetTagList() *TagList {
|
||||
return wrapTagList(tagList)
|
||||
}
|
||||
|
||||
func (t *gstTagSetter) AddTagValue(mergeMode TagMergeMode, tagKey string, tagValue interface{}) {
|
||||
ckey := C.CString(tagKey)
|
||||
func (t *gstTagSetter) AddTagValue(mergeMode TagMergeMode, tagKey Tag, tagValue interface{}) {
|
||||
ckey := C.CString(string(tagKey))
|
||||
defer C.free(unsafe.Pointer(ckey))
|
||||
gVal, err := glib.GValue(tagValue)
|
||||
if err != nil {
|
||||
|
@@ -2,6 +2,11 @@ package gst
|
||||
|
||||
// #include "gst.go.h"
|
||||
import "C"
|
||||
import "github.com/gotk3/gotk3/glib"
|
||||
|
||||
// InterfaceTOCSetter represents the GstTocSetter interface GType. Use this when querying bins
|
||||
// for elements that implement a TOCSetter.
|
||||
var InterfaceTOCSetter = glib.Type(C.GST_TYPE_TOC_SETTER)
|
||||
|
||||
// TOCSetter is an interface that elements can implement to provide TOC writing capabilities.
|
||||
type TOCSetter interface {
|
||||
|
76
gst/gst_uri_handler.go
Normal file
76
gst/gst_uri_handler.go
Normal file
@@ -0,0 +1,76 @@
|
||||
package gst
|
||||
|
||||
// #include "gst.go.h"
|
||||
import "C"
|
||||
import (
|
||||
"errors"
|
||||
"unsafe"
|
||||
|
||||
"github.com/gotk3/gotk3/glib"
|
||||
)
|
||||
|
||||
// InterfaceURIHandler represents the GstURIHandler interface GType. Use this when querying bins
|
||||
// for elements that implement a URIHandler.
|
||||
var InterfaceURIHandler = glib.Type(C.GST_TYPE_URI_HANDLER)
|
||||
|
||||
// URIHandler represents an interface that elements can implement to provide URI handling
|
||||
// capabilities.
|
||||
type URIHandler interface {
|
||||
// GetURI gets the currently handled URI.
|
||||
GetURI() string
|
||||
// GetURIType returns the type of URI this element can handle.
|
||||
GetURIType() URIType
|
||||
// GetURIProtocols returns the protocols this element can handle.
|
||||
GetURIProtocols() []string
|
||||
// SetURI tries to set the URI of the given handler.
|
||||
SetURI(string) (bool, error)
|
||||
}
|
||||
|
||||
// gstURIHandler implements a URIHandler that is backed by an Element from the C runtime.
|
||||
type gstURIHandler struct {
|
||||
ptr *C.GstElement
|
||||
}
|
||||
|
||||
func (g *gstURIHandler) Instance() *C.GstURIHandler {
|
||||
return C.toGstURIHandler(unsafe.Pointer(g.ptr))
|
||||
}
|
||||
|
||||
// GetURI gets the currently handled URI.
|
||||
func (g *gstURIHandler) GetURI() string {
|
||||
ret := C.gst_uri_handler_get_uri(g.Instance())
|
||||
defer C.g_free((C.gpointer)(unsafe.Pointer(ret)))
|
||||
return C.GoString(ret)
|
||||
}
|
||||
|
||||
// GetURIType returns the type of URI this element can handle.
|
||||
func (g *gstURIHandler) GetURIType() URIType {
|
||||
ty := C.gst_uri_handler_get_uri_type((*C.GstURIHandler)(g.Instance()))
|
||||
return URIType(ty)
|
||||
}
|
||||
|
||||
// GetURIProtocols returns the protocols this element can handle.
|
||||
func (g *gstURIHandler) GetURIProtocols() []string {
|
||||
protocols := C.gst_uri_handler_get_protocols((*C.GstURIHandler)(g.Instance()))
|
||||
if protocols == nil {
|
||||
return nil
|
||||
}
|
||||
size := C.sizeOfGCharArray(protocols)
|
||||
return goStrings(size, protocols)
|
||||
}
|
||||
|
||||
// SetURI tries to set the URI of the given handler.
|
||||
func (g *gstURIHandler) SetURI(uri string) (bool, error) {
|
||||
curi := C.CString(uri)
|
||||
defer C.free(unsafe.Pointer(curi))
|
||||
var gerr *C.GError
|
||||
ret := C.gst_uri_handler_set_uri(
|
||||
g.Instance(),
|
||||
(*C.gchar)(unsafe.Pointer(curi)),
|
||||
&gerr,
|
||||
)
|
||||
if gerr != nil {
|
||||
defer C.g_error_free(gerr)
|
||||
return gobool(ret), errors.New(C.GoString(gerr.message))
|
||||
}
|
||||
return gobool(ret), nil
|
||||
}
|
Reference in New Issue
Block a user