mirror of
https://github.com/go-gst/go-gst.git
synced 2025-10-05 16:06:55 +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()
|
fmt.Println()
|
||||||
}
|
}
|
||||||
|
|
||||||
colorOrange.print("URI handling capabilities:\n")
|
uriHandler := elem.URIHandler()
|
||||||
colorLightGray.printfIndent(2, "Element can act as %s.\n", strings.ToLower(elem.GetURIType().String()))
|
|
||||||
|
|
||||||
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 {
|
if len(protos) == 0 {
|
||||||
fmt.Println()
|
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
|
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
|
// TOCLoopType represents a GstTocLoopType
|
||||||
type TOCLoopType int
|
type TOCLoopType int
|
||||||
|
|
||||||
|
@@ -91,6 +91,26 @@ func (b *Bin) GetElementsSorted() ([]*Element, error) {
|
|||||||
return iteratorToElementSlice(iterator)
|
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
|
// // GetElementsByFactoryName returns a list of the elements in this bin created from the given factory
|
||||||
// // name.
|
// // name.
|
||||||
// func (b *Bin) GetElementsByFactoryName(name string) ([]*Element, error) {
|
// func (b *Bin) GetElementsByFactoryName(name string) ([]*Element, error) {
|
||||||
|
@@ -174,30 +174,14 @@ func (e *Element) IsURIHandler() bool {
|
|||||||
return gobool(C.gstElementIsURIHandler(e.Instance()))
|
return gobool(C.gstElementIsURIHandler(e.Instance()))
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Go back over URI and implement as interface
|
// URIHandler returns a URIHandler interface if implemented by this element. Otherwise it
|
||||||
|
// returns nil. Currently this only supports elements built through this package, however,
|
||||||
func (e *Element) uriHandler() *C.GstURIHandler { return C.toGstURIHandler(e.Unsafe()) }
|
// inner application elements could still use the interface as a reference implementation.
|
||||||
|
func (e *Element) URIHandler() URIHandler {
|
||||||
// GetURIType returns the type of URI this element can handle.
|
if C.toGstURIHandler(e.Unsafe()) == nil {
|
||||||
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
|
return nil
|
||||||
}
|
}
|
||||||
protocols := C.gst_uri_handler_get_protocols((*C.GstURIHandler)(e.uriHandler()))
|
return &gstURIHandler{ptr: e.Instance()}
|
||||||
if protocols == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
size := C.sizeOfGCharArray(protocols)
|
|
||||||
return goStrings(size, protocols)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TOCSetter returns a TOCSetter interface if implemented by this element. Otherwise it
|
// 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.
|
// ParseSelectStreams parses the SELECT_STREAMS event and retrieve the contained streams.
|
||||||
func (e *Event) ParseSelectStreams() []*Stream {
|
func (e *Event) ParseSelectStreams() []*Stream {
|
||||||
outList := &C.GList{}
|
var outList *C.GList
|
||||||
C.gst_event_parse_select_streams(e.Instance(), &outList)
|
C.gst_event_parse_select_streams(e.Instance(), &outList)
|
||||||
return glistToStreamSlice(outList)
|
return glistToStreamSlice(outList)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseSinkMessage parses the sink-message event. Unref msg after usage.
|
// ParseSinkMessage parses the sink-message event. Unref msg after usage.
|
||||||
func (e *Event) ParseSinkMessage() *Message {
|
func (e *Event) ParseSinkMessage() *Message {
|
||||||
msg := &C.GstMessage{}
|
var msg *C.GstMessage
|
||||||
C.gst_event_parse_sink_message(e.Instance(), &msg)
|
C.gst_event_parse_sink_message(e.Instance(), &msg)
|
||||||
return wrapMessage(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.
|
// ParseStream parses a stream-start event and extract the GstStream from it.
|
||||||
func (e *Event) ParseStream() *Stream {
|
func (e *Event) ParseStream() *Stream {
|
||||||
stream := &C.GstStream{}
|
var stream *C.GstStream
|
||||||
C.gst_event_parse_stream(e.Instance(), &stream)
|
C.gst_event_parse_stream(e.Instance(), &stream)
|
||||||
return wrapStream(&glib.Object{GObject: glib.ToGObject(unsafe.Pointer(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
|
// ParseTag parses a tag event and stores the results in the given taglist location. Do not modify or free the returned
|
||||||
// tag list.
|
// tag list.
|
||||||
func (e *Event) ParseTag() *TagList {
|
func (e *Event) ParseTag() *TagList {
|
||||||
out := &C.GstTagList{}
|
var out *C.GstTagList
|
||||||
C.gst_event_parse_tag(e.Instance(), &out)
|
C.gst_event_parse_tag(e.Instance(), &out)
|
||||||
return wrapTagList(out)
|
return wrapTagList(out)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseTOC parses a TOC event and store the results in the given toc and updated locations.
|
// ParseTOC parses a TOC event and store the results in the given toc and updated locations.
|
||||||
func (e *Event) ParseTOC() (toc *TOC, updated bool) {
|
func (e *Event) ParseTOC() (toc *TOC, updated bool) {
|
||||||
out := &C.GstToc{}
|
var out *C.GstToc
|
||||||
var gupdated C.gboolean
|
var gupdated C.gboolean
|
||||||
C.gst_event_parse_toc(e.Instance(), &out, &gupdated)
|
C.gst_event_parse_toc(e.Instance(), &out, &gupdated)
|
||||||
return wrapTOC(out), gobool(gupdated)
|
return wrapTOC(out), gobool(gupdated)
|
||||||
|
@@ -144,6 +144,15 @@ func (m *Message) ParseTags() *TagList {
|
|||||||
return wrapTagList(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
|
// ParseStreamStatus parses the stream status type of the message as well as the element
|
||||||
// that produced it. The element returned should NOT be unrefed.
|
// that produced it. The element returned should NOT be unrefed.
|
||||||
func (m *Message) ParseStreamStatus() (StreamStatusType, *Element) {
|
func (m *Message) ParseStreamStatus() (StreamStatusType, *Element) {
|
||||||
|
@@ -8,13 +8,17 @@ import (
|
|||||||
"github.com/gotk3/gotk3/glib"
|
"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.
|
// TagSetter is an interface that elements can implement to provide Tag writing capabilities.
|
||||||
type TagSetter interface {
|
type TagSetter interface {
|
||||||
// Returns the current list of tags the setter uses. The list should not be modified or freed.
|
// Returns the current list of tags the setter uses. The list should not be modified or freed.
|
||||||
GetTagList() *TagList
|
GetTagList() *TagList
|
||||||
// Adds the given tag/value pair using the given merge mode. If the tag value cannot be coerced
|
// 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.
|
// 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
|
// Merges a tag list with the given merge mode
|
||||||
MergeTags(*TagList, TagMergeMode)
|
MergeTags(*TagList, TagMergeMode)
|
||||||
// Resets the internal tag list. Elements should call this from within the state-change handler.
|
// 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)
|
return wrapTagList(tagList)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *gstTagSetter) AddTagValue(mergeMode TagMergeMode, tagKey string, tagValue interface{}) {
|
func (t *gstTagSetter) AddTagValue(mergeMode TagMergeMode, tagKey Tag, tagValue interface{}) {
|
||||||
ckey := C.CString(tagKey)
|
ckey := C.CString(string(tagKey))
|
||||||
defer C.free(unsafe.Pointer(ckey))
|
defer C.free(unsafe.Pointer(ckey))
|
||||||
gVal, err := glib.GValue(tagValue)
|
gVal, err := glib.GValue(tagValue)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@@ -2,6 +2,11 @@ package gst
|
|||||||
|
|
||||||
// #include "gst.go.h"
|
// #include "gst.go.h"
|
||||||
import "C"
|
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.
|
// TOCSetter is an interface that elements can implement to provide TOC writing capabilities.
|
||||||
type TOCSetter interface {
|
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