finish GstTagList, GstToc, setters, and add auto go type conversion for functions taking gvalues

This commit is contained in:
tinyzimmer
2020-10-02 10:38:17 +03:00
parent 0d0a974156
commit e586f0262e
9 changed files with 639 additions and 28 deletions

View File

@@ -4,6 +4,8 @@ package gst
import "C"
import (
"fmt"
"time"
"unsafe"
)
@@ -20,6 +22,37 @@ func gboolean(b bool) C.gboolean {
return C.gboolean(0)
}
// gdateToTime converts a GDate to a time object.
func gdateToTime(gdate *C.GDate) time.Time {
tm := time.Time{}
tm.AddDate(int(C.g_date_get_year(gdate)), int(C.g_date_get_month(gdate)), int(C.g_date_get_day(gdate)))
return tm
}
// gstDateTimeToTime converts a GstDateTime to a time object. If the datetime object could not be parsed,
// an empty time object is returned.
func gstDateTimeToTime(gstdatetime *C.GstDateTime) time.Time {
dateStr := fmt.Sprintf(
"%s %s %d:%d:%d %s %d",
time.Weekday(C.gst_date_time_get_day(gstdatetime)).String(),
time.Month(C.gst_date_time_get_month(gstdatetime)).String(),
int(C.gst_date_time_get_hour(gstdatetime)),
int(C.gst_date_time_get_minute(gstdatetime)),
int(C.gst_date_time_get_second(gstdatetime)),
formatOffset(C.gst_date_time_get_time_zone_offset(gstdatetime)),
int(C.gst_date_time_get_year(gstdatetime)),
)
tm, _ := time.Parse("Mon Jan 2 15:04:05 -0700 2006", dateStr)
return tm
}
func formatOffset(offset C.gfloat) string {
if offset < 0 {
return fmt.Sprintf("-0%d00", int(offset))
}
return fmt.Sprintf("+0%d00", int(offset))
}
// goStrings returns a string slice for an array of size argc starting at the address argv.
func goStrings(argc C.int, argv **C.gchar) []string {
length := int(argc)

View File

@@ -13,6 +13,15 @@ import (
gopointer "github.com/mattn/go-pointer"
)
//export goTagForEachFunc
func goTagForEachFunc(tagList *C.GstTagList, tag *C.gchar, userData C.gpointer) {
cbIface := gopointer.Restore(unsafe.Pointer(userData))
cbFunc := cbIface.(TagListForEachFunc)
cbFunc(wrapTagList(tagList), Tag(C.GoString(tag)))
}
// func goTagMergeFunc(dest, src *C.GValue) {}
//export goBufferListForEachCb
func goBufferListForEachCb(buf **C.GstBuffer, idx C.guint, userData C.gpointer) C.gboolean {
cbIface := gopointer.Restore(unsafe.Pointer(userData))

View File

@@ -35,6 +35,7 @@ inline GstSample * toGstSample (void *p) { return (GST_SAM
inline GstStreamCollection * toGstStreamCollection (void *p) { return (GST_STREAM_COLLECTION_CAST(p)); }
inline GstStream * toGstStream (void *p) { return (GST_STREAM_CAST(p)); }
inline GstStructure * toGstStructure (void *p) { return (GST_STRUCTURE(p)); }
inline GstTagList * toGstTagList (void *p) { return (GST_TAG_LIST(p)); }
inline GstURIHandler * toGstURIHandler (void *p) { return (GST_URI_HANDLER(p)); }
inline GstUri * toGstURI (void *p) { return (GST_URI(p)); }
@@ -126,6 +127,11 @@ inline GstToc * makeTocWritable (GstToc * toc) { return
inline GstToc * tocRef (GstToc * toc) { return gst_toc_ref(toc); }
inline void tocUnref (GstToc * toc) { gst_toc_unref(toc); }
/* TagList utilities */
inline gboolean tagListIsWritable (GstTagList * tagList) { return gst_tag_list_is_writable(tagList); }
inline GstTagList * makeTagListWritable (GstTagList * tagList) { return gst_tag_list_make_writable(tagList); }
/* Object Utilities */
inline GObjectClass * getGObjectClass (void * p) { return (G_OBJECT_GET_CLASS(p)); }

View File

@@ -392,12 +392,17 @@ func (c *Caps) SetFeaturesSimple(features *CapsFeatures) {
}
// SetValue sets the given field on all structures of caps to the given value. This is a convenience
// function for calling SetValue on all structures of caps.
func (c *Caps) SetValue(field string, val *glib.Value) {
// function for calling SetValue on all structures of caps. If the value cannot be coerced to a C type,
// then nothing will happen.
func (c *Caps) SetValue(field string, val interface{}) {
gVal, err := glib.GValue(val)
if err != nil {
return
}
C.gst_caps_set_value(
c.Instance(),
(*C.gchar)(unsafe.Pointer(C.CString(field))),
(*C.GValue)(val.GetPointer()),
(*C.GValue)(gVal.Native()),
)
}

View File

@@ -288,17 +288,22 @@ func NewProgressMessage(src interface{}, progressType ProgressType, code, text s
return wrapMessage(C.gst_message_new_progress(srcObj, C.GstProgressType(progressType), cCode, cText))
}
// NewPropertyNotifyMessage creates a new message notifying an object's properties have changed.
func NewPropertyNotifyMessage(src interface{}, propName string, val *glib.Value) *Message {
// NewPropertyNotifyMessage creates a new message notifying an object's properties have changed. If the
// source OR the value cannot be coereced to C types, the function will return nil.
func NewPropertyNotifyMessage(src interface{}, propName string, val interface{}) *Message {
srcObj := getMessageSourceObj(src)
if srcObj == nil {
return nil
}
gVal, err := glib.GValue(val)
if err != nil {
return nil
}
cName := (*C.gchar)(unsafe.Pointer(C.CString(propName)))
return wrapMessage(C.gst_message_new_property_notify(
srcObj,
cName,
(*C.GValue)(val.GetPointer()),
(*C.GValue)(gVal.Native()),
))
}

View File

@@ -87,7 +87,7 @@ func (s *Structure) SetValue(key string, value interface{}) error {
}
cKey := C.CString(key)
defer C.free(unsafe.Pointer(cKey))
C.gst_structure_set_value(s.Instance(), cKey, (*C.GValue)(gVal.GetPointer()))
C.gst_structure_set_value(s.Instance(), cKey, (*C.GValue)(unsafe.Pointer(gVal.GValue)))
return nil
}

View File

@@ -1,9 +1,25 @@
package gst
// #include "gst.go.h"
/*
#include "gst.go.h"
extern void goTagForEachFunc (const GstTagList * tagList, const gchar * tag, gpointer user_data);
void cgoTagForEachFunc (const GstTagList * tagList, const gchar * tag, gpointer user_data)
{
goTagForEachFunc(tagList, tag, user_data);
}
*/
import "C"
import "unsafe"
import (
"time"
"unsafe"
"github.com/gotk3/gotk3/glib"
gopointer "github.com/mattn/go-pointer"
)
// TagList is a go wrapper around a GstTagList. For now, until the rest of the methods are
// implemnented, this struct is primarily used for retrieving serialized copies of the tags.
@@ -11,8 +27,30 @@ type TagList struct {
ptr *C.GstTagList
}
// NewEmptyTagList returns a new empty tag list.
//
// tagList := gst.NewEmptyTagList()
// fmt.Println(tagList.IsEmpty())
// // true
//
func NewEmptyTagList() *TagList {
return wrapTagList(C.gst_tag_list_new_empty())
}
// NewTagListFromString creates a new tag list from the given string. This is the same format produced
// by the stringer interface on the TagList.
func NewTagListFromString(tags string) *TagList {
ctags := C.CString(tags)
defer C.free(unsafe.Pointer(ctags))
tagList := C.gst_tag_list_new_from_string((*C.gchar)(unsafe.Pointer(ctags)))
if tagList == nil {
return nil
}
return wrapTagList(tagList)
}
// Instance returns the underlying GstTagList instance.
func (t *TagList) Instance() *C.GstTagList { return t.ptr }
func (t *TagList) Instance() *C.GstTagList { return C.toGstTagList(unsafe.Pointer(t.ptr)) }
// String implements a stringer on the TagList and serializes it to a string.
func (t *TagList) String() string { return C.GoString(C.gst_tag_list_to_string(t.Instance())) }
@@ -24,17 +62,522 @@ func (t *TagList) Ref() *TagList { return wrapTagList(C.gst_tag_list_ref(t.Insta
// is destroyed.
func (t *TagList) Unref() { C.gst_tag_list_unref(t.Instance()) }
// Size returns the number of key/value pairs in ths TagList
func (t *TagList) Size() int { return int(C.gst_tag_list_n_tags(t.Instance())) }
// AddValue adds a value to a given tag using the given merge mode. If the value provided
// cannot be coerced to a GValue, nothing will happen.
//
// tagList := gst.NewEmptyTagList()
// tagList.AddValue(gst.TagMergeAppend, gst.TagAlbum, "MyNewAlbum")
// myAlbum, _ := tagList.GetString(gst.TagAlbum)
// fmt.Println(myAlbum)
// // MyNewAlbum
//
func (t *TagList) AddValue(mergeMode TagMergeMode, tag Tag, value interface{}) {
ctag := C.CString(string(tag))
defer C.free(unsafe.Pointer(ctag))
gVal, err := glib.GValue(value)
if err != nil {
return
}
C.gst_tag_list_add_value(
t.Instance(),
C.GstTagMergeMode(mergeMode),
(*C.gchar)(ctag),
(*C.GValue)(gVal.Native()),
)
}
// AddValues can be used to add multiple values to a tag with the given merge mode.
// Values that cannot be coerced to C types will be ignored.
func (t *TagList) AddValues(mergeMode TagMergeMode, tag Tag, vals ...interface{}) {
for _, val := range vals {
t.AddValue(mergeMode, tag, val)
}
}
// Copy creates a new TagList as a copy of the old taglist. The new taglist will have a refcount of 1,
// owned by the caller, and will be writable as a result.
//
// Note that this function is the semantic equivalent of a Ref followed by a MakeWritable. If you only want
// to hold on to a reference to the data, you should use Ref.
//
// When you are finished with the taglist, call Unref on it.
func (t *TagList) Copy() *TagList { return wrapTagList(C.gst_tag_list_copy(t.Instance())) }
// TagListForEachFunc is a function that will be called in ForEach. The function may not modify the tag list.
type TagListForEachFunc func(tagList *TagList, tag Tag)
// ForEach calls the given function for each tag inside the tag list. Note that if there is no tag,
// the function won't be called at all.
//
// tagList := gst.NewEmptyTagList()
//
// tagList.AddValue(gst.TagMergeAppend, gst.TagAlbumArtist, "tinyzimmer")
// tagList.AddValue(gst.TagMergeAppend, gst.TagAlbum, "GstreamerInGo")
//
// tagList.ForEach(func(_ *gst.TagList, tag gst.Tag) {
// val, _ := tagList.GetString(tag)
// fmt.Println(tag, ":", val)
// })
//
// // album-artist : tinyzimmer
// // album : GstreamerInGo
//
func (t *TagList) ForEach(f TagListForEachFunc) {
ptr := gopointer.Save(f)
defer gopointer.Unref(ptr)
C.gst_tag_list_foreach(
t.Instance(),
C.GstTagForeachFunc(C.cgoTagForEachFunc),
(C.gpointer)(ptr),
)
}
// GetBool returns the boolean value at the given tag key. If multiple values are associated with the tag they
// are merged.
func (t *TagList) GetBool(tag Tag) (value, ok bool) {
ctag := C.CString(string(tag))
defer C.free(unsafe.Pointer(ctag))
var gout C.gboolean
gok := C.gst_tag_list_get_boolean(
t.Instance(),
(*C.gchar)(unsafe.Pointer(ctag)),
&gout,
)
return gobool(gout), gobool(gok)
}
// GetBoolIndex retrieves the bool at the given index in the tag key.
func (t *TagList) GetBoolIndex(tag Tag, idx uint) (value, ok bool) {
ctag := C.CString(string(tag))
defer C.free(unsafe.Pointer(ctag))
var gout C.gboolean
gok := C.gst_tag_list_get_boolean_index(
t.Instance(),
(*C.gchar)(unsafe.Pointer(ctag)),
C.guint(idx),
&gout,
)
return gobool(gout), gobool(gok)
}
// GetDate returns the date stored at the given tag key. If there are multiple values, the first one
// is returned.
func (t *TagList) GetDate(tag Tag) (value time.Time, ok bool) {
ctag := C.CString(string(tag))
defer C.free(unsafe.Pointer(ctag))
var gout *C.GDate
gok := C.gst_tag_list_get_date(
t.Instance(),
(*C.gchar)(unsafe.Pointer(ctag)),
&gout,
)
if gobool(gok) {
defer C.g_date_free(gout)
return gdateToTime(gout), true
}
return time.Time{}, false
}
// GetDateIndex returns the date stored at the given index in tag key.
func (t *TagList) GetDateIndex(tag Tag, idx uint) (value time.Time, ok bool) {
ctag := C.CString(string(tag))
defer C.free(unsafe.Pointer(ctag))
var gout *C.GDate
gok := C.gst_tag_list_get_date_index(
t.Instance(),
(*C.gchar)(unsafe.Pointer(ctag)),
C.guint(idx),
&gout,
)
if gobool(gok) {
defer C.g_date_free(gout)
return gdateToTime(gout), true
}
return time.Time{}, false
}
// GetDateTime returns the date and time stored at the given tag key. If there are multiple values, the first one
// is returned.
func (t *TagList) GetDateTime(tag Tag) (value time.Time, ok bool) {
ctag := C.CString(string(tag))
defer C.free(unsafe.Pointer(ctag))
var gout *C.GstDateTime
gok := C.gst_tag_list_get_date_time(
t.Instance(),
(*C.gchar)(unsafe.Pointer(ctag)),
&gout,
)
if gobool(gok) {
defer C.gst_date_time_unref(gout)
return gstDateTimeToTime(gout), true
}
return time.Time{}, false
}
// GetDateTimeIndex returns the date and time stored at the given tag key at the given index.
func (t *TagList) GetDateTimeIndex(tag Tag, idx uint) (value time.Time, ok bool) {
ctag := C.CString(string(tag))
defer C.free(unsafe.Pointer(ctag))
var gout *C.GstDateTime
gok := C.gst_tag_list_get_date_time_index(
t.Instance(),
(*C.gchar)(unsafe.Pointer(ctag)),
C.guint(idx),
&gout,
)
if gobool(gok) {
defer C.gst_date_time_unref(gout)
return gstDateTimeToTime(gout), true
}
return time.Time{}, false
}
// GetFloat64 returns the float at the given tag key, merging multiple values into one if multiple values
// are associated with the tag. This is the equivalent of a C double stored in the tag.
func (t *TagList) GetFloat64(tag Tag) (value float64, ok bool) {
ctag := C.CString(string(tag))
defer C.free(unsafe.Pointer(ctag))
var gout C.gdouble
gok := C.gst_tag_list_get_double(
t.Instance(),
(*C.gchar)(unsafe.Pointer(ctag)),
&gout,
)
return float64(gout), gobool(gok)
}
// GetFloat64Index returns the float at the index of the given tag key.
func (t *TagList) GetFloat64Index(tag Tag, idx uint) (value float64, ok bool) {
ctag := C.CString(string(tag))
defer C.free(unsafe.Pointer(ctag))
var gout C.gdouble
gok := C.gst_tag_list_get_double_index(
t.Instance(),
(*C.gchar)(unsafe.Pointer(ctag)),
C.uint(idx),
&gout,
)
return float64(gout), gobool(gok)
}
// GetFloat32 returns the float at the given tag key, merging multiple values into one if multiple values
// are associated with the tag.
func (t *TagList) GetFloat32(tag Tag) (value float32, ok bool) {
ctag := C.CString(string(tag))
defer C.free(unsafe.Pointer(ctag))
var gout C.gfloat
gok := C.gst_tag_list_get_float(
t.Instance(),
(*C.gchar)(unsafe.Pointer(ctag)),
&gout,
)
return float32(gout), gobool(gok)
}
// GetFloat32Index returns the float at the index of the given tag key.
func (t *TagList) GetFloat32Index(tag Tag, idx uint) (value float32, ok bool) {
ctag := C.CString(string(tag))
defer C.free(unsafe.Pointer(ctag))
var gout C.gfloat
gok := C.gst_tag_list_get_float_index(
t.Instance(),
(*C.gchar)(unsafe.Pointer(ctag)),
C.uint(idx),
&gout,
)
return float32(gout), gobool(gok)
}
// GetInt32 returns the integer at the given tag key, merging multiple values into one if multiple values
// are associated with the tag.
func (t *TagList) GetInt32(tag Tag) (value int32, ok bool) {
ctag := C.CString(string(tag))
defer C.free(unsafe.Pointer(ctag))
var gout C.gint
gok := C.gst_tag_list_get_int(
t.Instance(),
(*C.gchar)(unsafe.Pointer(ctag)),
&gout,
)
return int32(gout), gobool(gok)
}
// GetInt32Index returns the integer at the index of the given tag key.
func (t *TagList) GetInt32Index(tag Tag, idx uint) (value int32, ok bool) {
ctag := C.CString(string(tag))
defer C.free(unsafe.Pointer(ctag))
var gout C.gint
gok := C.gst_tag_list_get_int_index(
t.Instance(),
(*C.gchar)(unsafe.Pointer(ctag)),
C.uint(idx),
&gout,
)
return int32(gout), gobool(gok)
}
// GetInt64 returns the integer at the given tag key, merging multiple values into one if multiple values
// are associated with the tag.
func (t *TagList) GetInt64(tag Tag) (value int64, ok bool) {
ctag := C.CString(string(tag))
defer C.free(unsafe.Pointer(ctag))
var gout C.gint64
gok := C.gst_tag_list_get_int64(
t.Instance(),
(*C.gchar)(unsafe.Pointer(ctag)),
&gout,
)
return int64(gout), gobool(gok)
}
// GetInt64Index returns the integer at the index of the given tag key.
func (t *TagList) GetInt64Index(tag Tag, idx uint) (value int64, ok bool) {
ctag := C.CString(string(tag))
defer C.free(unsafe.Pointer(ctag))
var gout C.gint64
gok := C.gst_tag_list_get_int64_index(
t.Instance(),
(*C.gchar)(unsafe.Pointer(ctag)),
C.uint(idx),
&gout,
)
return int64(gout), gobool(gok)
}
// GetPointer returns the C pointer stored at the given tag key, merging values if there are multiple.
func (t *TagList) GetPointer(tag Tag) (value unsafe.Pointer, ok bool) {
ctag := C.CString(string(tag))
defer C.free(unsafe.Pointer(ctag))
var gout C.gpointer
gok := C.gst_tag_list_get_pointer(
t.Instance(),
(*C.gchar)(unsafe.Pointer(ctag)),
&gout,
)
return unsafe.Pointer(gout), gobool(gok)
}
// GetPointerIndex returns the C pointer stored at the given tag key index.
func (t *TagList) GetPointerIndex(tag Tag, idx uint) (value unsafe.Pointer, ok bool) {
ctag := C.CString(string(tag))
defer C.free(unsafe.Pointer(ctag))
var gout C.gpointer
gok := C.gst_tag_list_get_pointer_index(
t.Instance(),
(*C.gchar)(unsafe.Pointer(ctag)),
C.guint(idx),
&gout,
)
return unsafe.Pointer(gout), gobool(gok)
}
// GetSample copies the first sample for the given tag in the taglist. Free the sample with Unref when it
// is no longer needed.
func (t *TagList) GetSample(tag Tag) (value *Sample, ok bool) {
ctag := C.CString(string(tag))
defer C.free(unsafe.Pointer(ctag))
var gout *C.GstSample
gok := C.gst_tag_list_get_sample(
t.Instance(),
(*C.gchar)(unsafe.Pointer(ctag)),
&gout,
)
if gobool(gok) {
return wrapSample(gout), true
}
return nil, false
}
// GetSampleIndex copies the sample for the given index in tag in the taglist. Free the sample with Unref
// when it is no longer needed.
func (t *TagList) GetSampleIndex(tag Tag, idx uint) (value *Sample, ok bool) {
ctag := C.CString(string(tag))
defer C.free(unsafe.Pointer(ctag))
var gout *C.GstSample
gok := C.gst_tag_list_get_sample_index(
t.Instance(),
(*C.gchar)(unsafe.Pointer(ctag)),
C.guint(idx),
&gout,
)
if gobool(gok) {
return wrapSample(gout), true
}
return nil, false
}
// GetString returns the string for the given tag, possibly merging multiple values into one.
func (t *TagList) GetString(tag Tag) (value string, ok bool) {
ctag := C.CString(string(tag))
defer C.free(unsafe.Pointer(ctag))
var gout *C.gchar
gok := C.gst_tag_list_get_string(
t.Instance(),
(*C.gchar)(unsafe.Pointer(ctag)),
&gout,
)
defer C.g_free((C.gpointer)(unsafe.Pointer(gout)))
return C.GoString(gout), gobool(gok)
}
// GetStringIndex returns the string for the given index in tag.
func (t *TagList) GetStringIndex(tag Tag, idx uint) (value string, ok bool) {
ctag := C.CString(string(tag))
defer C.free(unsafe.Pointer(ctag))
var gout *C.gchar
gok := C.gst_tag_list_get_string_index(
t.Instance(),
(*C.gchar)(unsafe.Pointer(ctag)),
C.guint(idx),
&gout,
)
defer C.g_free((C.gpointer)(unsafe.Pointer(gout)))
return C.GoString(gout), gobool(gok)
}
// GetUint32 returns the unsigned integer at the given tag key, merging multiple values into one if multiple values
// are associated with the tag.
func (t *TagList) GetUint32(tag Tag) (value uint32, ok bool) {
ctag := C.CString(string(tag))
defer C.free(unsafe.Pointer(ctag))
var gout C.guint
gok := C.gst_tag_list_get_uint(
t.Instance(),
(*C.gchar)(unsafe.Pointer(ctag)),
&gout,
)
return uint32(gout), gobool(gok)
}
// GetUint32Index returns the unsigned integer at the index of the given tag key.
func (t *TagList) GetUint32Index(tag Tag, idx uint) (value uint32, ok bool) {
ctag := C.CString(string(tag))
defer C.free(unsafe.Pointer(ctag))
var gout C.guint
gok := C.gst_tag_list_get_uint_index(
t.Instance(),
(*C.gchar)(unsafe.Pointer(ctag)),
C.uint(idx),
&gout,
)
return uint32(gout), gobool(gok)
}
// GetUint64 returns the unsigned integer at the given tag key, merging multiple values into one if multiple values
// are associated with the tag.
func (t *TagList) GetUint64(tag Tag) (value uint64, ok bool) {
ctag := C.CString(string(tag))
defer C.free(unsafe.Pointer(ctag))
var gout C.guint64
gok := C.gst_tag_list_get_uint64(
t.Instance(),
(*C.gchar)(unsafe.Pointer(ctag)),
&gout,
)
return uint64(gout), gobool(gok)
}
// GetUint64Index returns the unsigned integer at the index of the given tag key.
func (t *TagList) GetUint64Index(tag Tag, idx uint) (value uint64, ok bool) {
ctag := C.CString(string(tag))
defer C.free(unsafe.Pointer(ctag))
var gout C.guint64
gok := C.gst_tag_list_get_uint64_index(
t.Instance(),
(*C.gchar)(unsafe.Pointer(ctag)),
C.uint(idx),
&gout,
)
return uint64(gout), gobool(gok)
}
// GetValueIndex retrieves the GValue at the given index in tag, or nil if none exists.
// Note that this function can also return nil if the stored value cannot be cleanly coerced
// to a go type. It is safer to use the other functions provided when you know the expected
// return type.
func (t *TagList) GetValueIndex(tag Tag, idx uint) interface{} {
ctag := C.CString(string(tag))
defer C.free(unsafe.Pointer(ctag))
gval := C.gst_tag_list_get_value_index(t.Instance(), (*C.gchar)(unsafe.Pointer(ctag)), C.guint(idx))
if gval == nil {
return nil
}
val := glib.ValueFromNative(unsafe.Pointer(gval))
iface, _ := val.GoValue()
return iface
}
// GetScope returns the scope for this TagList.
func (t *TagList) GetScope() TagScope { return TagScope(C.gst_tag_list_get_scope(t.Instance())) }
// GetTagSize returns the number of tag values at the given tag key.
func (t *TagList) GetTagSize(tagKey string) int {
cStr := C.CString(tagKey)
defer C.free(unsafe.Pointer(cStr))
return int(C.gst_tag_list_get_tag_size(t.Instance(), (*C.gchar)(cStr)))
}
// Insert inserts the tags from the provided list using the given merge mode.
func (t *TagList) Insert(tagList *TagList, mergeMode TagMergeMode) {
C.gst_tag_list_insert(t.Instance(), tagList.Instance(), C.GstTagMergeMode(mergeMode))
}
// IsEmpty returns true if this tag list is empty.
func (t *TagList) IsEmpty() bool { return gobool(C.gst_tag_list_is_empty(t.Instance())) }
// IsEqual checks if the two tag lists are equal.
func (t *TagList) IsEqual(tagList *TagList) bool {
return gobool(C.gst_tag_list_is_equal(t.Instance(), tagList.Instance()))
}
// IsWritable returns true if this TagList is writable.
func (t *TagList) IsWritable() bool { return gobool(C.tagListIsWritable(t.Instance())) }
// MakeWritable will return a writable copy of the tag list if it is not already so.
func (t *TagList) MakeWritable() *TagList {
return wrapTagList(C.makeTagListWritable(t.Instance()))
}
// Merge merges the two tag lists with the given mode.
func (t *TagList) Merge(tagList *TagList, mergeMode TagMergeMode) *TagList {
return wrapTagList(C.gst_tag_list_merge(
t.Instance(),
tagList.Instance(),
C.GstTagMergeMode(mergeMode),
))
}
// NumTags returns the number of key/value pairs in ths TagList
func (t *TagList) NumTags() int { return int(C.gst_tag_list_n_tags(t.Instance())) }
// TagNameAt returns the tag name at the given index.
func (t *TagList) TagNameAt(idx int) string {
return C.GoString(C.gst_tag_list_nth_tag_name(t.Instance(), C.guint(idx)))
}
// NumValuesAt returns the number of tag values at the given tag key.
func (t *TagList) NumValuesAt(tagKey string) int {
cStr := C.CString(tagKey)
defer C.free(unsafe.Pointer(cStr))
return int(C.gst_tag_list_get_tag_size(t.Instance(), (*C.gchar)(cStr)))
// PeekStringIndex peeks at the value that is at the given index for the given tag in the given list.
func (t *TagList) PeekStringIndex(tag Tag, idx uint) (value string, ok bool) {
ctag := C.CString(string(tag))
defer C.free(unsafe.Pointer(ctag))
var gout *C.gchar
gok := C.gst_tag_list_peek_string_index(
t.Instance(),
(*C.gchar)(unsafe.Pointer(ctag)),
C.guint(idx),
&gout,
)
defer C.g_free((C.gpointer)(unsafe.Pointer(gout)))
return C.GoString(gout), gobool(gok)
}
// RemoveTag removes the values for the given tag in this list.
func (t *TagList) RemoveTag(tag Tag) {
ctag := C.CString(string(tag))
defer C.free(unsafe.Pointer(ctag))
C.gst_tag_list_remove_tag(t.Instance(), (*C.gchar)(unsafe.Pointer(ctag)))
}
// SetScope sets the scope of this TagList. By default, the scope of a tag list is stream scope.
func (t *TagList) SetScope(scope TagScope) {
C.gst_tag_list_set_scope(t.Instance(), C.GstTagScope(scope))
}

View File

@@ -12,9 +12,9 @@ import (
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.
// TODO: Either an additional function or this one should be modified to accept go types.
AddTagValue(mergeMode TagMergeMode, tagKey string, tagValue *glib.Value)
// 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{})
// 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,14 +42,18 @@ func (t *gstTagSetter) GetTagList() *TagList {
return wrapTagList(tagList)
}
func (t *gstTagSetter) AddTagValue(mergeMode TagMergeMode, tagKey string, tagValue *glib.Value) {
func (t *gstTagSetter) AddTagValue(mergeMode TagMergeMode, tagKey string, tagValue interface{}) {
ckey := C.CString(tagKey)
defer C.free(unsafe.Pointer(ckey))
gVal, err := glib.GValue(tagValue)
if err != nil {
return
}
C.gst_tag_setter_add_tag_value(
t.Instance(),
C.GstTagMergeMode(mergeMode),
(*C.gchar)(unsafe.Pointer(ckey)),
(*C.GValue)(tagValue.GetPointer()),
(*C.GValue)(gVal.Native()),
)
}

View File

@@ -2,11 +2,6 @@ package gst
/*
#include "gst.go.h"
GValue * gvalPtrToGval (gpointer p)
{
return (GValue*)(p);
}
*/
import "C"
@@ -134,6 +129,10 @@ func init() {
T: glib.Type(C.GST_TYPE_TOC),
F: marshalTOC,
},
{
T: glib.Type(C.GST_TYPE_TAG_LIST),
F: marsalTagList,
},
// Boxed
{T: glib.Type(C.gst_message_get_type()), F: marshalMessage},
@@ -142,7 +141,8 @@ func init() {
}
func uintptrToGVal(p uintptr) *C.GValue {
return (*C.GValue)(unsafe.Pointer(p))
return (*C.GValue)(unsafe.Pointer(p)) // vet thinks this is unsafe and there is no way around it for now.
// but the given ptr is an address to a C object so go's concerns are misplaced.
}
// Object wrappers
@@ -372,3 +372,9 @@ func marshalTOCEntry(p uintptr) (interface{}, error) {
obj := (*C.GstTocEntry)(unsafe.Pointer(c))
return wrapTOCEntry(obj), nil
}
func marsalTagList(p uintptr) (interface{}, error) {
c := C.g_value_get_object(uintptrToGVal(p))
obj := (*C.GstTagList)(unsafe.Pointer(c))
return wrapTagList(obj), nil
}