major move of all glib specific bindings and extendable objects from go runtime to go-glib package

This commit is contained in:
Avi Zimmerman
2021-01-17 18:42:14 +02:00
parent d5306ebb3e
commit 56afdb35c0
61 changed files with 286 additions and 2614 deletions

View File

@@ -1,15 +1,15 @@
GO_VERSION ?= 1.15
DOCKER_IMAGE ?= ghcr.io/tinyzimmer/go-gst:$(GO_VERSION)
GOLANGCI_VERSION ?= 1.31.0
GOLANGCI_LINT ?= _bin/golangci-lint
GOLANGCI_DOWNLOAD_URL ?= https://github.com/golangci/golangci-lint/releases/download/v${GOLANGCI_VERSION}/golangci-lint-${GOLANGCI_VERSION}-$(shell uname | tr A-Z a-z)-amd64.tar.gz
GOPATH ?= $(shell go env GOPATH)
GOBIN ?= $(GOPATH)/bin
GOLANGCI_VERSION ?= v1.33.0
GOLANGCI_LINT ?= $(GOBIN)/golangci-lint
PLUGIN_GEN ?= "$(shell go env GOPATH)/bin/gst-plugin-gen"
$(GOLANGCI_LINT):
mkdir -p $(dir $(GOLANGCI_LINT))
cd $(dir $(GOLANGCI_LINT)) && curl -JL $(GOLANGCI_DOWNLOAD_URL) | tar xzf -
chmod +x $(dir $(GOLANGCI_LINT))golangci-lint-$(GOLANGCI_VERSION)-$(shell uname | tr A-Z a-z)-amd64/golangci-lint
ln -s golangci-lint-$(GOLANGCI_VERSION)-$(shell uname | tr A-Z a-z)-amd64/golangci-lint $(GOLANGCI_LINT)
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(GOBIN) $(GOLANGCI_VERSION)
lint: $(GOLANGCI_LINT)
$(GOLANGCI_LINT) run -v

View File

@@ -3,12 +3,12 @@ package examples
import (
"fmt"
"github.com/tinyzimmer/go-gst/gst"
"github.com/tinyzimmer/go-glib/glib"
)
// Run is used to wrap the given function in a main loop and print any error
func Run(f func() error) {
mainLoop := gst.NewMainLoop(gst.DefaultMainContext(), false)
mainLoop := glib.NewMainLoop(glib.MainContextDefault(), false)
defer mainLoop.Unref()
@@ -24,8 +24,8 @@ func Run(f func() error) {
// RunLoop is used to wrap the given function in a main loop and print any error.
// The main loop itself is passed to the function for more control over exiting.
func RunLoop(f func(*gst.MainLoop) error) {
mainLoop := gst.NewMainLoop(gst.DefaultMainContext(), false)
func RunLoop(f func(*glib.MainLoop) error) {
mainLoop := glib.NewMainLoop(glib.MainContextDefault(), false)
defer mainLoop.Unref()
if err := f(mainLoop); err != nil {

View File

@@ -6,6 +6,7 @@ import (
"fmt"
"time"
"github.com/tinyzimmer/go-glib/glib"
"github.com/tinyzimmer/go-gst/examples"
"github.com/tinyzimmer/go-gst/gst"
)
@@ -77,7 +78,7 @@ func createPipeline() (*gst.Pipeline, error) {
return pipeline, nil
}
func mainLoop(loop *gst.MainLoop, pipeline *gst.Pipeline) error {
func mainLoop(loop *glib.MainLoop, pipeline *gst.Pipeline) error {
// Create a watch on the pipeline to kill the main loop when EOS is received
pipeline.GetPipelineBus().AddWatch(func(msg *gst.Message) bool {
switch msg.Type() {
@@ -118,7 +119,7 @@ func mainLoop(loop *gst.MainLoop, pipeline *gst.Pipeline) error {
}
func main() {
examples.RunLoop(func(loop *gst.MainLoop) error {
examples.RunLoop(func(loop *glib.MainLoop) error {
var pipeline *gst.Pipeline
var err error
if pipeline, err = createPipeline(); err != nil {

View File

@@ -38,6 +38,7 @@ import (
"os"
"strings"
"github.com/tinyzimmer/go-glib/glib"
"github.com/tinyzimmer/go-gst/examples"
"github.com/tinyzimmer/go-gst/gst"
)
@@ -152,7 +153,7 @@ func buildPipeline() (*gst.Pipeline, error) {
return pipeline, nil
}
func runPipeline(loop *gst.MainLoop, pipeline *gst.Pipeline) error {
func runPipeline(loop *glib.MainLoop, pipeline *gst.Pipeline) error {
// Start the pipeline
pipeline.SetState(gst.StatePlaying)
// Stop and cleanup the pipeline when we exit
@@ -196,7 +197,7 @@ func main() {
flag.Usage()
os.Exit(1)
}
examples.RunLoop(func(loop *gst.MainLoop) error {
examples.RunLoop(func(loop *glib.MainLoop) error {
pipeline, err := buildPipeline()
if err != nil {
return err

View File

@@ -24,11 +24,12 @@ import (
"fmt"
"time"
"github.com/tinyzimmer/go-glib/glib"
"github.com/tinyzimmer/go-gst/examples"
"github.com/tinyzimmer/go-gst/gst"
)
func runPipeline(loop *gst.MainLoop) error {
func runPipeline(loop *glib.MainLoop) error {
gst.Init(nil)
// Build a pipeline with fake audio data going to a fakesink
@@ -109,7 +110,7 @@ func runPipeline(loop *gst.MainLoop) error {
}
func main() {
examples.RunLoop(func(loop *gst.MainLoop) error {
examples.RunLoop(func(loop *glib.MainLoop) error {
return runPipeline(loop)
})
}

View File

@@ -13,6 +13,7 @@ import (
"strings"
"time"
"github.com/tinyzimmer/go-glib/glib"
"github.com/tinyzimmer/go-gst/examples"
"github.com/tinyzimmer/go-gst/gst"
"github.com/tinyzimmer/go-gst/gst/app"
@@ -25,7 +26,7 @@ var outFile string
const width = 320
const height = 240
func encodeGif(mainLoop *gst.MainLoop) error {
func encodeGif(mainLoop *glib.MainLoop) error {
gst.Init(nil)
// Initialize an empty buffer for the encoded gif images.

View File

@@ -9,11 +9,12 @@ import (
"os"
"strings"
"github.com/tinyzimmer/go-glib/glib"
"github.com/tinyzimmer/go-gst/examples"
"github.com/tinyzimmer/go-gst/gst"
)
func runPipeline(mainLoop *gst.MainLoop) error {
func runPipeline(mainLoop *glib.MainLoop) error {
gst.Init(nil)
if len(os.Args) == 1 {
@@ -60,7 +61,7 @@ func runPipeline(mainLoop *gst.MainLoop) error {
}
func main() {
examples.RunLoop(func(loop *gst.MainLoop) error {
examples.RunLoop(func(loop *glib.MainLoop) error {
return runPipeline(loop)
})
}

View File

@@ -15,11 +15,12 @@ import (
"math"
"time"
"github.com/tinyzimmer/go-glib/glib"
"github.com/tinyzimmer/go-gst/examples"
"github.com/tinyzimmer/go-gst/gst"
)
func padProbes(mainLoop *gst.MainLoop) error {
func padProbes(mainLoop *glib.MainLoop) error {
gst.Init(nil)
// Parse the pipeline we want to probe from a static in-line string.

View File

@@ -16,13 +16,14 @@ import (
"fmt"
"os"
"github.com/tinyzimmer/go-glib/glib"
"github.com/tinyzimmer/go-gst/examples"
"github.com/tinyzimmer/go-gst/gst"
)
var srcURI string
func playbin(mainLoop *gst.MainLoop) error {
func playbin(mainLoop *glib.MainLoop) error {
if len(os.Args) < 2 {
return errors.New("Usage: playbin <uri>")
}

View File

@@ -59,13 +59,13 @@ var CAT = gst.NewDebugCategory(
// This element only has a single property, the location of the file to write to.
// When getting and setting properties later on, you will reference them by their index in
// this list.
var properties = []*gst.ParamSpec{
gst.NewStringParam(
var properties = []*glib.ParamSpec{
glib.NewStringParam(
"location", // The name of the parameter
"File Location", // The long name for the parameter
"Location to write the file to", // A blurb about the parameter
nil, // A default value for the parameter
gst.ParameterReadWrite, // Flags for the parameter
glib.ParameterReadWrite, // Flags for the parameter
),
}
@@ -85,7 +85,7 @@ type settings struct {
location string
}
// Finally a structure is defined that implements (at a minimum) the gst.GoElement interface.
// Finally a structure is defined that implements (at a minimum) the glib.GoObject interface.
// It is possible to signal to the bindings to inherit from other classes or implement other
// interfaces via the registration and TypeInit processes.
type fileSink struct {
@@ -109,10 +109,9 @@ func (f *fileSink) setLocation(path string) error {
// element and its capabilities with the type system. These are the minimum methods that
// should be implemented by an element.
// Every element needs to provide its own constructor that returns an initialized
// gst.GoElement implementation. Here we simply create a new fileSink with zeroed settings
// and state objects.
func (f *fileSink) New() gst.GoElement {
// Every element needs to provide its own constructor that returns an initialized glib.GoObjectSubclass
// implementation. Here we simply create a new fileSink with zeroed settings and state objects.
func (f *fileSink) New() glib.GoObjectSubclass {
CAT.Log(gst.LevelLog, "Initializing new fileSink object")
return &fileSink{
settings: &settings{},
@@ -122,29 +121,30 @@ func (f *fileSink) New() gst.GoElement {
// 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 *gst.TypeInstance) {
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 *gst.ElementClass) {
func (f *fileSink) ClassInit(klass *glib.ObjectClass) {
CAT.Log(gst.LevelLog, "Initializing gofilesink class")
klass.SetMetadata(
class := gst.ToElementClass(klass)
class.SetMetadata(
"File Sink",
"Sink/File",
"Write stream to a file",
"Avi Zimmerman <avi.zimmerman@gmail.com>",
)
CAT.Log(gst.LevelLog, "Adding sink pad template and properties to class")
klass.AddPadTemplate(gst.NewPadTemplate(
class.AddPadTemplate(gst.NewPadTemplate(
"sink",
gst.PadDirectionSink,
gst.PadPresenceAlways,
gst.NewAnyCaps(),
))
klass.InstallProperties(properties)
class.InstallProperties(properties)
}
// Object implementations are used during the initialization of an element. The

View File

@@ -59,13 +59,13 @@ var CAT = gst.NewDebugCategory(
// This element only has a single property, the location of the file to read from.
// When getting and setting properties later on, you will reference them by their index in
// this list.
var properties = []*gst.ParamSpec{
gst.NewStringParam(
var properties = []*glib.ParamSpec{
glib.NewStringParam(
"location", // The name of the parameter
"File Location", // The long name for the parameter
"Location of the file to read from", // A blurb about the parameter
nil, // A default value for the parameter
gst.ParameterReadWrite, // Flags for the parameter
glib.ParameterReadWrite, // Flags for the parameter
),
}
@@ -114,9 +114,8 @@ func (f *fileSrc) setLocation(path string) error {
// should be implemented by an element.
// Every element needs to provide its own constructor that returns an initialized
// gst.GoElement implementation. Here we simply create a new fileSrc with zeroed settings
// and state objects.
func (f *fileSrc) New() gst.GoElement {
// glib.GoObjectSubclass and state objects.
func (f *fileSrc) New() glib.GoObjectSubclass {
CAT.Log(gst.LevelLog, "Initializing new fileSrc object")
return &fileSrc{
settings: &settings{},
@@ -126,29 +125,30 @@ func (f *fileSrc) New() gst.GoElement {
// 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 *gst.TypeInstance) {
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 *gst.ElementClass) {
func (f *fileSrc) ClassInit(klass *glib.ObjectClass) {
CAT.Log(gst.LevelLog, "Initializing gofilesrc class")
klass.SetMetadata(
class := gst.ToElementClass(klass)
class.SetMetadata(
"File Source",
"Source/File",
"Read stream from a file",
"Avi Zimmerman <avi.zimmerman@gmail.com>",
)
CAT.Log(gst.LevelLog, "Adding src pad template and properties to class")
klass.AddPadTemplate(gst.NewPadTemplate(
class.AddPadTemplate(gst.NewPadTemplate(
"src",
gst.PadDirectionSource,
gst.PadPresenceAlways,
gst.NewAnyCaps(),
))
klass.InstallProperties(properties)
class.InstallProperties(properties)
}
// Object implementations are used during the initialization of an element. The

View File

@@ -1,36 +0,0 @@
package main
import (
"os"
)
const (
accessKeyIDEnvVar = "MINIO_ACCESS_KEY_ID"
secretAccessKeyEnvVar = "MINIO_SECRET_ACCESS_KEY"
)
var (
defaultEndpoint = "play.min.io"
defaultUseTLS = true
defaultRegion = "us-east-1"
)
type settings struct {
endpoint string
useTLS bool
region string
bucket string
key string
accessKeyID string
secretAccessKey string
}
func defaultSettings() *settings {
return &settings{
endpoint: defaultEndpoint,
useTLS: defaultUseTLS,
region: defaultRegion,
accessKeyID: os.Getenv(accessKeyIDEnvVar),
secretAccessKey: os.Getenv(secretAccessKeyEnvVar),
}
}

View File

@@ -1,267 +0,0 @@
package main
import (
"context"
"fmt"
"io"
"sync"
minio "github.com/minio/minio-go/v7"
"github.com/minio/minio-go/v7/pkg/credentials"
"github.com/tinyzimmer/go-glib/glib"
"github.com/tinyzimmer/go-gst/gst"
"github.com/tinyzimmer/go-gst/gst/base"
)
var sinkCAT = gst.NewDebugCategory(
"miniosink",
gst.DebugColorNone,
"MinIOSink Element",
)
var sinkProperties = []*gst.ParamSpec{
gst.NewStringParam(
"endpoint",
"S3 API Endpoint",
"The endpoint for the S3 API server",
&defaultEndpoint,
gst.ParameterReadWrite,
),
gst.NewBoolParam(
"use-tls",
"Use TLS",
"Use HTTPS for API requests",
defaultUseTLS,
gst.ParameterReadWrite,
),
gst.NewStringParam(
"region",
"Bucket region",
"The region where the bucket is",
&defaultRegion,
gst.ParameterReadWrite,
),
gst.NewStringParam(
"bucket",
"Bucket name",
"The name of the MinIO bucket",
nil,
gst.ParameterReadWrite,
),
gst.NewStringParam(
"key",
"Object key",
"The key of the object inside the bucket",
nil,
gst.ParameterReadWrite,
),
gst.NewStringParam(
"access-key-id",
"Access Key ID",
"The access key ID to use for authentication",
nil,
gst.ParameterReadWrite,
),
gst.NewStringParam(
"secret-access-key",
"Secret Access Key",
"The secret access key to use for authentication",
nil,
gst.ParameterReadWrite,
),
}
type minioSink struct {
settings *settings
state *sinkstate
}
type sinkstate struct {
started bool
rPipe io.ReadCloser
wPipe io.WriteCloser
doneChan chan struct{}
mux sync.Mutex
}
func (m *minioSink) New() gst.GoElement {
srcCAT.Log(gst.LevelLog, "Creating new minioSink object")
return &minioSink{
settings: defaultSettings(),
state: &sinkstate{},
}
}
func (m *minioSink) TypeInit(*gst.TypeInstance) {}
func (m *minioSink) ClassInit(klass *gst.ElementClass) {
sinkCAT.Log(gst.LevelLog, "Initializing miniosink class")
klass.SetMetadata(
"MinIO Sink",
"Sink/File",
"Write stream to a MinIO object",
"Avi Zimmerman <avi.zimmerman@gmail.com>",
)
sinkCAT.Log(gst.LevelLog, "Adding sink pad template and properties to class")
klass.AddPadTemplate(gst.NewPadTemplate(
"sink",
gst.PadDirectionSink,
gst.PadPresenceAlways,
gst.NewAnyCaps(),
))
klass.InstallProperties(sinkProperties)
}
func (m *minioSink) SetProperty(self *gst.Object, id uint, value *glib.Value) {
prop := sinkProperties[id]
val, err := value.GoValue()
if err != nil {
gst.ToElement(self).ErrorMessage(gst.DomainLibrary, gst.LibraryErrorSettings,
fmt.Sprintf("Could not coerce %v to go value", value), err.Error())
}
switch prop.Name() {
case "endpoint":
m.settings.endpoint = val.(string)
case "use-tls":
m.settings.useTLS = val.(bool)
case "region":
m.settings.region = val.(string)
case "bucket":
m.settings.bucket = val.(string)
case "key":
m.settings.key = val.(string)
case "access-key-id":
m.settings.accessKeyID = val.(string)
case "secret-access-key":
m.settings.secretAccessKey = val.(string)
}
}
func (m *minioSink) GetProperty(self *gst.Object, id uint) *glib.Value {
prop := sinkProperties[id]
var localVal interface{}
switch prop.Name() {
case "endpoint":
localVal = m.settings.endpoint
case "use-tls":
localVal = m.settings.useTLS
case "region":
localVal = m.settings.region
case "bucket":
localVal = m.settings.bucket
case "key":
localVal = m.settings.key
case "access-key-id":
localVal = m.settings.accessKeyID
case "secret-access-key":
localVal = m.settings.secretAccessKey
default:
gst.ToElement(self).ErrorMessage(gst.DomainLibrary, gst.LibraryErrorSettings,
fmt.Sprintf("Cannot get invalid property %s", prop.Name()), "")
return nil
}
val, err := glib.GValue(localVal)
if err != nil {
gst.ToElement(self).ErrorMessage(gst.DomainLibrary, gst.LibraryErrorFailed,
fmt.Sprintf("Could not convert %v to GValue", localVal),
err.Error(),
)
}
return val
}
func (m *minioSink) Start(self *base.GstBaseSink) bool {
if m.state.started {
self.ErrorMessage(gst.DomainResource, gst.ResourceErrorSettings,
"MinIOSink is already started", "")
return false
}
if m.settings.bucket == "" {
self.ErrorMessage(gst.DomainResource, gst.ResourceErrorSettings,
"No bucket configured on the miniosink", "")
return false
}
if m.settings.key == "" {
self.ErrorMessage(gst.DomainResource, gst.ResourceErrorSettings,
"No bucket configured on the miniosink", "")
return false
}
m.state.doneChan = make(chan struct{})
client, err := minio.New(m.settings.endpoint, &minio.Options{
Creds: credentials.NewStaticV4(m.settings.accessKeyID, m.settings.secretAccessKey, ""),
Secure: m.settings.useTLS,
Region: m.settings.region,
})
if err != nil {
self.ErrorMessage(gst.DomainResource, gst.ResourceErrorFailed,
fmt.Sprintf("Failed to connect to MinIO endpoint %s", m.settings.endpoint), err.Error())
return false
}
m.state.rPipe, m.state.wPipe = io.Pipe()
go func() {
self.Log(sinkCAT, gst.LevelInfo,
fmt.Sprintf("Starting PutObject operation to %s/%s/%s", m.settings.endpoint, m.settings.bucket, m.settings.key),
)
if _, err := client.PutObject(context.Background(),
m.settings.bucket, m.settings.key,
m.state.rPipe, -1,
minio.PutObjectOptions{
ContentType: "application/octet-stream",
}); err != nil {
self.ErrorMessage(gst.DomainResource, gst.ResourceErrorFailed,
fmt.Sprintf("Error during PutObject call to %s/%s", m.settings.bucket, m.settings.key), err.Error())
}
m.state.doneChan <- struct{}{}
}()
m.state.started = true
self.Log(sinkCAT, gst.LevelInfo, "MinIOSink has started")
return true
}
func (m *minioSink) Stop(self *base.GstBaseSink) bool {
if !m.state.started {
self.ErrorMessage(gst.DomainResource, gst.ResourceErrorSettings, "MinIOSink is not started", "")
return false
}
if err := m.state.wPipe.Close(); err != nil {
self.ErrorMessage(gst.DomainResource, gst.ResourceErrorWrite, "Failed to close the write pipe", err.Error())
return false
}
self.Log(sinkCAT, gst.LevelInfo, "Waiting for PutObject operation to complete")
<-m.state.doneChan
self.Log(sinkCAT, gst.LevelInfo, "MinIOSink has stopped")
return true
}
func (m *minioSink) Render(self *base.GstBaseSink, buffer *gst.Buffer) gst.FlowReturn {
if !m.state.started {
self.ErrorMessage(gst.DomainResource, gst.ResourceErrorSettings, "MinIOSink is not started", "")
return gst.FlowError
}
self.Log(sinkCAT, gst.LevelLog, fmt.Sprintf("Rendering buffer %v", buffer))
if _, err := io.Copy(m.state.wPipe, buffer.Reader()); err != nil {
self.ErrorMessage(gst.DomainResource, gst.ResourceErrorWrite, "Error copying buffer to write pipe", err.Error())
return gst.FlowError
}
return gst.FlowOK
}

View File

@@ -1,324 +0,0 @@
// This example demonstrates a src element that reads from objects in a minio bucket.
// Since minio implements the S3 API this plugin could also be used for S3 buckets by
// setting the correct endpoints and credentials.
//
// By default this plugin will use the credentials set in the environment at MINIO_ACCESS_KEY_ID
// and MINIO_SECRET_ACCESS_KEY however these can also be set on the element directly.
//
//
// In order to build the plugin for use by GStreamer, you can do the following:
//
// $ go build -o libgstminiosrc.so -buildmode c-shared .
//
package main
import (
"context"
"fmt"
"io"
"sync"
minio "github.com/minio/minio-go/v7"
"github.com/minio/minio-go/v7/pkg/credentials"
"github.com/tinyzimmer/go-glib/glib"
"github.com/tinyzimmer/go-gst/gst"
"github.com/tinyzimmer/go-gst/gst/base"
)
var srcCAT = gst.NewDebugCategory(
"miniosrc",
gst.DebugColorNone,
"MinIOSrc Element",
)
var srcProperties = []*gst.ParamSpec{
gst.NewStringParam(
"endpoint",
"S3 API Endpoint",
"The endpoint for the S3 API server",
&defaultEndpoint,
gst.ParameterReadWrite,
),
gst.NewBoolParam(
"use-tls",
"Use TLS",
"Use HTTPS for API requests",
defaultUseTLS,
gst.ParameterReadWrite,
),
gst.NewStringParam(
"region",
"Bucket region",
"The region where the bucket is",
&defaultRegion,
gst.ParameterReadWrite,
),
gst.NewStringParam(
"bucket",
"Bucket name",
"The name of the MinIO bucket",
nil,
gst.ParameterReadWrite,
),
gst.NewStringParam(
"key",
"Object key",
"The key of the object inside the bucket",
nil,
gst.ParameterReadWrite,
),
gst.NewStringParam(
"access-key-id",
"Access Key ID",
"The access key ID to use for authentication",
nil,
gst.ParameterReadWrite,
),
gst.NewStringParam(
"secret-access-key",
"Secret Access Key",
"The secret access key to use for authentication",
nil,
gst.ParameterReadWrite,
),
}
type minioSrc struct {
settings *settings
state *srcstate
}
type srcstate struct {
started bool
object *minio.Object
objInfo minio.ObjectInfo
mux sync.Mutex
}
func (m *minioSrc) New() gst.GoElement {
srcCAT.Log(gst.LevelLog, "Creating new minioSrc object")
return &minioSrc{
settings: defaultSettings(),
state: &srcstate{},
}
}
func (m *minioSrc) TypeInit(*gst.TypeInstance) {}
func (m *minioSrc) ClassInit(klass *gst.ElementClass) {
srcCAT.Log(gst.LevelLog, "Initializing miniosrc class")
klass.SetMetadata(
"MinIO Source",
"Source/File",
"Read stream from a MinIO object",
"Avi Zimmerman <avi.zimmerman@gmail.com>",
)
srcCAT.Log(gst.LevelLog, "Adding src pad template and properties to class")
klass.AddPadTemplate(gst.NewPadTemplate(
"src",
gst.PadDirectionSource,
gst.PadPresenceAlways,
gst.NewAnyCaps(),
))
klass.InstallProperties(srcProperties)
}
func (m *minioSrc) SetProperty(self *gst.Object, id uint, value *glib.Value) {
prop := srcProperties[id]
val, err := value.GoValue()
if err != nil {
gst.ToElement(self).ErrorMessage(gst.DomainLibrary, gst.LibraryErrorSettings,
fmt.Sprintf("Could not coerce %v to go value", value), err.Error())
}
switch prop.Name() {
case "endpoint":
m.settings.endpoint = val.(string)
case "use-tls":
m.settings.useTLS = val.(bool)
case "region":
m.settings.region = val.(string)
case "bucket":
m.settings.bucket = val.(string)
case "key":
m.settings.key = val.(string)
case "access-key-id":
m.settings.accessKeyID = val.(string)
case "secret-access-key":
m.settings.secretAccessKey = val.(string)
}
}
func (m *minioSrc) GetProperty(self *gst.Object, id uint) *glib.Value {
prop := srcProperties[id]
var localVal interface{}
switch prop.Name() {
case "endpoint":
localVal = m.settings.endpoint
case "use-tls":
localVal = m.settings.useTLS
case "region":
localVal = m.settings.region
case "bucket":
localVal = m.settings.bucket
case "key":
localVal = m.settings.key
case "access-key-id":
localVal = m.settings.accessKeyID
case "secret-access-key":
localVal = m.settings.secretAccessKey
default:
gst.ToElement(self).ErrorMessage(gst.DomainLibrary, gst.LibraryErrorSettings,
fmt.Sprintf("Cannot get invalid property %s", prop.Name()), "")
return nil
}
val, err := glib.GValue(localVal)
if err != nil {
gst.ToElement(self).ErrorMessage(gst.DomainLibrary, gst.LibraryErrorFailed,
fmt.Sprintf("Could not convert %v to GValue", localVal),
err.Error(),
)
}
return val
}
func (m *minioSrc) Constructed(self *gst.Object) {
self.Log(srcCAT, gst.LevelLog, "Setting format of GstBaseSrc to bytes")
base.ToGstBaseSrc(self).SetFormat(gst.FormatBytes)
}
func (m *minioSrc) IsSeekable(*base.GstBaseSrc) bool { return true }
func (m *minioSrc) GetSize(self *base.GstBaseSrc) (bool, int64) {
if !m.state.started {
return false, 0
}
return true, m.state.objInfo.Size
}
func (m *minioSrc) Start(self *base.GstBaseSrc) bool {
m.state.mux.Lock()
if m.state.started {
self.ErrorMessage(gst.DomainResource, gst.ResourceErrorFailed, "MinIOSrc is already started", "")
return false
}
if m.settings.bucket == "" {
self.ErrorMessage(gst.DomainResource, gst.ResourceErrorFailed, "No source bucket defined", "")
return false
}
if m.settings.key == "" {
self.ErrorMessage(gst.DomainResource, gst.ResourceErrorFailed, "No object key defined", "")
return false
}
client, err := minio.New(m.settings.endpoint, &minio.Options{
Creds: credentials.NewStaticV4(m.settings.accessKeyID, m.settings.secretAccessKey, ""),
Secure: m.settings.useTLS,
Region: m.settings.region,
})
if err != nil {
self.ErrorMessage(gst.DomainResource, gst.ResourceErrorFailed,
fmt.Sprintf("Failed to connect to MinIO endpoint %s", m.settings.endpoint), err.Error())
return false
}
self.Log(srcCAT, gst.LevelInfo, fmt.Sprintf("Requesting %s/%s from %s", m.settings.bucket, m.settings.key, m.settings.endpoint))
m.state.object, err = client.GetObject(context.Background(), m.settings.bucket, m.settings.key, minio.GetObjectOptions{})
if err != nil {
self.ErrorMessage(gst.DomainResource, gst.ResourceErrorOpenRead,
fmt.Sprintf("Failed to retrieve object %q from bucket %q", m.settings.key, m.settings.bucket), err.Error())
return false
}
self.Log(srcCAT, gst.LevelInfo, "Getting HEAD for object")
m.state.objInfo, err = m.state.object.Stat()
if err != nil {
self.ErrorMessage(gst.DomainResource, gst.ResourceErrorOpenRead,
fmt.Sprintf("Failed to stat object %q in bucket %q: %s", m.settings.key, m.settings.bucket, err.Error()), "")
return false
}
self.Log(srcCAT, gst.LevelInfo, fmt.Sprintf("%+v", m.state.objInfo))
m.state.started = true
m.state.mux.Unlock()
self.StartComplete(gst.FlowOK)
self.Log(srcCAT, gst.LevelInfo, "MinIOSrc has started")
return true
}
func (m *minioSrc) Stop(self *base.GstBaseSrc) bool {
m.state.mux.Lock()
defer m.state.mux.Unlock()
if !m.state.started {
self.ErrorMessage(gst.DomainResource, gst.ResourceErrorSettings, "MinIOSrc is not started", "")
return false
}
if err := m.state.object.Close(); err != nil {
self.ErrorMessage(gst.DomainResource, gst.ResourceErrorClose, "Failed to close the bucket object", err.Error())
return false
}
m.state.object = nil
m.state.started = false
self.Log(srcCAT, gst.LevelInfo, "MinIOSrc has stopped")
return true
}
func (m *minioSrc) Fill(self *base.GstBaseSrc, offset uint64, size uint, buffer *gst.Buffer) gst.FlowReturn {
if !m.state.started || m.state.object == nil {
self.ErrorMessage(gst.DomainCore, gst.CoreErrorFailed, "MinIOSrc is not started yet", "")
return gst.FlowError
}
self.Log(srcCAT, gst.LevelLog, fmt.Sprintf("Request to fill buffer from offset %v with size %v", offset, size))
m.state.mux.Lock()
defer m.state.mux.Unlock()
data := make([]byte, size)
read, err := m.state.object.ReadAt(data, int64(offset))
if err != nil && err != io.EOF {
self.ErrorMessage(gst.DomainResource, gst.ResourceErrorRead,
fmt.Sprintf("Failed to read %d bytes from object at offset %d", size, offset), err.Error())
return gst.FlowError
}
if read < int(size) {
self.Log(srcCAT, gst.LevelDebug, fmt.Sprintf("Only read %d bytes from object, trimming", read))
trim := make([]byte, read)
copy(trim, data)
data = trim
}
bufmap := buffer.Map(gst.MapWrite)
if bufmap == nil {
self.ErrorMessage(gst.DomainLibrary, gst.LibraryErrorFailed, "Failed to map buffer", "")
return gst.FlowError
}
defer buffer.Unmap()
bufmap.WriteData(data)
buffer.SetSize(int64(read))
return gst.FlowOK
}

View File

@@ -1,61 +0,0 @@
package main
import "C"
import (
"unsafe"
"github.com/tinyzimmer/go-gst/gst"
"github.com/tinyzimmer/go-gst/gst/base"
)
// The metadata for this plugin
var pluginMeta = &gst.PluginMetadata{
MajorVersion: gst.VersionMajor,
MinorVersion: gst.VersionMinor,
Name: "miniosrc",
Description: "GStreamer plugins for reading and writing from Minio",
Version: "v0.0.1",
License: gst.LicenseLGPL,
Source: "go-gst",
Package: "examples",
Origin: "https://github.com/tinyzimmer/go-gst",
ReleaseDate: "2021-01-11",
// The init function is called to register elements provided by the plugin.
Init: func(plugin *gst.Plugin) bool {
if ok := gst.RegisterElement(
plugin,
// The name of the element
"miniosrc",
// The rank of the element
gst.RankNone,
// The GoElement implementation for the element
&minioSrc{},
// The base subclass this element extends
base.ExtendsBaseSrc,
); !ok {
return ok
}
if ok := gst.RegisterElement(
plugin,
// The name of the element
"miniosink",
// The rank of the element
gst.RankNone,
// The GoElement implementation for the element
&minioSink{},
// The base subclass this element extends
base.ExtendsBaseSink,
); !ok {
return ok
}
return true
},
}
func main() {}
//export gst_plugin_minio_get_desc
func gst_plugin_minio_get_desc() unsafe.Pointer { return pluginMeta.Export() }

View File

@@ -55,29 +55,29 @@ var CAT = gst.NewDebugCategory(
"WebsocketSrc Element",
)
var properties = []*gst.ParamSpec{
gst.NewStringParam(
var properties = []*glib.ParamSpec{
glib.NewStringParam(
"address",
"Server Address",
"The address to bind the server to",
&DefaultAddress,
gst.ParameterReadWrite,
glib.ParameterReadWrite,
),
gst.NewIntParam(
glib.NewIntParam(
"port",
"Server Port",
"The port to bind the server to",
1024, 65535,
DefaultPort,
gst.ParameterReadWrite,
glib.ParameterReadWrite,
),
// not implemented yet
gst.NewBoolParam(
glib.NewBoolParam(
"retrieve-remote-addr",
"Retrieve Remote Address",
"Include the remote client's address in the buffer metadata",
DefaultRetrieveRemoteAddr,
gst.ParameterReadWrite,
glib.ParameterReadWrite,
),
}
@@ -398,29 +398,30 @@ func (w *websocketSrc) setupSrcPad(elem *gst.Element) {
// * ObjectSubclass * //
func (w *websocketSrc) New() gst.GoElement {
func (w *websocketSrc) New() glib.GoObjectSubclass {
return &websocketSrc{
settings: defaultSettings(),
state: &state{},
}
}
func (w *websocketSrc) TypeInit(instance *gst.TypeInstance) {}
func (w *websocketSrc) TypeInit(instance *glib.TypeInstance) {}
func (w *websocketSrc) ClassInit(klass *gst.ElementClass) {
klass.SetMetadata(
func (w *websocketSrc) ClassInit(klass *glib.ObjectClass) {
class := gst.ToElementClass(klass)
class.SetMetadata(
"Websocket Src",
"Src/Websocket",
"Write stream from a connection over a websocket server",
"Avi Zimmerman <avi.zimmerman@gmail.com>",
)
klass.AddPadTemplate(gst.NewPadTemplate(
class.AddPadTemplate(gst.NewPadTemplate(
"src",
gst.PadDirectionSource,
gst.PadPresenceAlways,
gst.NewAnyCaps(),
))
klass.InstallProperties(properties)
class.InstallProperties(properties)
}
// * Object * //

View File

@@ -20,11 +20,12 @@ import (
"strings"
"time"
"github.com/tinyzimmer/go-glib/glib"
"github.com/tinyzimmer/go-gst/examples"
"github.com/tinyzimmer/go-gst/gst"
)
func queries(mainLoop *gst.MainLoop) error {
func queries(mainLoop *glib.MainLoop) error {
if len(os.Args) < 2 {
fmt.Println("USAGE: queries <pipeline>")

View File

@@ -18,11 +18,12 @@ import (
"os"
"time"
"github.com/tinyzimmer/go-glib/glib"
"github.com/tinyzimmer/go-gst/examples"
"github.com/tinyzimmer/go-gst/gst"
)
func tagsetter(mainLoop *gst.MainLoop) error {
func tagsetter(mainLoop *glib.MainLoop) error {
gst.Init(nil)
if len(os.Args) < 2 {

3
go.mod
View File

@@ -4,5 +4,6 @@ go 1.15
require (
github.com/mattn/go-pointer v0.0.1
github.com/tinyzimmer/go-glib v0.0.4
github.com/tinyzimmer/go-glib v0.0.7
golang.org/x/net v0.0.0-20201224014010-6772e930b67b
)

12
go.sum
View File

@@ -1,4 +1,12 @@
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.4 h1:IaysVU2Y4QNqgyKhnMVB1Q/55+zpgkVXnIEbV9bWWS8=
github.com/tinyzimmer/go-glib v0.0.4/go.mod h1:D5rd0CvYn1p7TBhwlwnBXHSr4d8lwEY9JImPQ66S+Bs=
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=
golang.org/x/net v0.0.0-20201224014010-6772e930b67b h1:iFwSg7t5GZmB/Q5TjiEAsdoLDrdJRC1RiF2WhuV29Qw=
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68 h1:nxC68pudNYkKU6jWhgrqdreuFiOQWj1Fs7T3VrH4Pjw=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=

View File

@@ -23,7 +23,9 @@ import (
"unsafe"
gopointer "github.com/mattn/go-pointer"
"github.com/tinyzimmer/go-gst/gst"
"github.com/tinyzimmer/go-gst/gst/base"
)
// SinkCallbacks represents callbacks that can be installed on an app sink when data is available.
@@ -37,7 +39,7 @@ type SinkCallbacks struct {
var ErrEOS = errors.New("Pipeline has reached end-of-stream")
// Sink wraps an Element made with the appsink plugin with additional methods for pulling samples.
type Sink struct{ *gst.Element }
type Sink struct{ *base.GstBaseSink }
// NewAppSink returns a new appsink element. Unref after usage.
func NewAppSink() (*Sink, error) {

View File

@@ -23,6 +23,7 @@ import (
gopointer "github.com/mattn/go-pointer"
"github.com/tinyzimmer/go-gst/gst"
"github.com/tinyzimmer/go-gst/gst/base"
)
// SourceCallbacks represents callbacks to configure on an AppSource.
@@ -43,7 +44,7 @@ const (
)
// Source wraps an Element made with the appsrc plugin with additional methods for pushing samples.
type Source struct{ *gst.Element }
type Source struct{ *base.GstBaseSrc }
// NewAppSrc returns a new AppSrc element.
func NewAppSrc() (*Source, error) {

View File

@@ -5,10 +5,15 @@ import "C"
import (
"github.com/tinyzimmer/go-gst/gst"
"github.com/tinyzimmer/go-gst/gst/base"
)
func wrapAppSink(elem *gst.Element) *Sink { return &Sink{elem} }
func wrapAppSrc(elem *gst.Element) *Source { return &Source{elem} }
func wrapAppSink(elem *gst.Element) *Sink {
return &Sink{GstBaseSink: &base.GstBaseSink{Element: elem}}
}
func wrapAppSrc(elem *gst.Element) *Source {
return &Source{GstBaseSrc: &base.GstBaseSrc{Element: elem}}
}
// gobool provides an easy type conversion between C.gboolean and a go bool.
func gobool(b C.gboolean) bool { return int(b) > 0 }

View File

@@ -9,12 +9,13 @@ import (
"time"
"unsafe"
"github.com/tinyzimmer/go-glib/glib"
"github.com/tinyzimmer/go-gst/gst"
)
//export goGstBaseSinkActivatePull
func goGstBaseSinkActivatePull(sink *C.GstBaseSink, active C.gboolean) C.gboolean {
iface := gst.FromObjectUnsafePrivate(unsafe.Pointer(sink)).(interface {
iface := glib.FromObjectUnsafePrivate(unsafe.Pointer(sink)).(interface {
ActivatePull(self *GstBaseSink, active bool) bool
})
return gboolean(iface.ActivatePull(wrapGstBaseSink(sink), gobool(active)))
@@ -22,7 +23,7 @@ func goGstBaseSinkActivatePull(sink *C.GstBaseSink, active C.gboolean) C.gboolea
//export goGstBaseSinkEvent
func goGstBaseSinkEvent(sink *C.GstBaseSink, event *C.GstEvent) C.gboolean {
iface := gst.FromObjectUnsafePrivate(unsafe.Pointer(sink)).(interface {
iface := glib.FromObjectUnsafePrivate(unsafe.Pointer(sink)).(interface {
Event(self *GstBaseSink, event *gst.Event) bool
})
return gboolean(iface.Event(wrapGstBaseSink(sink), gst.FromGstEventUnsafe(unsafe.Pointer(event))))
@@ -30,7 +31,7 @@ func goGstBaseSinkEvent(sink *C.GstBaseSink, event *C.GstEvent) C.gboolean {
//export goGstBaseSinkFixate
func goGstBaseSinkFixate(sink *C.GstBaseSink, caps *C.GstCaps) *C.GstCaps {
iface := gst.FromObjectUnsafePrivate(unsafe.Pointer(sink)).(interface {
iface := glib.FromObjectUnsafePrivate(unsafe.Pointer(sink)).(interface {
Fixate(self *GstBaseSink, caps *gst.Caps) *gst.Caps
})
fixated := iface.Fixate(wrapGstBaseSink(sink), gst.FromGstCapsUnsafe(unsafe.Pointer(caps)))
@@ -42,7 +43,7 @@ func goGstBaseSinkFixate(sink *C.GstBaseSink, caps *C.GstCaps) *C.GstCaps {
//export goGstBaseSinkGetCaps
func goGstBaseSinkGetCaps(sink *C.GstBaseSink, filter *C.GstCaps) *C.GstCaps {
iface := gst.FromObjectUnsafePrivate(unsafe.Pointer(sink)).(interface {
iface := glib.FromObjectUnsafePrivate(unsafe.Pointer(sink)).(interface {
GetCaps(self *GstBaseSink, filter *gst.Caps) *gst.Caps
})
filtered := iface.GetCaps(wrapGstBaseSink(sink), gst.FromGstCapsUnsafe(unsafe.Pointer(filter)))
@@ -54,7 +55,7 @@ func goGstBaseSinkGetCaps(sink *C.GstBaseSink, filter *C.GstCaps) *C.GstCaps {
//export goGstBaseSinkGetTimes
func goGstBaseSinkGetTimes(sink *C.GstBaseSink, buf *C.GstBuffer, start, end *C.GstClockTime) {
iface := gst.FromObjectUnsafePrivate(unsafe.Pointer(sink)).(interface {
iface := glib.FromObjectUnsafePrivate(unsafe.Pointer(sink)).(interface {
GetTimes(self *GstBaseSink, buffer *gst.Buffer) (start, end time.Duration)
})
retStart, retEnd := iface.GetTimes(wrapGstBaseSink(sink), gst.FromGstBufferUnsafe(unsafe.Pointer(buf)))
@@ -64,7 +65,7 @@ func goGstBaseSinkGetTimes(sink *C.GstBaseSink, buf *C.GstBuffer, start, end *C.
//export goGstBaseSinkPrepare
func goGstBaseSinkPrepare(sink *C.GstBaseSink, buf *C.GstBuffer) C.GstFlowReturn {
iface := gst.FromObjectUnsafePrivate(unsafe.Pointer(sink)).(interface {
iface := glib.FromObjectUnsafePrivate(unsafe.Pointer(sink)).(interface {
Prepare(self *GstBaseSink, buffer *gst.Buffer) gst.FlowReturn
})
return C.GstFlowReturn(iface.Prepare(wrapGstBaseSink(sink), gst.FromGstBufferUnsafe(unsafe.Pointer(buf))))
@@ -72,7 +73,7 @@ func goGstBaseSinkPrepare(sink *C.GstBaseSink, buf *C.GstBuffer) C.GstFlowReturn
//export goGstBaseSinkPrepareList
func goGstBaseSinkPrepareList(sink *C.GstBaseSink, list *C.GstBufferList) C.GstFlowReturn {
iface := gst.FromObjectUnsafePrivate(unsafe.Pointer(sink)).(interface {
iface := glib.FromObjectUnsafePrivate(unsafe.Pointer(sink)).(interface {
PrepareList(self *GstBaseSink, bufferList *gst.BufferList) gst.FlowReturn
})
return C.GstFlowReturn(iface.PrepareList(wrapGstBaseSink(sink), gst.FromGstBufferListUnsafe(unsafe.Pointer(list))))
@@ -80,7 +81,7 @@ func goGstBaseSinkPrepareList(sink *C.GstBaseSink, list *C.GstBufferList) C.GstF
//export goGstBaseSinkPreroll
func goGstBaseSinkPreroll(sink *C.GstBaseSink, buf *C.GstBuffer) C.GstFlowReturn {
iface := gst.FromObjectUnsafePrivate(unsafe.Pointer(sink)).(interface {
iface := glib.FromObjectUnsafePrivate(unsafe.Pointer(sink)).(interface {
Preroll(self *GstBaseSink, buffer *gst.Buffer) gst.FlowReturn
})
return C.GstFlowReturn(iface.Preroll(wrapGstBaseSink(sink), gst.FromGstBufferUnsafe(unsafe.Pointer(buf))))
@@ -88,7 +89,7 @@ func goGstBaseSinkPreroll(sink *C.GstBaseSink, buf *C.GstBuffer) C.GstFlowReturn
//export goGstBaseSinkProposeAllocation
func goGstBaseSinkProposeAllocation(sink *C.GstBaseSink, query *C.GstQuery) C.gboolean {
iface := gst.FromObjectUnsafePrivate(unsafe.Pointer(sink)).(interface {
iface := glib.FromObjectUnsafePrivate(unsafe.Pointer(sink)).(interface {
ProposeAllocation(self *GstBaseSink, query *gst.Query) bool
})
return gboolean(iface.ProposeAllocation(wrapGstBaseSink(sink), gst.FromGstQueryUnsafe(unsafe.Pointer(query))))
@@ -96,7 +97,7 @@ func goGstBaseSinkProposeAllocation(sink *C.GstBaseSink, query *C.GstQuery) C.gb
//export goGstBaseSinkQuery
func goGstBaseSinkQuery(sink *C.GstBaseSink, query *C.GstQuery) C.gboolean {
iface := gst.FromObjectUnsafePrivate(unsafe.Pointer(sink)).(interface {
iface := glib.FromObjectUnsafePrivate(unsafe.Pointer(sink)).(interface {
Query(self *GstBaseSink, query *gst.Query) bool
})
return gboolean(iface.Query(wrapGstBaseSink(sink), gst.FromGstQueryUnsafe(unsafe.Pointer(query))))
@@ -104,7 +105,7 @@ func goGstBaseSinkQuery(sink *C.GstBaseSink, query *C.GstQuery) C.gboolean {
//export goGstBaseSinkRender
func goGstBaseSinkRender(sink *C.GstBaseSink, buf *C.GstBuffer) C.GstFlowReturn {
iface := gst.FromObjectUnsafePrivate(unsafe.Pointer(sink)).(interface {
iface := glib.FromObjectUnsafePrivate(unsafe.Pointer(sink)).(interface {
Render(self *GstBaseSink, buffer *gst.Buffer) gst.FlowReturn
})
return C.GstFlowReturn(iface.Render(wrapGstBaseSink(sink), gst.FromGstBufferUnsafe(unsafe.Pointer(buf))))
@@ -112,7 +113,7 @@ func goGstBaseSinkRender(sink *C.GstBaseSink, buf *C.GstBuffer) C.GstFlowReturn
//export goGstBaseSinkRenderList
func goGstBaseSinkRenderList(sink *C.GstBaseSink, buf *C.GstBufferList) C.GstFlowReturn {
iface := gst.FromObjectUnsafePrivate(unsafe.Pointer(sink)).(interface {
iface := glib.FromObjectUnsafePrivate(unsafe.Pointer(sink)).(interface {
RenderList(self *GstBaseSink, bufferList *gst.BufferList) gst.FlowReturn
})
return C.GstFlowReturn(iface.RenderList(wrapGstBaseSink(sink), gst.FromGstBufferListUnsafe(unsafe.Pointer(buf))))
@@ -120,7 +121,7 @@ func goGstBaseSinkRenderList(sink *C.GstBaseSink, buf *C.GstBufferList) C.GstFlo
//export goGstBaseSinkSetCaps
func goGstBaseSinkSetCaps(sink *C.GstBaseSink, caps *C.GstCaps) C.gboolean {
iface := gst.FromObjectUnsafePrivate(unsafe.Pointer(sink)).(interface {
iface := glib.FromObjectUnsafePrivate(unsafe.Pointer(sink)).(interface {
SetCaps(self *GstBaseSink, caps *gst.Caps) bool
})
return gboolean(iface.SetCaps(wrapGstBaseSink(sink), gst.FromGstCapsUnsafe(unsafe.Pointer(caps))))
@@ -128,7 +129,7 @@ func goGstBaseSinkSetCaps(sink *C.GstBaseSink, caps *C.GstCaps) C.gboolean {
//export goGstBaseSinkStart
func goGstBaseSinkStart(sink *C.GstBaseSink) C.gboolean {
iface := gst.FromObjectUnsafePrivate(unsafe.Pointer(sink)).(interface {
iface := glib.FromObjectUnsafePrivate(unsafe.Pointer(sink)).(interface {
Start(self *GstBaseSink) bool
})
return gboolean(iface.Start(wrapGstBaseSink(sink)))
@@ -136,7 +137,7 @@ func goGstBaseSinkStart(sink *C.GstBaseSink) C.gboolean {
//export goGstBaseSinkStop
func goGstBaseSinkStop(sink *C.GstBaseSink) C.gboolean {
iface := gst.FromObjectUnsafePrivate(unsafe.Pointer(sink)).(interface {
iface := glib.FromObjectUnsafePrivate(unsafe.Pointer(sink)).(interface {
Stop(self *GstBaseSink) bool
})
return gboolean(iface.Stop(wrapGstBaseSink(sink)))
@@ -144,7 +145,7 @@ func goGstBaseSinkStop(sink *C.GstBaseSink) C.gboolean {
//export goGstBaseSinkUnlock
func goGstBaseSinkUnlock(sink *C.GstBaseSink) C.gboolean {
iface := gst.FromObjectUnsafePrivate(unsafe.Pointer(sink)).(interface {
iface := glib.FromObjectUnsafePrivate(unsafe.Pointer(sink)).(interface {
Unlock(self *GstBaseSink) bool
})
return gboolean(iface.Unlock(wrapGstBaseSink(sink)))
@@ -152,7 +153,7 @@ func goGstBaseSinkUnlock(sink *C.GstBaseSink) C.gboolean {
//export goGstBaseSinkUnlockStop
func goGstBaseSinkUnlockStop(sink *C.GstBaseSink) C.gboolean {
iface := gst.FromObjectUnsafePrivate(unsafe.Pointer(sink)).(interface {
iface := glib.FromObjectUnsafePrivate(unsafe.Pointer(sink)).(interface {
UnlockStop(self *GstBaseSink) bool
})
return gboolean(iface.UnlockStop(wrapGstBaseSink(sink)))
@@ -160,7 +161,7 @@ func goGstBaseSinkUnlockStop(sink *C.GstBaseSink) C.gboolean {
//export goGstBaseSinkWaitEvent
func goGstBaseSinkWaitEvent(sink *C.GstBaseSink, event *C.GstEvent) C.GstFlowReturn {
iface := gst.FromObjectUnsafePrivate(unsafe.Pointer(sink)).(interface {
iface := glib.FromObjectUnsafePrivate(unsafe.Pointer(sink)).(interface {
WaitEvent(self *GstBaseSink, event *gst.Event) gst.FlowReturn
})
return C.GstFlowReturn(iface.WaitEvent(wrapGstBaseSink(sink), gst.FromGstEventUnsafe(unsafe.Pointer(event))))

View File

@@ -64,7 +64,7 @@ import (
var (
// ExtendsBaseSink is an Extendable for extending a GstBaseSink
ExtendsBaseSink gst.Extendable = &extendsBaseSink{parent: gst.ExtendsElement}
ExtendsBaseSink glib.Extendable = &extendsBaseSink{parent: gst.ExtendsElement}
)
// GstBaseSinkImpl is the documented interface for extending a GstBaseSink. It does not have to
@@ -120,13 +120,13 @@ type GstBaseSinkImpl interface {
WaitEvent(self *GstBaseSink, event *gst.Event) gst.FlowReturn
}
type extendsBaseSink struct{ parent gst.Extendable }
type extendsBaseSink struct{ parent glib.Extendable }
func (e *extendsBaseSink) Type() glib.Type { return glib.Type(C.gst_base_sink_get_type()) }
func (e *extendsBaseSink) ClassSize() int64 { return int64(C.sizeof_GstBaseSinkClass) }
func (e *extendsBaseSink) InstanceSize() int64 { return int64(C.sizeof_GstBaseSink) }
func (e *extendsBaseSink) InitClass(klass unsafe.Pointer, elem gst.GoElement) {
func (e *extendsBaseSink) InitClass(klass unsafe.Pointer, elem glib.GoObjectSubclass) {
e.parent.InitClass(klass, elem)
sinkClass := C.toGstBaseSinkClass(klass)

View File

@@ -7,12 +7,13 @@ import (
"time"
"unsafe"
"github.com/tinyzimmer/go-glib/glib"
"github.com/tinyzimmer/go-gst/gst"
)
//export goGstBaseSrcGetCaps
func goGstBaseSrcGetCaps(src *C.GstBaseSrc, filter *C.GstCaps) *C.GstCaps {
elem := gst.FromObjectUnsafePrivate(unsafe.Pointer(src))
elem := glib.FromObjectUnsafePrivate(unsafe.Pointer(src))
caller := elem.(interface {
GetCaps(*GstBaseSrc, *gst.Caps) *gst.Caps
})
@@ -22,7 +23,7 @@ func goGstBaseSrcGetCaps(src *C.GstBaseSrc, filter *C.GstCaps) *C.GstCaps {
//export goGstBaseSrcNegotiate
func goGstBaseSrcNegotiate(src *C.GstBaseSrc) C.gboolean {
elem := gst.FromObjectUnsafePrivate(unsafe.Pointer(src))
elem := glib.FromObjectUnsafePrivate(unsafe.Pointer(src))
caller := elem.(interface {
Negotiate(*GstBaseSrc) bool
})
@@ -31,7 +32,7 @@ func goGstBaseSrcNegotiate(src *C.GstBaseSrc) C.gboolean {
//export goGstBaseSrcFixate
func goGstBaseSrcFixate(src *C.GstBaseSrc, caps *C.GstCaps) *C.GstCaps {
elem := gst.FromObjectUnsafePrivate(unsafe.Pointer(src))
elem := glib.FromObjectUnsafePrivate(unsafe.Pointer(src))
caller := elem.(interface {
Fixate(*GstBaseSrc, *gst.Caps) *gst.Caps
})
@@ -41,7 +42,7 @@ func goGstBaseSrcFixate(src *C.GstBaseSrc, caps *C.GstCaps) *C.GstCaps {
//export goGstBaseSrcSetCaps
func goGstBaseSrcSetCaps(src *C.GstBaseSrc, filter *C.GstCaps) C.gboolean {
elem := gst.FromObjectUnsafePrivate(unsafe.Pointer(src))
elem := glib.FromObjectUnsafePrivate(unsafe.Pointer(src))
caller := elem.(interface {
SetCaps(*GstBaseSrc, *gst.Caps) bool
})
@@ -50,7 +51,7 @@ func goGstBaseSrcSetCaps(src *C.GstBaseSrc, filter *C.GstCaps) C.gboolean {
//export goGstBaseSrcDecideAllocation
func goGstBaseSrcDecideAllocation(src *C.GstBaseSrc, query *C.GstQuery) C.gboolean {
elem := gst.FromObjectUnsafePrivate(unsafe.Pointer(src))
elem := glib.FromObjectUnsafePrivate(unsafe.Pointer(src))
caller := elem.(interface {
DecideAllocation(*GstBaseSrc, *gst.Query) bool
})
@@ -59,7 +60,7 @@ func goGstBaseSrcDecideAllocation(src *C.GstBaseSrc, query *C.GstQuery) C.gboole
//export goGstBaseSrcStart
func goGstBaseSrcStart(src *C.GstBaseSrc) C.gboolean {
elem := gst.FromObjectUnsafePrivate(unsafe.Pointer(src))
elem := glib.FromObjectUnsafePrivate(unsafe.Pointer(src))
caller := elem.(interface {
Start(*GstBaseSrc) bool
})
@@ -68,7 +69,7 @@ func goGstBaseSrcStart(src *C.GstBaseSrc) C.gboolean {
//export goGstBaseSrcStop
func goGstBaseSrcStop(src *C.GstBaseSrc) C.gboolean {
elem := gst.FromObjectUnsafePrivate(unsafe.Pointer(src))
elem := glib.FromObjectUnsafePrivate(unsafe.Pointer(src))
caller := elem.(interface {
Stop(*GstBaseSrc) bool
})
@@ -77,7 +78,7 @@ func goGstBaseSrcStop(src *C.GstBaseSrc) C.gboolean {
//export goGstBaseSrcGetTimes
func goGstBaseSrcGetTimes(src *C.GstBaseSrc, buf *C.GstBuffer, start *C.GstClockTime, end *C.GstClockTime) {
elem := gst.FromObjectUnsafePrivate(unsafe.Pointer(src))
elem := glib.FromObjectUnsafePrivate(unsafe.Pointer(src))
caller := elem.(interface {
GetTimes(*GstBaseSrc, *gst.Buffer) (start, end time.Duration)
})
@@ -88,7 +89,7 @@ func goGstBaseSrcGetTimes(src *C.GstBaseSrc, buf *C.GstBuffer, start *C.GstClock
//export goGstBaseSrcGetSize
func goGstBaseSrcGetSize(src *C.GstBaseSrc, size *C.guint64) C.gboolean {
elem := gst.FromObjectUnsafePrivate(unsafe.Pointer(src))
elem := glib.FromObjectUnsafePrivate(unsafe.Pointer(src))
caller := elem.(interface {
GetSize(*GstBaseSrc) (bool, int64)
})
@@ -102,7 +103,7 @@ func goGstBaseSrcGetSize(src *C.GstBaseSrc, size *C.guint64) C.gboolean {
//export goGstBaseSrcIsSeekable
func goGstBaseSrcIsSeekable(src *C.GstBaseSrc) C.gboolean {
elem := gst.FromObjectUnsafePrivate(unsafe.Pointer(src))
elem := glib.FromObjectUnsafePrivate(unsafe.Pointer(src))
caller := elem.(interface {
IsSeekable(*GstBaseSrc) bool
})
@@ -111,7 +112,7 @@ func goGstBaseSrcIsSeekable(src *C.GstBaseSrc) C.gboolean {
//export goGstBaseSrcPrepareSeekSegment
func goGstBaseSrcPrepareSeekSegment(src *C.GstBaseSrc, seek *C.GstEvent, segment *C.GstSegment) C.gboolean {
elem := gst.FromObjectUnsafePrivate(unsafe.Pointer(src))
elem := glib.FromObjectUnsafePrivate(unsafe.Pointer(src))
caller := elem.(interface {
PrepareSeekSegment(*GstBaseSrc, *gst.Event, *gst.Segment) bool
})
@@ -120,7 +121,7 @@ func goGstBaseSrcPrepareSeekSegment(src *C.GstBaseSrc, seek *C.GstEvent, segment
//export goGstBaseSrcDoSeek
func goGstBaseSrcDoSeek(src *C.GstBaseSrc, segment *C.GstSegment) C.gboolean {
elem := gst.FromObjectUnsafePrivate(unsafe.Pointer(src))
elem := glib.FromObjectUnsafePrivate(unsafe.Pointer(src))
caller := elem.(interface {
DoSeek(*GstBaseSrc, *gst.Segment) bool
})
@@ -129,7 +130,7 @@ func goGstBaseSrcDoSeek(src *C.GstBaseSrc, segment *C.GstSegment) C.gboolean {
//export goGstBaseSrcUnlock
func goGstBaseSrcUnlock(src *C.GstBaseSrc) C.gboolean {
elem := gst.FromObjectUnsafePrivate(unsafe.Pointer(src))
elem := glib.FromObjectUnsafePrivate(unsafe.Pointer(src))
caller := elem.(interface {
Unlock(*GstBaseSrc) bool
})
@@ -138,7 +139,7 @@ func goGstBaseSrcUnlock(src *C.GstBaseSrc) C.gboolean {
//export goGstBaseSrcUnlockStop
func goGstBaseSrcUnlockStop(src *C.GstBaseSrc) C.gboolean {
elem := gst.FromObjectUnsafePrivate(unsafe.Pointer(src))
elem := glib.FromObjectUnsafePrivate(unsafe.Pointer(src))
caller := elem.(interface {
UnlockStop(*GstBaseSrc) bool
})
@@ -147,7 +148,7 @@ func goGstBaseSrcUnlockStop(src *C.GstBaseSrc) C.gboolean {
//export goGstBaseSrcQuery
func goGstBaseSrcQuery(src *C.GstBaseSrc, query *C.GstQuery) C.gboolean {
elem := gst.FromObjectUnsafePrivate(unsafe.Pointer(src))
elem := glib.FromObjectUnsafePrivate(unsafe.Pointer(src))
caller := elem.(interface {
Query(*GstBaseSrc, *gst.Query) bool
})
@@ -156,7 +157,7 @@ func goGstBaseSrcQuery(src *C.GstBaseSrc, query *C.GstQuery) C.gboolean {
//export goGstBaseSrcEvent
func goGstBaseSrcEvent(src *C.GstBaseSrc, event *C.GstEvent) C.gboolean {
elem := gst.FromObjectUnsafePrivate(unsafe.Pointer(src))
elem := glib.FromObjectUnsafePrivate(unsafe.Pointer(src))
caller := elem.(interface {
Event(*GstBaseSrc, *gst.Event) bool
})
@@ -165,7 +166,7 @@ func goGstBaseSrcEvent(src *C.GstBaseSrc, event *C.GstEvent) C.gboolean {
//export goGstBaseSrcCreate
func goGstBaseSrcCreate(src *C.GstBaseSrc, offset C.guint64, size C.guint, buf **C.GstBuffer) C.GstFlowReturn {
elem := gst.FromObjectUnsafePrivate(unsafe.Pointer(src))
elem := glib.FromObjectUnsafePrivate(unsafe.Pointer(src))
caller := elem.(interface {
Create(*GstBaseSrc, uint64, uint) (gst.FlowReturn, *gst.Buffer)
})
@@ -178,7 +179,7 @@ func goGstBaseSrcCreate(src *C.GstBaseSrc, offset C.guint64, size C.guint, buf *
//export goGstBaseSrcAlloc
func goGstBaseSrcAlloc(src *C.GstBaseSrc, offset C.guint64, size C.guint, buf **C.GstBuffer) C.GstFlowReturn {
elem := gst.FromObjectUnsafePrivate(unsafe.Pointer(src))
elem := glib.FromObjectUnsafePrivate(unsafe.Pointer(src))
caller := elem.(interface {
Alloc(*GstBaseSrc, uint64, uint) (gst.FlowReturn, *gst.Buffer)
})
@@ -191,7 +192,7 @@ func goGstBaseSrcAlloc(src *C.GstBaseSrc, offset C.guint64, size C.guint, buf **
//export goGstBaseSrcFill
func goGstBaseSrcFill(src *C.GstBaseSrc, offset C.guint64, size C.guint, buf *C.GstBuffer) C.GstFlowReturn {
elem := gst.FromObjectUnsafePrivate(unsafe.Pointer(src))
elem := glib.FromObjectUnsafePrivate(unsafe.Pointer(src))
caller := elem.(interface {
Fill(*GstBaseSrc, uint64, uint, *gst.Buffer) gst.FlowReturn
})

View File

@@ -57,7 +57,7 @@ import (
var (
// ExtendsBaseSrc is an Extendable for extending a GstBaseSrc
ExtendsBaseSrc gst.Extendable = &extendsBaseSrc{parent: gst.ExtendsElement}
ExtendsBaseSrc glib.Extendable = &extendsBaseSrc{parent: gst.ExtendsElement}
)
// GstBaseSrcImpl is the documented interface for an element extending a GstBaseSrc. It does not have to
@@ -110,7 +110,7 @@ type GstBaseSrcImpl interface {
Fill(self *GstBaseSrc, offset uint64, size uint, buffer *gst.Buffer) gst.FlowReturn
}
type extendsBaseSrc struct{ parent gst.Extendable }
type extendsBaseSrc struct{ parent glib.Extendable }
func (e *extendsBaseSrc) Type() glib.Type { return glib.Type(C.gst_base_src_get_type()) }
func (e *extendsBaseSrc) ClassSize() int64 { return int64(C.sizeof_GstBaseSrcClass) }
@@ -118,7 +118,7 @@ func (e *extendsBaseSrc) InstanceSize() int64 { return int64(C.sizeof_GstBaseSrc
// InitClass iterates the methods provided by the element and overrides any provided
// in the virtual methods.
func (e *extendsBaseSrc) InitClass(klass unsafe.Pointer, elem gst.GoElement) {
func (e *extendsBaseSrc) InitClass(klass unsafe.Pointer, elem glib.GoObjectSubclass) {
e.parent.InitClass(klass, elem)
class := C.toGstBaseSrcClass(klass)

View File

@@ -14,7 +14,7 @@ import (
//export goGstBaseTransformAcceptCaps
func goGstBaseTransformAcceptCaps(self *C.GstBaseTransform, direction C.GstPadDirection, caps *C.GstCaps) C.gboolean {
elem := gst.FromObjectUnsafePrivate(unsafe.Pointer(self))
elem := glib.FromObjectUnsafePrivate(unsafe.Pointer(self))
caller := elem.(interface {
AcceptCaps(self *GstBaseTransform, direction gst.PadDirection, caps *gst.Caps) bool
})
@@ -23,7 +23,7 @@ func goGstBaseTransformAcceptCaps(self *C.GstBaseTransform, direction C.GstPadDi
//export goGstBaseTransformBeforeTransform
func goGstBaseTransformBeforeTransform(self *C.GstBaseTransform, buffer *C.GstBuffer) {
elem := gst.FromObjectUnsafePrivate(unsafe.Pointer(self))
elem := glib.FromObjectUnsafePrivate(unsafe.Pointer(self))
caller := elem.(interface {
BeforeTransform(self *GstBaseTransform, buffer *gst.Buffer)
})
@@ -32,7 +32,7 @@ func goGstBaseTransformBeforeTransform(self *C.GstBaseTransform, buffer *C.GstBu
//export goGstBaseTransformCopyMetadata
func goGstBaseTransformCopyMetadata(self *C.GstBaseTransform, input, outbuf *C.GstBuffer) C.gboolean {
elem := gst.FromObjectUnsafePrivate(unsafe.Pointer(self))
elem := glib.FromObjectUnsafePrivate(unsafe.Pointer(self))
caller := elem.(interface {
CopyMetadata(self *GstBaseTransform, input, output *gst.Buffer) bool
})
@@ -41,7 +41,7 @@ func goGstBaseTransformCopyMetadata(self *C.GstBaseTransform, input, outbuf *C.G
//export goGstBaseTransformDecideAllocation
func goGstBaseTransformDecideAllocation(self *C.GstBaseTransform, query *C.GstQuery) C.gboolean {
elem := gst.FromObjectUnsafePrivate(unsafe.Pointer(self))
elem := glib.FromObjectUnsafePrivate(unsafe.Pointer(self))
caller := elem.(interface {
DecideAllocation(self *GstBaseTransform, query *gst.Query) bool
})
@@ -50,7 +50,7 @@ func goGstBaseTransformDecideAllocation(self *C.GstBaseTransform, query *C.GstQu
//export goGstBaseTransformFilterMeta
func goGstBaseTransformFilterMeta(self *C.GstBaseTransform, query *C.GstQuery, api C.GType, params *C.GstStructure) C.gboolean {
elem := gst.FromObjectUnsafePrivate(unsafe.Pointer(self))
elem := glib.FromObjectUnsafePrivate(unsafe.Pointer(self))
caller := elem.(interface {
FilterMeta(self *GstBaseTransform, query *gst.Query, api glib.Type, params *gst.Structure) bool
})
@@ -64,7 +64,7 @@ func goGstBaseTransformFilterMeta(self *C.GstBaseTransform, query *C.GstQuery, a
//export goGstBaseTransformFixateCaps
func goGstBaseTransformFixateCaps(self *C.GstBaseTransform, direction C.GstPadDirection, caps, othercaps *C.GstCaps) *C.GstCaps {
elem := gst.FromObjectUnsafePrivate(unsafe.Pointer(self))
elem := glib.FromObjectUnsafePrivate(unsafe.Pointer(self))
caller := elem.(interface {
FixateCaps(self *GstBaseTransform, directon gst.PadDirection, caps *gst.Caps, othercaps *gst.Caps) *gst.Caps
})
@@ -82,7 +82,7 @@ func goGstBaseTransformFixateCaps(self *C.GstBaseTransform, direction C.GstPadDi
//export goGstBaseTransformGenerateOutput
func goGstBaseTransformGenerateOutput(self *C.GstBaseTransform, buf **C.GstBuffer) C.GstFlowReturn {
elem := gst.FromObjectUnsafePrivate(unsafe.Pointer(self))
elem := glib.FromObjectUnsafePrivate(unsafe.Pointer(self))
caller := elem.(interface {
GenerateOutput(self *GstBaseTransform) (gst.FlowReturn, *gst.Buffer)
})
@@ -95,7 +95,7 @@ func goGstBaseTransformGenerateOutput(self *C.GstBaseTransform, buf **C.GstBuffe
//export goGstBaseTransformGetUnitSize
func goGstBaseTransformGetUnitSize(self *C.GstBaseTransform, caps *C.GstCaps, size *C.gsize) C.gboolean {
elem := gst.FromObjectUnsafePrivate(unsafe.Pointer(self))
elem := glib.FromObjectUnsafePrivate(unsafe.Pointer(self))
caller := elem.(interface {
GetUnitSize(self *GstBaseTransform, caps *gst.Caps) (ok bool, size int64)
})
@@ -108,7 +108,7 @@ func goGstBaseTransformGetUnitSize(self *C.GstBaseTransform, caps *C.GstCaps, si
//export goGstBaseTransformPrepareOutputBuffer
func goGstBaseTransformPrepareOutputBuffer(self *C.GstBaseTransform, input *C.GstBuffer, outbuf **C.GstBuffer) C.GstFlowReturn {
elem := gst.FromObjectUnsafePrivate(unsafe.Pointer(self))
elem := glib.FromObjectUnsafePrivate(unsafe.Pointer(self))
caller := elem.(interface {
PrepareOutputBuffer(self *GstBaseTransform, input *gst.Buffer) (gst.FlowReturn, *gst.Buffer)
})
@@ -121,7 +121,7 @@ func goGstBaseTransformPrepareOutputBuffer(self *C.GstBaseTransform, input *C.Gs
//export goGstBaseTransformProposeAllocation
func goGstBaseTransformProposeAllocation(self *C.GstBaseTransform, decide, query *C.GstQuery) C.gboolean {
elem := gst.FromObjectUnsafePrivate(unsafe.Pointer(self))
elem := glib.FromObjectUnsafePrivate(unsafe.Pointer(self))
caller := elem.(interface {
ProposeAllocation(self *GstBaseTransform, decideQuery, query *gst.Query) bool
})
@@ -130,7 +130,7 @@ func goGstBaseTransformProposeAllocation(self *C.GstBaseTransform, decide, query
//export goGstBaseTransformQuery
func goGstBaseTransformQuery(self *C.GstBaseTransform, direction C.GstPadDirection, query *C.GstQuery) C.gboolean {
elem := gst.FromObjectUnsafePrivate(unsafe.Pointer(self))
elem := glib.FromObjectUnsafePrivate(unsafe.Pointer(self))
caller := elem.(interface {
Query(self *GstBaseTransform, direction gst.PadDirection, query *gst.Query) bool
})
@@ -139,7 +139,7 @@ func goGstBaseTransformQuery(self *C.GstBaseTransform, direction C.GstPadDirecti
//export goGstBaseTransformSetCaps
func goGstBaseTransformSetCaps(self *C.GstBaseTransform, incaps, outcaps *C.GstCaps) C.gboolean {
elem := gst.FromObjectUnsafePrivate(unsafe.Pointer(self))
elem := glib.FromObjectUnsafePrivate(unsafe.Pointer(self))
caller := elem.(interface {
SetCaps(self *GstBaseTransform, incaps, outcaps *gst.Caps) bool
})
@@ -152,7 +152,7 @@ func goGstBaseTransformSetCaps(self *C.GstBaseTransform, incaps, outcaps *C.GstC
//export goGstBaseTransformSinkEvent
func goGstBaseTransformSinkEvent(self *C.GstBaseTransform, event *C.GstEvent) C.gboolean {
elem := gst.FromObjectUnsafePrivate(unsafe.Pointer(self))
elem := glib.FromObjectUnsafePrivate(unsafe.Pointer(self))
caller := elem.(interface {
SinkEvent(self *GstBaseTransform, event *gst.Event) bool
})
@@ -161,7 +161,7 @@ func goGstBaseTransformSinkEvent(self *C.GstBaseTransform, event *C.GstEvent) C.
//export goGstBaseTransformSrcEvent
func goGstBaseTransformSrcEvent(self *C.GstBaseTransform, event *C.GstEvent) C.gboolean {
elem := gst.FromObjectUnsafePrivate(unsafe.Pointer(self))
elem := glib.FromObjectUnsafePrivate(unsafe.Pointer(self))
caller := elem.(interface {
SrcEvent(self *GstBaseTransform, event *gst.Event) bool
})
@@ -170,7 +170,7 @@ func goGstBaseTransformSrcEvent(self *C.GstBaseTransform, event *C.GstEvent) C.g
//export goGstBaseTransformStart
func goGstBaseTransformStart(self *C.GstBaseTransform) C.gboolean {
elem := gst.FromObjectUnsafePrivate(unsafe.Pointer(self))
elem := glib.FromObjectUnsafePrivate(unsafe.Pointer(self))
caller := elem.(interface {
Start(self *GstBaseTransform) bool
})
@@ -179,7 +179,7 @@ func goGstBaseTransformStart(self *C.GstBaseTransform) C.gboolean {
//export goGstBaseTransformStop
func goGstBaseTransformStop(self *C.GstBaseTransform) C.gboolean {
elem := gst.FromObjectUnsafePrivate(unsafe.Pointer(self))
elem := glib.FromObjectUnsafePrivate(unsafe.Pointer(self))
caller := elem.(interface {
Stop(self *GstBaseTransform) bool
})
@@ -188,7 +188,7 @@ func goGstBaseTransformStop(self *C.GstBaseTransform) C.gboolean {
//export goGstBaseTransformSubmitInputBuffer
func goGstBaseTransformSubmitInputBuffer(self *C.GstBaseTransform, isDiscont C.gboolean, input *C.GstBuffer) C.GstFlowReturn {
elem := gst.FromObjectUnsafePrivate(unsafe.Pointer(self))
elem := glib.FromObjectUnsafePrivate(unsafe.Pointer(self))
caller := elem.(interface {
SubmitInputBuffer(self *GstBaseTransform, isDiscont bool, input *gst.Buffer) gst.FlowReturn
})
@@ -201,7 +201,7 @@ func goGstBaseTransformSubmitInputBuffer(self *C.GstBaseTransform, isDiscont C.g
//export goGstBaseTransformTransform
func goGstBaseTransformTransform(self *C.GstBaseTransform, inbuf, outbuf *C.GstBuffer) C.GstFlowReturn {
elem := gst.FromObjectUnsafePrivate(unsafe.Pointer(self))
elem := glib.FromObjectUnsafePrivate(unsafe.Pointer(self))
caller := elem.(interface {
Transform(self *GstBaseTransform, inbuf, outbuf *gst.Buffer) gst.FlowReturn
})
@@ -214,7 +214,7 @@ func goGstBaseTransformTransform(self *C.GstBaseTransform, inbuf, outbuf *C.GstB
//export goGstBaseTransformTransformCaps
func goGstBaseTransformTransformCaps(self *C.GstBaseTransform, direction C.GstPadDirection, caps, filter *C.GstCaps) *C.GstCaps {
elem := gst.FromObjectUnsafePrivate(unsafe.Pointer(self))
elem := glib.FromObjectUnsafePrivate(unsafe.Pointer(self))
caller := elem.(interface {
TransformCaps(self *GstBaseTransform, direction gst.PadDirection, caps, filter *gst.Caps) *gst.Caps
})
@@ -232,7 +232,7 @@ func goGstBaseTransformTransformCaps(self *C.GstBaseTransform, direction C.GstPa
//export goGstBaseTransformTransformIP
func goGstBaseTransformTransformIP(self *C.GstBaseTransform, buf *C.GstBuffer) C.GstFlowReturn {
elem := gst.FromObjectUnsafePrivate(unsafe.Pointer(self))
elem := glib.FromObjectUnsafePrivate(unsafe.Pointer(self))
caller := elem.(interface {
TransformIP(self *GstBaseTransform, buf *gst.Buffer) gst.FlowReturn
})
@@ -244,7 +244,7 @@ func goGstBaseTransformTransformIP(self *C.GstBaseTransform, buf *C.GstBuffer) C
//export goGstBaseTransformTransformMeta
func goGstBaseTransformTransformMeta(self *C.GstBaseTransform, outbuf *C.GstBuffer, meta *C.GstMeta, inbuf *C.GstBuffer) C.gboolean {
elem := gst.FromObjectUnsafePrivate(unsafe.Pointer(self))
elem := glib.FromObjectUnsafePrivate(unsafe.Pointer(self))
caller := elem.(interface {
TransformMeta(self *GstBaseTransform, outbuf *gst.Buffer, meta *gst.Meta, inbuf *gst.Buffer) bool
})
@@ -258,7 +258,7 @@ func goGstBaseTransformTransformMeta(self *C.GstBaseTransform, outbuf *C.GstBuff
//export goGstBaseTransformTransformSize
func goGstBaseTransformTransformSize(self *C.GstBaseTransform, direction C.GstPadDirection, caps *C.GstCaps, size C.gsize, othercaps *C.GstCaps, outsize *C.gsize) C.gboolean {
elem := gst.FromObjectUnsafePrivate(unsafe.Pointer(self))
elem := glib.FromObjectUnsafePrivate(unsafe.Pointer(self))
caller := elem.(interface {
TransformSize(self *GstBaseTransform, direction gst.PadDirection, caps *gst.Caps, size int64, othercaps *gst.Caps) (ok bool, othersize int64)
})

View File

@@ -61,7 +61,7 @@ import (
var (
// ExtendsBaseTransform is an Extendable for extending a GstBaseTransform
ExtendsBaseTransform gst.Extendable = &extendsBaseTransform{parent: gst.ExtendsElement}
ExtendsBaseTransform glib.Extendable = &extendsBaseTransform{parent: gst.ExtendsElement}
)
// GstBaseTransformImpl is the interface for an element extending a GstBaseTransform.
@@ -151,13 +151,13 @@ type GstBaseTransformImpl interface {
TransformSize(self *GstBaseTransform, direction gst.PadDirection, caps *gst.Caps, size int64, othercaps *gst.Caps) (ok bool, othersize int64)
}
type extendsBaseTransform struct{ parent gst.Extendable }
type extendsBaseTransform struct{ parent glib.Extendable }
func (e *extendsBaseTransform) Type() glib.Type { return glib.Type(C.gst_base_transform_get_type()) }
func (e *extendsBaseTransform) ClassSize() int64 { return int64(C.sizeof_GstBaseTransformClass) }
func (e *extendsBaseTransform) InstanceSize() int64 { return int64(C.sizeof_GstBaseTransform) }
func (e *extendsBaseTransform) InitClass(klass unsafe.Pointer, elem gst.GoElement) {
func (e *extendsBaseTransform) InitClass(klass unsafe.Pointer, elem glib.GoObjectSubclass) {
e.parent.InitClass(klass, elem)
class := C.toGstBaseTransformClass(klass)

View File

@@ -8,12 +8,13 @@ import "C"
import (
"unsafe"
"github.com/tinyzimmer/go-glib/glib"
"github.com/tinyzimmer/go-gst/gst"
)
//export goGstPushSrcAlloc
func goGstPushSrcAlloc(src *C.GstPushSrc, buf **C.GstBuffer) C.GstFlowReturn {
caller := gst.FromObjectUnsafePrivate(unsafe.Pointer(src)).(interface {
caller := glib.FromObjectUnsafePrivate(unsafe.Pointer(src)).(interface {
Alloc(*GstPushSrc) (gst.FlowReturn, *gst.Buffer)
})
ret, buffer := caller.Alloc(wrapGstPushSrc(src))
@@ -26,7 +27,7 @@ func goGstPushSrcAlloc(src *C.GstPushSrc, buf **C.GstBuffer) C.GstFlowReturn {
//export goGstPushSrcCreate
func goGstPushSrcCreate(src *C.GstPushSrc, buf **C.GstBuffer) C.GstFlowReturn {
caller := gst.FromObjectUnsafePrivate(unsafe.Pointer(src)).(interface {
caller := glib.FromObjectUnsafePrivate(unsafe.Pointer(src)).(interface {
Create(*GstPushSrc) (gst.FlowReturn, *gst.Buffer)
})
ret, buffer := caller.Create(wrapGstPushSrc(src))
@@ -39,7 +40,7 @@ func goGstPushSrcCreate(src *C.GstPushSrc, buf **C.GstBuffer) C.GstFlowReturn {
//export goGstPushSrcFill
func goGstPushSrcFill(src *C.GstPushSrc, buf *C.GstBuffer) C.GstFlowReturn {
caller := gst.FromObjectUnsafePrivate(unsafe.Pointer(src)).(interface {
caller := glib.FromObjectUnsafePrivate(unsafe.Pointer(src)).(interface {
Fill(*GstPushSrc, *gst.Buffer) gst.FlowReturn
})
return C.GstFlowReturn(caller.Fill(wrapGstPushSrc(src), gst.FromGstBufferUnsafe(unsafe.Pointer(buf))))

View File

@@ -23,7 +23,7 @@ import (
var (
// ExtendsPushSrc is an Extendable for extending a GstPushSrc
ExtendsPushSrc gst.Extendable = &extendsPushSrc{parent: ExtendsBaseSrc}
ExtendsPushSrc glib.Extendable = &extendsPushSrc{parent: ExtendsBaseSrc}
)
// GstPushSrcImpl is the documented interface for an element extending a GstPushSrc. It does not have to
@@ -42,13 +42,13 @@ type GstPushSrcImpl interface {
Fill(*GstPushSrc, *gst.Buffer) gst.FlowReturn
}
type extendsPushSrc struct{ parent gst.Extendable }
type extendsPushSrc struct{ parent glib.Extendable }
func (e *extendsPushSrc) Type() glib.Type { return glib.Type(C.gst_push_src_get_type()) }
func (e *extendsPushSrc) ClassSize() int64 { return int64(C.sizeof_GstPushSrcClass) }
func (e *extendsPushSrc) InstanceSize() int64 { return int64(C.sizeof_GstPushSrc) }
func (e *extendsPushSrc) InitClass(klass unsafe.Pointer, elem gst.GoElement) {
func (e *extendsPushSrc) InitClass(klass unsafe.Pointer, elem glib.GoObjectSubclass) {
e.parent.InitClass(klass, elem)
srcClass := C.toGstPushSrcClass(klass)

View File

@@ -10,7 +10,6 @@ package gst
import "C"
import (
"reflect"
"time"
"unsafe"
@@ -245,38 +244,6 @@ func goGlobalPluginInit(plugin *C.GstPlugin) C.gboolean {
return gboolean(globalPluginInit(wrapPlugin(&glib.Object{GObject: glib.ToGObject(unsafe.Pointer(plugin))})))
}
//export goClassInit
func goClassInit(klass C.gpointer, klassData C.gpointer) {
registerMutex.Lock()
defer registerMutex.Unlock()
ptr := unsafe.Pointer(klassData)
iface := gopointer.Restore(ptr)
defer gopointer.Unref(ptr)
data := iface.(*classData)
registeredClasses[klass] = data.elem
data.ext.InitClass(unsafe.Pointer(klass), data.elem)
C.g_type_class_add_private(klass, C.gsize(unsafe.Sizeof(uintptr(0))))
data.elem.ClassInit(wrapElementClass(klass))
}
//export goInstanceInit
func goInstanceInit(obj *C.GTypeInstance, klass C.gpointer) {
registerMutex.Lock()
defer registerMutex.Unlock()
elem := registeredClasses[klass].New()
registeredClasses[klass] = elem
ptr := gopointer.Save(elem)
private := C.g_type_instance_get_private(obj, registeredTypes[reflect.TypeOf(registeredClasses[klass]).String()])
C.memcpy(unsafe.Pointer(private), unsafe.Pointer(&ptr), C.gsize(unsafe.Sizeof(uintptr(0))))
}
//export goURIHdlrGetURIType
func goURIHdlrGetURIType(gtype C.GType) C.GstURIType {
return C.GstURIType(globalURIHdlr.GetURIType())
@@ -297,52 +264,16 @@ func goURIHdlrGetProtocols(gtype C.GType) **C.gchar {
//export goURIHdlrGetURI
func goURIHdlrGetURI(hdlr *C.GstURIHandler) *C.gchar {
iface := FromObjectUnsafePrivate(unsafe.Pointer(hdlr))
iface := glib.FromObjectUnsafePrivate(unsafe.Pointer(hdlr))
return (*C.gchar)(unsafe.Pointer(C.CString(iface.(URIHandler).GetURI())))
}
//export goURIHdlrSetURI
func goURIHdlrSetURI(hdlr *C.GstURIHandler, uri *C.gchar, gerr **C.GError) C.gboolean {
iface := FromObjectUnsafePrivate(unsafe.Pointer(hdlr))
iface := glib.FromObjectUnsafePrivate(unsafe.Pointer(hdlr))
ok, err := iface.(URIHandler).SetURI(C.GoString(uri))
if err != nil {
C.g_set_error_literal(gerr, DomainLibrary.toQuark(), C.gint(LibraryErrorSettings), C.CString(err.Error()))
}
return gboolean(ok)
}
//export goObjectSetProperty
func goObjectSetProperty(obj *C.GObject, propID C.guint, val *C.GValue, param *C.GParamSpec) {
iface := FromObjectUnsafePrivate(unsafe.Pointer(obj)).(interface {
SetProperty(obj *Object, id uint, value *glib.Value)
})
iface.SetProperty(wrapObject(toGObject(unsafe.Pointer(obj))), uint(propID-1), glib.ValueFromNative(unsafe.Pointer(val)))
}
//export goObjectGetProperty
func goObjectGetProperty(obj *C.GObject, propID C.guint, value *C.GValue, param *C.GParamSpec) {
iface := FromObjectUnsafePrivate(unsafe.Pointer(obj)).(interface {
GetProperty(obj *Object, id uint) *glib.Value
})
val := iface.GetProperty(wrapObject(toGObject(unsafe.Pointer(obj))), uint(propID-1))
if val == nil {
return
}
C.g_value_copy((*C.GValue)(unsafe.Pointer(val.GValue)), value)
}
//export goObjectConstructed
func goObjectConstructed(obj *C.GObject) {
iface := FromObjectUnsafePrivate(unsafe.Pointer(obj)).(interface {
Constructed(*Object)
})
iface.Constructed(wrapObject(toGObject(unsafe.Pointer(obj))))
}
//export goObjectFinalize
func goObjectFinalize(obj *C.GObject, klass C.gpointer) {
registerMutex.Lock()
defer registerMutex.Unlock()
delete(registeredClasses, klass)
gopointer.Unref(privateFromObj(unsafe.Pointer(obj)))
}

View File

@@ -1,35 +0,0 @@
package gst
// GError is a Go wrapper for a C GError in the context of GStreamer. It implements the error interface
// and provides additional functions for retrieving debug strings and details.
type GError struct {
errMsg, debugStr string
structure *Structure
// used for message constructors
code ErrorCode
}
// Message is an alias to `Error()`. It's for clarity when this object
// is parsed from a `GST_MESSAGE_INFO` or `GST_MESSAGE_WARNING`.
func (e *GError) Message() string { return e.Error() }
// Error implements the error interface and returns the error message.
func (e *GError) Error() string { return e.errMsg }
// DebugString returns any debug info alongside the error.
func (e *GError) DebugString() string { return e.debugStr }
// Structure returns the structure of the error message which may contain additional metadata.
func (e *GError) Structure() *Structure { return e.structure }
// Code returns the error code of the error message.
func (e *GError) Code() ErrorCode { return e.code }
// NewGError wraps the given error inside a GError (to be used with message constructors).
func NewGError(code ErrorCode, err error) *GError {
return &GError{
errMsg: err.Error(),
code: code,
}
}

View File

@@ -1,117 +0,0 @@
package gst
/*
#include <glib.h>
*/
import "C"
// MainLoop is a go representation of a GMainLoop. It can be used to block execution
// while a pipeline is running, and also allows for event sources and signals to be used
// across gstreamer objects.
type MainLoop struct {
ptr *C.GMainLoop
}
// NewMainLoop creates a new GMainLoop. If ctx is nil then the default context is used.
// If isRunning is true the loop will automatically start, however, this function will not
// block. To block on the loop itself you will still need to call MainLoop.Run().
//
// A MainLoop is required when wishing to handle signals to/from elements asynchronously.
// Otherwise you will need to iterate on the DefaultMainContext (or an external created one)
// manually.
func NewMainLoop(ctx *MainContext, isRunning bool) *MainLoop {
var gCtx *C.GMainContext
if ctx != nil {
gCtx = ctx.Instance()
}
loop := C.g_main_loop_new(gCtx, gboolean(isRunning))
return wrapMainLoop(loop)
}
// Instance returns the underlying GMainLoop instance.
func (m *MainLoop) Instance() *C.GMainLoop { return m.ptr }
// Ref increases the ref count on the main loop by one. It returns the original main loop
// for convenience in return functions.
func (m *MainLoop) Ref() *MainLoop {
return wrapMainLoop(C.g_main_loop_ref(m.Instance()))
}
// Unref decreases the reference count on a GMainLoop object by one. If the result is zero,
// it frees the loop and all associated memory.
func (m *MainLoop) Unref() { C.g_main_loop_unref(m.Instance()) }
// Run a main loop until Quit() is called on the loop. If this is called from the thread of
// the loop's GMainContext, it will process events from the loop, otherwise it will simply wait.
func (m *MainLoop) Run() { C.g_main_loop_run(m.Instance()) }
// RunError is an alias to Run() except it returns nil as soon as the main loop quits. This is for
// convenience when wanting to use `return mainLoop.RunError()` at the end of a function that
// expects an error.
func (m *MainLoop) RunError() error {
m.Run()
return nil
}
// Quit stops a MainLoop from running. Any calls to Run() for the loop will return. Note that
// sources that have already been dispatched when Quit() is called will still be executed.
func (m *MainLoop) Quit() { C.g_main_loop_quit(m.Instance()) }
// IsRunning returns true if this main loop is currently running.
func (m *MainLoop) IsRunning() bool { return gobool(C.g_main_loop_is_running(m.Instance())) }
// GetContext returns the GMainContext for this loop.
func (m *MainLoop) GetContext() *MainContext {
ctx := C.g_main_loop_get_context(m.Instance())
return wrapMainContext(ctx)
}
// MainContext is a go representation of a GMainContext. Most of the time you will just
// want to use the default GMainContext which can be specified either via DefaultMainContext()
// or by passing nil to any function that requires it.
type MainContext struct {
ptr *C.GMainContext
}
// NewMainContext returns a new main context. This object is still not fully implemented
// and most of the time you will want to use the DefaultMainContext, or nil, when required.
func NewMainContext() *MainContext {
return wrapMainContext(C.g_main_context_new())
}
// DefaultMainContext returns the default main context.
func DefaultMainContext() *MainContext {
return wrapMainContext(C.g_main_context_default())
}
// Instance returns the underlying GMainContext instance.
func (m *MainContext) Instance() *C.GMainContext { return m.ptr }
// Ref increases the reference count on a GMainContext object by one.
func (m *MainContext) Ref() *MainContext {
return wrapMainContext(C.g_main_context_ref(m.Instance()))
}
// Unref decreases the reference count on a GMainContext object by one.
// If the result is zero, it frees the context and all associated memory.
func (m *MainContext) Unref() { C.g_main_context_unref(m.Instance()) }
// Iteration runs a single iteration for the given main loop. This involves checking
// to see if any event sources are ready to be processed.
//
// If no events sources are ready AND mayBlock is TRUE, it waits for a source to become ready,
// then dispatches the highest priority events sources that are ready.
//
// Otherwise, if mayBlock is FALSE it does not wait for sources to become ready, only those
// highest priority events sources will be dispatched (if any), and then the function will return.
//
// The return value reflects whether or not any event sources were dispatched.
func (m *MainContext) Iteration(mayBlock bool) bool {
return gobool(C.g_main_context_iteration(m.Instance(), gboolean(mayBlock)))
}
// Pending checks if any sources have pending events for this context.
func (m *MainContext) Pending() bool { return gobool(C.g_main_context_pending(m.Instance())) }
// Wakeup either stops a currently running Iteration() or the next Iteration() from blocking.
func (m *MainContext) Wakeup() { C.g_main_context_wakeup(m.Instance()) }

View File

@@ -1,79 +0,0 @@
package gst
/*
#include "gst.go.h"
extern void goObjectSetProperty (GObject * object, guint property_id, const GValue * value, GParamSpec *pspec);
extern void goObjectGetProperty (GObject * object, guint property_id, GValue * value, GParamSpec * pspec);
extern void goObjectConstructed (GObject * object);
extern void goObjectFinalize (GObject * object, gpointer klass);
void objectFinalize (GObject * object)
{
GObjectClass *parent = g_type_class_peek_parent((G_OBJECT_GET_CLASS(object)));
goObjectFinalize(object, G_OBJECT_GET_CLASS(object));
parent->finalize(object);
}
void objectConstructed (GObject * object)
{
GObjectClass *parent = g_type_class_peek_parent((G_OBJECT_GET_CLASS(object)));
goObjectConstructed(object);
parent->constructed(object);
}
void setGObjectClassSetProperty (void * klass) { ((GObjectClass *)klass)->set_property = goObjectSetProperty; }
void setGObjectClassGetProperty (void * klass) { ((GObjectClass *)klass)->get_property = goObjectGetProperty; }
void setGObjectClassConstructed (void * klass) { ((GObjectClass *)klass)->constructed = objectConstructed; }
void setGObjectClassFinalize (void * klass) { ((GObjectClass *)klass)->finalize = objectFinalize; }
*/
import "C"
import (
"unsafe"
"github.com/tinyzimmer/go-glib/glib"
)
// GoObject is an interface that abstracts on the GObject. In almost all cases at least SetProperty and GetProperty
// should be implemented by elements built from the go bindings.
type GoObject interface {
// SetProperty should set the value of the property with the given id. ID is the index+1 of the parameter
// in the order it was registered.
SetProperty(obj *Object, id uint, value *glib.Value)
// GetProperty should retrieve the value of the property with the given id. ID is the index+1 of the parameter
// in the order it was registered.
GetProperty(obj *Object, id uint) *glib.Value
// Constructed is called when the Object has finished setting up.
Constructed(*Object)
}
// ExtendsObject signifies a GoElement that extends a GObject. It is the base Extendable
// that all other implementations derive from.
var ExtendsObject Extendable = &extendObject{}
type extendObject struct{}
func (e *extendObject) Type() glib.Type { return glib.Type(C.g_object_get_type()) }
func (e *extendObject) ClassSize() int64 { return int64(C.sizeof_GObjectClass) }
func (e *extendObject) InstanceSize() int64 { return int64(C.sizeof_GObject) }
func (e *extendObject) InitClass(klass unsafe.Pointer, elem GoElement) {
C.setGObjectClassFinalize(klass)
if _, ok := elem.(interface {
SetProperty(obj *Object, id uint, value *glib.Value)
}); ok {
C.setGObjectClassSetProperty(klass)
}
if _, ok := elem.(interface {
GetProperty(obj *Object, id uint) *glib.Value
}); ok {
C.setGObjectClassGetProperty(klass)
}
if _, ok := elem.(interface {
Constructed(*Object)
}); ok {
C.setGObjectClassConstructed(klass)
}
}

View File

@@ -1,75 +0,0 @@
package gst
/*
#include "gst.go.h"
extern GstURIType goURIHdlrGetURIType (GType type);
extern const gchar * const * goURIHdlrGetProtocols (GType type);
extern gchar * goURIHdlrGetURI (GstURIHandler * handler);
extern gboolean goURIHdlrSetURI (GstURIHandler * handler,
const gchar * uri,
GError ** error);
void uriHandlerInit (gpointer iface, gpointer iface_data)
{
((GstURIHandlerInterface*)iface)->get_type = goURIHdlrGetURIType;
((GstURIHandlerInterface*)iface)->get_protocols = goURIHdlrGetProtocols;
((GstURIHandlerInterface*)iface)->get_uri = goURIHdlrGetURI;
((GstURIHandlerInterface*)iface)->set_uri = goURIHdlrSetURI;
}
*/
import "C"
import (
"unsafe"
"github.com/tinyzimmer/go-glib/glib"
)
// ObjectClass is a loose binding around the glib GObjectClass.
// It forms the base of a GstElementClass.
type ObjectClass struct {
ptr *C.GObjectClass
}
// Unsafe is a convenience wrapper to return the unsafe.Pointer of the underlying C instance.
func (o *ObjectClass) Unsafe() unsafe.Pointer { return unsafe.Pointer(o.ptr) }
// Instance returns the underlying C GObjectClass pointer
func (o *ObjectClass) Instance() *C.GObjectClass { return o.ptr }
// InstallProperties will install the given ParameterSpecs to the object class.
// They will be IDed in the order they are provided.
func (o *ObjectClass) InstallProperties(params []*ParamSpec) {
for idx, prop := range params {
C.g_object_class_install_property(
o.Instance(),
C.guint(idx+1),
prop.paramSpec,
)
}
}
// TypeInstance is a loose binding around the glib GTypeInstance. It exposes methods required
// to register the various capabilities of an element.
type TypeInstance struct {
gtype C.GType
gotype GoElement
}
// AddInterface will add an interface implementation for the type referenced by this object.
func (t *TypeInstance) AddInterface(iface glib.Type) {
ifaceInfo := C.GInterfaceInfo{
interface_data: nil,
interface_finalize: nil,
}
switch iface {
case InterfaceURIHandler:
globalURIHdlr = t.gotype.(URIHandler)
ifaceInfo.interface_init = C.GInterfaceInitFunc(C.uriHandlerInit)
}
C.g_type_add_interface_static(
(C.GType)(t.gtype),
(C.GType)(iface),
&ifaceInfo,
)
}

View File

@@ -1,244 +0,0 @@
package gst
// #include "gst.go.h"
import "C"
import (
"strings"
"unsafe"
"github.com/tinyzimmer/go-glib/glib"
)
// ParamSpec is a go representation of a C GParamSpec
type ParamSpec struct{ paramSpec *C.GParamSpec }
// Name returns the name of this parameter.
func (p *ParamSpec) Name() string {
return C.GoString(C.g_param_spec_get_name(p.paramSpec))
}
// Blurb returns the blurb for this parameter.
func (p *ParamSpec) Blurb() string {
return C.GoString(C.g_param_spec_get_blurb(p.paramSpec))
}
// Flags returns the flags for this parameter.
func (p *ParamSpec) Flags() ParameterFlags {
return ParameterFlags(p.paramSpec.flags)
}
// ValueType returns the GType for the value inside this parameter.
func (p *ParamSpec) ValueType() glib.Type {
return glib.Type(p.paramSpec.value_type)
}
// OwnerType returns the Gtype for the owner of this parameter.
func (p *ParamSpec) OwnerType() glib.Type {
return glib.Type(p.paramSpec.owner_type)
}
// Unref the underlying paramater spec.
func (p *ParamSpec) Unref() { C.g_param_spec_unref(p.paramSpec) }
// UIntRange returns the range of the Uint stored in this parameter spec.
func (p *ParamSpec) UIntRange() (uint, uint) {
paramUint := C.getParamUInt(p.paramSpec)
return uint(paramUint.minimum), uint(paramUint.maximum)
}
// IntRange returns the range of the Int stored in this parameter spec.
func (p *ParamSpec) IntRange() (int, int) {
paramUint := C.getParamInt(p.paramSpec)
return int(paramUint.minimum), int(paramUint.maximum)
}
// UInt64Range returns the range of the Uint64 stored in this parameter spec.
func (p *ParamSpec) UInt64Range() (uint64, uint64) {
paramUint := C.getParamUInt64(p.paramSpec)
return uint64(paramUint.minimum), uint64(paramUint.maximum)
}
// Int64Range returns the range of the Int64 stored in this parameter spec.
func (p *ParamSpec) Int64Range() (int64, int64) {
paramUint := C.getParamInt64(p.paramSpec)
return int64(paramUint.minimum), int64(paramUint.maximum)
}
// FloatRange returns the range of the Float stored in this parameter spec.
func (p *ParamSpec) FloatRange() (float64, float64) {
paramUint := C.getParamFloat(p.paramSpec)
return float64(paramUint.minimum), float64(paramUint.maximum)
}
// DoubleRange returns the range of the Double stored in this parameter spec.
func (p *ParamSpec) DoubleRange() (float64, float64) {
paramUint := C.getParamDouble(p.paramSpec)
return float64(paramUint.minimum), float64(paramUint.maximum)
}
// IsCaps returns true if this parameter contains a caps object.
func (p *ParamSpec) IsCaps() bool { return gobool(C.isParamSpecTypeCaps(p.paramSpec)) }
// IsEnum returns true if this parameter contains an enum.
func (p *ParamSpec) IsEnum() bool { return gobool(C.isParamSpecEnum(p.paramSpec)) }
// IsFlags returns true if this paramater contains flags.
func (p *ParamSpec) IsFlags() bool { return gobool(C.isParamSpecFlags(p.paramSpec)) }
// IsObject returns true if this parameter contains an object.
func (p *ParamSpec) IsObject() bool { return gobool(C.isParamSpecObject(p.paramSpec)) }
// IsBoxed returns true if this parameter contains a boxed object.
func (p *ParamSpec) IsBoxed() bool { return gobool(C.isParamSpecBoxed(p.paramSpec)) }
// IsPointer returns true if this paramater contains a pointer.
func (p *ParamSpec) IsPointer() bool { return gobool(C.isParamSpecPointer(p.paramSpec)) }
// IsFraction returns true if this parameter contains a fraction.
func (p *ParamSpec) IsFraction() bool { return gobool(C.isParamSpecFraction(p.paramSpec)) }
// IsGstArray returns true if this parameter contains a Gst array.
func (p *ParamSpec) IsGstArray() bool { return gobool(C.isParamSpecGstArray(p.paramSpec)) }
// EnumValue is a go representation of a GEnumValue
type EnumValue struct {
Value int
ValueNick, ValueName string
}
// GetEnumValues returns the possible enum values for this parameter.
func (p *ParamSpec) GetEnumValues() []*EnumValue {
var gsize C.guint
gEnumValues := C.getEnumValues(p.paramSpec, &gsize)
size := int(gsize)
out := make([]*EnumValue, size)
for idx, enumVal := range (*[1 << 30]C.GEnumValue)(unsafe.Pointer(gEnumValues))[:size:size] {
out[idx] = &EnumValue{
Value: int(enumVal.value),
ValueNick: C.GoString(enumVal.value_nick),
ValueName: C.GoString(enumVal.value_name),
}
}
return out
}
// FlagsValue is a go representation of GFlagsValue
type FlagsValue struct {
Value int
ValueName, ValueNick string
}
// GetFlagValues returns the possible flags for this parameter.
func (p *ParamSpec) GetFlagValues() []*FlagsValue {
var gSize C.guint
gFlags := C.getParamSpecFlags(p.paramSpec, &gSize)
size := int(gSize)
out := make([]*FlagsValue, size)
for idx, flag := range (*[1 << 30]C.GFlagsValue)(unsafe.Pointer(gFlags))[:size:size] {
out[idx] = &FlagsValue{
Value: int(flag.value),
ValueNick: C.GoString(flag.value_nick),
ValueName: C.GoString(flag.value_name),
}
}
return out
}
// ParameterFlags is a go cast of GParamFlags.
type ParameterFlags int
// Has returns true if these flags contain the provided ones.
func (p ParameterFlags) Has(b ParameterFlags) bool { return p&b != 0 }
// Type casting of GParamFlags
const (
ParameterReadable ParameterFlags = C.G_PARAM_READABLE // the parameter is readable
ParameterWritable = C.G_PARAM_WRITABLE // the parameter is writable
ParameterReadWrite = ParameterReadable | ParameterWritable
ParameterConstruct = C.G_PARAM_CONSTRUCT // the parameter will be set upon object construction
ParameterConstructOnly = C.G_PARAM_CONSTRUCT_ONLY // the parameter can only be set upon object construction
ParameterLaxValidation = C.G_PARAM_LAX_VALIDATION // upon parameter conversion (see g_param_value_convert()) strict validation is not required
ParameterStaticName = C.G_PARAM_STATIC_NAME // the string used as name when constructing the parameter is guaranteed to remain valid and unmodified for the lifetime of the parameter. Since 2.8
ParameterStaticNick = C.G_PARAM_STATIC_NICK // the string used as nick when constructing the parameter is guaranteed to remain valid and unmmodified for the lifetime of the parameter. Since 2.8
ParameterStaticBlurb = C.G_PARAM_STATIC_BLURB // the string used as blurb when constructing the parameter is guaranteed to remain valid and unmodified for the lifetime of the parameter. Since 2.8
ParameterExplicitNotify = C.G_PARAM_EXPLICIT_NOTIFY // calls to g_object_set_property() for this property will not automatically result in a "notify" signal being emitted: the implementation must call g_object_notify() themselves in case the property actually changes. Since: 2.42.
ParameterDeprecated = C.G_PARAM_DEPRECATED // the parameter is deprecated and will be removed in a future version. A warning will be generated if it is used while running with G_ENABLE_DIAGNOSTIC=1. Since 2.26
ParameterControllable = C.GST_PARAM_CONTROLLABLE
ParameterMutablePlaying = C.GST_PARAM_MUTABLE_PLAYING
ParameterMutablePaused = C.GST_PARAM_MUTABLE_PAUSED
ParameterMutableReady = C.GST_PARAM_MUTABLE_READY
)
var allFlags = []ParameterFlags{
ParameterReadable,
ParameterWritable,
ParameterConstruct,
ParameterConstructOnly,
ParameterLaxValidation,
ParameterStaticName,
ParameterStaticNick,
ParameterStaticBlurb,
ParameterExplicitNotify,
ParameterDeprecated,
ParameterControllable,
ParameterMutablePlaying,
ParameterMutablePaused,
ParameterMutableReady,
}
var allFlagStrings = []string{
"readable",
"writable",
"construct",
"construct only",
"lax validation",
"deprecated",
"static name",
"static nick",
"static blurb",
"explicitly notify",
"deprecated",
"controllable",
"changeable in NULL, READY, PAUSED or PLAYING state",
"changeable only in NULL, READY or PAUSED state",
"changeable only in NULL or READY state",
}
func (p ParameterFlags) String() string {
out := make([]string, 0)
for idx, param := range allFlags {
if p.Has(param) {
out = append(out, allFlagStrings[idx])
}
}
return strings.Join(out, ", ")
}
// GstFlagsString returns a string of the flags that are relevant specifically
// to gstreamer.
func (p ParameterFlags) GstFlagsString() string {
out := make([]string, 0)
if p.Has(ParameterReadable) {
out = append(out, "readable")
}
if p.Has(ParameterWritable) {
out = append(out, "writable")
}
if p.Has(ParameterControllable) {
out = append(out, "controllable")
}
if p.Has(ParameterMutablePlaying) {
out = append(out, "changeable in NULL, READY, PAUSED or PLAYING state")
}
if p.Has(ParameterMutablePaused) {
out = append(out, "changeable only in NULL, READY or PAUSED state")
}
if p.Has(ParameterMutableReady) {
out = append(out, "changeable only in NULL or READY state")
}
if p.Has(ParameterDeprecated) {
out = append(out, "deprecated")
}
return strings.Join(out, ", ")
}

View File

@@ -1,131 +0,0 @@
package gst
// #include "gst.go.h"
import "C"
import "github.com/tinyzimmer/go-glib/glib"
// NewStringParam returns a new ParamSpec that will hold a string value.
func NewStringParam(name, nick, blurb string, defaultValue *string, flags ParameterFlags) *ParamSpec {
var cdefault *C.gchar
if defaultValue != nil {
cdefault = C.CString(*defaultValue)
}
paramSpec := C.g_param_spec_string(
(*C.gchar)(C.CString(name)),
(*C.gchar)(C.CString(nick)),
(*C.gchar)(C.CString(blurb)),
(*C.gchar)(cdefault),
C.GParamFlags(flags),
)
return &ParamSpec{paramSpec: paramSpec}
}
// NewBoolParam creates a new ParamSpec that will hold a boolean value.
func NewBoolParam(name, nick, blurb string, defaultValue bool, flags ParameterFlags) *ParamSpec {
paramSpec := C.g_param_spec_boolean(
(*C.gchar)(C.CString(name)),
(*C.gchar)(C.CString(nick)),
(*C.gchar)(C.CString(blurb)),
gboolean(defaultValue),
C.GParamFlags(flags),
)
return &ParamSpec{paramSpec: paramSpec}
}
// NewIntParam creates a new ParamSpec that will hold a signed integer value.
func NewIntParam(name, nick, blurb string, min, max, defaultValue int, flags ParameterFlags) *ParamSpec {
paramSpec := C.g_param_spec_int(
(*C.gchar)(C.CString(name)),
(*C.gchar)(C.CString(nick)),
(*C.gchar)(C.CString(blurb)),
C.gint(min),
C.gint(max),
C.gint(defaultValue),
C.GParamFlags(flags),
)
return &ParamSpec{paramSpec: paramSpec}
}
// NewUintParam creates a new ParamSpec that will hold an unsigned integer value.
func NewUintParam(name, nick, blurb string, min, max, defaultValue uint, flags ParameterFlags) *ParamSpec {
paramSpec := C.g_param_spec_uint(
(*C.gchar)(C.CString(name)),
(*C.gchar)(C.CString(nick)),
(*C.gchar)(C.CString(blurb)),
C.guint(min),
C.guint(max),
C.guint(defaultValue),
C.GParamFlags(flags),
)
return &ParamSpec{paramSpec: paramSpec}
}
// NewInt64Param creates a new ParamSpec that will hold a signed 64-bit integer value.
func NewInt64Param(name, nick, blurb string, min, max, defaultValue int64, flags ParameterFlags) *ParamSpec {
paramSpec := C.g_param_spec_int64(
(*C.gchar)(C.CString(name)),
(*C.gchar)(C.CString(nick)),
(*C.gchar)(C.CString(blurb)),
C.gint64(min),
C.gint64(max),
C.gint64(defaultValue),
C.GParamFlags(flags),
)
return &ParamSpec{paramSpec: paramSpec}
}
// NewUint64Param creates a new ParamSpec that will hold an unsigned 64-bit integer value.
func NewUint64Param(name, nick, blurb string, min, max, defaultValue uint64, flags ParameterFlags) *ParamSpec {
paramSpec := C.g_param_spec_uint64(
(*C.gchar)(C.CString(name)),
(*C.gchar)(C.CString(nick)),
(*C.gchar)(C.CString(blurb)),
C.guint64(min),
C.guint64(max),
C.guint64(defaultValue),
C.GParamFlags(flags),
)
return &ParamSpec{paramSpec: paramSpec}
}
// NewFloat32Param creates a new ParamSpec that will hold a 32-bit float value.
func NewFloat32Param(name, nick, blurb string, min, max, defaultValue float32, flags ParameterFlags) *ParamSpec {
paramSpec := C.g_param_spec_float(
(*C.gchar)(C.CString(name)),
(*C.gchar)(C.CString(nick)),
(*C.gchar)(C.CString(blurb)),
C.gfloat(min),
C.gfloat(max),
C.gfloat(defaultValue),
C.GParamFlags(flags),
)
return &ParamSpec{paramSpec: paramSpec}
}
// NewFloat64Param creates a new ParamSpec that will hold a 64-bit float value.
func NewFloat64Param(name, nick, blurb string, min, max, defaultValue float64, flags ParameterFlags) *ParamSpec {
paramSpec := C.g_param_spec_double(
(*C.gchar)(C.CString(name)),
(*C.gchar)(C.CString(nick)),
(*C.gchar)(C.CString(blurb)),
C.gdouble(min),
C.gdouble(max),
C.gdouble(defaultValue),
C.GParamFlags(flags),
)
return &ParamSpec{paramSpec: paramSpec}
}
// NewBoxedParam creates a new ParamSpec containing a boxed type. Some helper type castings are included
// in these bindings.
func NewBoxedParam(name, nick, blurb string, boxedType glib.Type, flags ParameterFlags) *ParamSpec {
paramSpec := C.g_param_spec_boxed(
(*C.gchar)(C.CString(name)),
(*C.gchar)(C.CString(nick)),
(*C.gchar)(C.CString(blurb)),
C.GType(boxedType),
C.GParamFlags(flags),
)
return &ParamSpec{paramSpec: paramSpec}
}

View File

@@ -10,7 +10,6 @@ typedef struct _PadDestroyNotifyInfo {
gpointer func_map_ptr;
} PadDestroyNotifyInfo;
/*
Type Castings
*/
@@ -173,49 +172,6 @@ inline gboolean gstObjectFlagIsSet (GstObject * obj, GstElementFlags
inline GstTocSetter * toTocSetter (GstElement * elem) { return GST_TOC_SETTER(elem); }
inline GstTagSetter * toTagSetter (GstElement *elem) { return GST_TAG_SETTER(elem); }
/*
ParamSpec Utilities
*/
inline gboolean isParamSpecTypeCaps (GParamSpec * p) { return p->value_type == GST_TYPE_CAPS; }
inline gboolean isParamSpecEnum (GParamSpec * p) { return (G_IS_PARAM_SPEC_ENUM(p)); }
inline gboolean isParamSpecFlags (GParamSpec * p) { return (G_IS_PARAM_SPEC_FLAGS(p)); }
inline gboolean isParamSpecObject (GParamSpec * p) { return (G_IS_PARAM_SPEC_OBJECT(p)); }
inline gboolean isParamSpecBoxed (GParamSpec * p) { return (G_IS_PARAM_SPEC_BOXED(p)); }
inline gboolean isParamSpecPointer (GParamSpec * p) { return (G_IS_PARAM_SPEC_POINTER(p)); }
inline gboolean isParamSpecFraction (GParamSpec * p) { return (GST_IS_PARAM_SPEC_FRACTION(p)); }
inline gboolean isParamSpecGstArray (GParamSpec * p) { return p->value_type == GST_TYPE_ARRAY; }
inline GParamSpecUInt * getParamUInt (GParamSpec * param) { return (G_PARAM_SPEC_UINT(param)); }
inline GParamSpecInt * getParamInt (GParamSpec * param) { return (G_PARAM_SPEC_INT(param)); }
inline GParamSpecUInt64 * getParamUInt64 (GParamSpec * param) { return (G_PARAM_SPEC_UINT64(param)); }
inline GParamSpecInt64 * getParamInt64 (GParamSpec * param) { return (G_PARAM_SPEC_INT64(param)); }
inline GParamSpecFloat * getParamFloat (GParamSpec * param) { return (G_PARAM_SPEC_FLOAT(param)); }
inline GParamSpecDouble * getParamDouble (GParamSpec * param) { return (G_PARAM_SPEC_DOUBLE(param)); }
inline GEnumValue * getEnumValues (GParamSpec * p, guint * size)
{
GEnumValue * values;
values = G_ENUM_CLASS (g_type_class_ref (p->value_type))->values;
guint i = 0;
while (values[i].value_name) {
++i;
}
*size = i;
return values;
}
inline GFlagsValue * getParamSpecFlags (GParamSpec * p, guint * size)
{
GParamSpecFlags * pflags = G_PARAM_SPEC_FLAGS (p);
GFlagsValue * vals = pflags->flags_class->values;
guint i = 0;
while (vals[i].value_name) {
++i;
}
*size = i;
return vals;
}
/* Misc */

View File

@@ -108,12 +108,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 GoElement, extends Extendable) bool {
func RegisterElement(plugin *Plugin, name string, rank Rank, elem glib.GoObjectSubclass, extends glib.Extendable) bool {
return gobool(C.gst_element_register(
plugin.Instance(),
C.CString(name),
C.guint(rank),
gtypeForGoElement(name, elem, extends),
C.GType(glib.RegisterGoType(name, elem, extends)),
))
}
@@ -452,7 +452,7 @@ func (e *Element) URIHandler() URIHandler {
}
// ExtendsElement signifies a GoElement that extends a GstElement.
var ExtendsElement Extendable = &extendElement{parent: ExtendsObject}
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.
@@ -492,13 +492,13 @@ type ElementImpl interface {
StateChanged(self *Element, old, new, pending State)
}
type extendElement struct{ parent Extendable }
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 GoElement) {
func (e *extendElement) InitClass(klass unsafe.Pointer, elem glib.GoObjectSubclass) {
e.parent.InitClass(klass, elem)
elemClass := C.toGstElementClass(klass)

View File

@@ -4,10 +4,19 @@ package gst
#include "gst.go.h"
*/
import "C"
import "unsafe"
import (
"unsafe"
"github.com/tinyzimmer/go-glib/glib"
)
// ElementClass represents the subclass of an element provided by a plugin.
type ElementClass struct{ *ObjectClass }
type ElementClass struct{ *glib.ObjectClass }
// ToElementClass wraps the given ObjectClass in an ElementClass instance.
func ToElementClass(klass *glib.ObjectClass) *ElementClass {
return &ElementClass{klass}
}
// Instance returns the underlying GstElementClass instance.
func (e *ElementClass) Instance() *C.GstElementClass {

View File

@@ -8,11 +8,13 @@ import "C"
import (
"time"
"unsafe"
"github.com/tinyzimmer/go-glib/glib"
)
//export goGstElementClassChangeState
func goGstElementClassChangeState(elem *C.GstElement, change C.GstStateChange) C.GstStateChangeReturn {
iface := FromObjectUnsafePrivate(unsafe.Pointer(elem)).(interface {
iface := glib.FromObjectUnsafePrivate(unsafe.Pointer(elem)).(interface {
ChangeState(*Element, StateChange) StateChangeReturn
})
return C.GstStateChangeReturn(iface.ChangeState(wrapCbElem(elem), StateChange(change)))
@@ -20,7 +22,7 @@ func goGstElementClassChangeState(elem *C.GstElement, change C.GstStateChange) C
//export goGstElementClassGetState
func goGstElementClassGetState(elem *C.GstElement, state, pending *C.GstState, timeout C.GstClockTime) C.GstStateChangeReturn {
iface := FromObjectUnsafePrivate(unsafe.Pointer(elem)).(interface {
iface := glib.FromObjectUnsafePrivate(unsafe.Pointer(elem)).(interface {
GetState(*Element, time.Duration) (ret StateChangeReturn, current, pending State)
})
ret, cur, pend := iface.GetState(wrapCbElem(elem), time.Duration(timeout)*time.Nanosecond)
@@ -34,7 +36,7 @@ func goGstElementClassGetState(elem *C.GstElement, state, pending *C.GstState, t
//export goGstElementClassNoMorePads
func goGstElementClassNoMorePads(elem *C.GstElement) {
iface := FromObjectUnsafePrivate(unsafe.Pointer(elem)).(interface {
iface := glib.FromObjectUnsafePrivate(unsafe.Pointer(elem)).(interface {
NoMorePads(*Element)
})
iface.NoMorePads(wrapCbElem(elem))
@@ -42,7 +44,7 @@ func goGstElementClassNoMorePads(elem *C.GstElement) {
//export goGstElementClassPadAdded
func goGstElementClassPadAdded(elem *C.GstElement, pad *C.GstPad) {
iface := FromObjectUnsafePrivate(unsafe.Pointer(elem)).(interface {
iface := glib.FromObjectUnsafePrivate(unsafe.Pointer(elem)).(interface {
PadAdded(*Element, *Pad)
})
iface.PadAdded(wrapCbElem(elem), wrapPad(toGObject(unsafe.Pointer(pad))))
@@ -50,7 +52,7 @@ func goGstElementClassPadAdded(elem *C.GstElement, pad *C.GstPad) {
//export goGstElementClassPadRemoved
func goGstElementClassPadRemoved(elem *C.GstElement, pad *C.GstPad) {
iface := FromObjectUnsafePrivate(unsafe.Pointer(elem)).(interface {
iface := glib.FromObjectUnsafePrivate(unsafe.Pointer(elem)).(interface {
PadRemoved(*Element, *Pad)
})
iface.PadRemoved(wrapCbElem(elem), wrapPad(toGObject(unsafe.Pointer(pad))))
@@ -58,7 +60,7 @@ func goGstElementClassPadRemoved(elem *C.GstElement, pad *C.GstPad) {
//export goGstElementClassPostMessage
func goGstElementClassPostMessage(elem *C.GstElement, msg *C.GstMessage) C.gboolean {
iface := FromObjectUnsafePrivate(unsafe.Pointer(elem)).(interface {
iface := glib.FromObjectUnsafePrivate(unsafe.Pointer(elem)).(interface {
PostMessage(*Element, *Message) bool
})
return gboolean(iface.PostMessage(wrapCbElem(elem), wrapMessage(msg)))
@@ -66,7 +68,7 @@ func goGstElementClassPostMessage(elem *C.GstElement, msg *C.GstMessage) C.gbool
//export goGstElementClassProvideClock
func goGstElementClassProvideClock(elem *C.GstElement) *C.GstClock {
iface := FromObjectUnsafePrivate(unsafe.Pointer(elem)).(interface {
iface := glib.FromObjectUnsafePrivate(unsafe.Pointer(elem)).(interface {
ProvideClock(*Element) *Clock
})
clock := iface.ProvideClock(wrapCbElem(elem))
@@ -78,7 +80,7 @@ func goGstElementClassProvideClock(elem *C.GstElement) *C.GstClock {
//export goGstElementClassQuery
func goGstElementClassQuery(elem *C.GstElement, query *C.GstQuery) C.gboolean {
iface := FromObjectUnsafePrivate(unsafe.Pointer(elem)).(interface {
iface := glib.FromObjectUnsafePrivate(unsafe.Pointer(elem)).(interface {
Query(*Element, *Query) bool
})
return gboolean(iface.Query(wrapCbElem(elem), wrapQuery(query)))
@@ -86,7 +88,7 @@ func goGstElementClassQuery(elem *C.GstElement, query *C.GstQuery) C.gboolean {
//export goGstElementClassReleasePad
func goGstElementClassReleasePad(elem *C.GstElement, pad *C.GstPad) {
iface := FromObjectUnsafePrivate(unsafe.Pointer(elem)).(interface {
iface := glib.FromObjectUnsafePrivate(unsafe.Pointer(elem)).(interface {
ReleasePad(*Element, *Pad)
})
iface.ReleasePad(wrapCbElem(elem), wrapPad(toGObject(unsafe.Pointer(pad))))
@@ -94,7 +96,7 @@ func goGstElementClassReleasePad(elem *C.GstElement, pad *C.GstPad) {
//export goGstElementClassRequestNewPad
func goGstElementClassRequestNewPad(elem *C.GstElement, templ *C.GstPadTemplate, name *C.gchar, caps *C.GstCaps) *C.GstPad {
iface := FromObjectUnsafePrivate(unsafe.Pointer(elem)).(interface {
iface := glib.FromObjectUnsafePrivate(unsafe.Pointer(elem)).(interface {
RequestNewPad(self *Element, templ *PadTemplate, name string, caps *Caps) *Pad
})
pad := iface.RequestNewPad(
@@ -111,7 +113,7 @@ func goGstElementClassRequestNewPad(elem *C.GstElement, templ *C.GstPadTemplate,
//export goGstElementClassSendEvent
func goGstElementClassSendEvent(elem *C.GstElement, event *C.GstEvent) C.gboolean {
iface := FromObjectUnsafePrivate(unsafe.Pointer(elem)).(interface {
iface := glib.FromObjectUnsafePrivate(unsafe.Pointer(elem)).(interface {
SendEvent(*Element, *Event) bool
})
return gboolean(iface.SendEvent(wrapCbElem(elem), wrapEvent(event)))
@@ -119,7 +121,7 @@ func goGstElementClassSendEvent(elem *C.GstElement, event *C.GstEvent) C.gboolea
//export goGstElementClassSetBus
func goGstElementClassSetBus(elem *C.GstElement, bus *C.GstBus) {
iface := FromObjectUnsafePrivate(unsafe.Pointer(elem)).(interface {
iface := glib.FromObjectUnsafePrivate(unsafe.Pointer(elem)).(interface {
SetBus(*Element, *Bus)
})
iface.SetBus(wrapCbElem(elem), wrapBus(toGObject(unsafe.Pointer(bus))))
@@ -127,7 +129,7 @@ func goGstElementClassSetBus(elem *C.GstElement, bus *C.GstBus) {
//export goGstElementClassSetClock
func goGstElementClassSetClock(elem *C.GstElement, clock *C.GstClock) C.gboolean {
iface := FromObjectUnsafePrivate(unsafe.Pointer(elem)).(interface {
iface := glib.FromObjectUnsafePrivate(unsafe.Pointer(elem)).(interface {
SetClock(*Element, *Clock) bool
})
return gboolean(iface.SetClock(wrapCbElem(elem), wrapClock(toGObject(unsafe.Pointer(clock)))))
@@ -135,7 +137,7 @@ func goGstElementClassSetClock(elem *C.GstElement, clock *C.GstClock) C.gboolean
//export goGstElementClassSetContext
func goGstElementClassSetContext(elem *C.GstElement, ctx *C.GstContext) {
iface := FromObjectUnsafePrivate(unsafe.Pointer(elem)).(interface {
iface := glib.FromObjectUnsafePrivate(unsafe.Pointer(elem)).(interface {
SetContext(*Element, *Context)
})
iface.SetContext(wrapCbElem(elem), wrapContext(ctx))
@@ -143,7 +145,7 @@ func goGstElementClassSetContext(elem *C.GstElement, ctx *C.GstContext) {
//export goGstElementClassSetState
func goGstElementClassSetState(elem *C.GstElement, state C.GstState) C.GstStateChangeReturn {
iface := FromObjectUnsafePrivate(unsafe.Pointer(elem)).(interface {
iface := glib.FromObjectUnsafePrivate(unsafe.Pointer(elem)).(interface {
SetState(*Element, State) StateChangeReturn
})
return C.GstStateChangeReturn(iface.SetState(wrapCbElem(elem), State(state)))
@@ -151,7 +153,7 @@ func goGstElementClassSetState(elem *C.GstElement, state C.GstState) C.GstStateC
//export goGstElementClassStateChanged
func goGstElementClassStateChanged(elem *C.GstElement, old, new, pending C.GstState) {
iface := FromObjectUnsafePrivate(unsafe.Pointer(elem)).(interface {
iface := glib.FromObjectUnsafePrivate(unsafe.Pointer(elem)).(interface {
StateChanged(self *Element, old, new, pending State)
})
iface.StateChanged(wrapCbElem(elem), State(old), State(new), State(pending))

View File

@@ -97,3 +97,37 @@ const (
StreamErrorDecrypt ErrorCode = C.GST_STREAM_ERROR_DECRYPT // (12) used when the stream is encrypted and can't be decrypted because this is not supported by the element.
StreamErrorDecryptNoKey ErrorCode = C.GST_STREAM_ERROR_DECRYPT_NOKEY // (13) used when the stream is encrypted and can't be decrypted because no suitable key is available.
)
// GError is a Go wrapper for a C GError in the context of GStreamer. It implements the error interface
// and provides additional functions for retrieving debug strings and details.
type GError struct {
errMsg, debugStr string
structure *Structure
// used for message constructors
code ErrorCode
}
// Message is an alias to `Error()`. It's for clarity when this object
// is parsed from a `GST_MESSAGE_INFO` or `GST_MESSAGE_WARNING`.
func (e *GError) Message() string { return e.Error() }
// Error implements the error interface and returns the error message.
func (e *GError) Error() string { return e.errMsg }
// DebugString returns any debug info alongside the error.
func (e *GError) DebugString() string { return e.debugStr }
// Structure returns the structure of the error message which may contain additional metadata.
func (e *GError) Structure() *Structure { return e.structure }
// Code returns the error code of the error message.
func (e *GError) Code() ErrorCode { return e.code }
// NewGError wraps the given error inside a GError (to be used with message constructors).
func NewGError(code ErrorCode, err error) *GError {
return &GError{
errMsg: err.Error(),
code: code,
}
}

View File

@@ -66,19 +66,16 @@ func (o *Object) Interfaces() []string {
// set in this object, or their defaults.
//
// Unref after usage.
func (o *Object) ListProperties() []*ParamSpec {
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([]*ParamSpec, 0)
out := make([]*glib.ParamSpec, 0)
for _, prop := range (*[1 << 30]*C.GParamSpec)(unsafe.Pointer(props))[:size:size] {
C.g_param_spec_sink(prop) // steal the ref on the property
out = append(out, &ParamSpec{
paramSpec: prop,
})
out = append(out, glib.ToParamSpec(unsafe.Pointer(prop)))
}
return out
}

12
gst/gst_param_flags.go Normal file
View File

@@ -0,0 +1,12 @@
package gst
// #include "gst.go.h"
import "C"
// Additional GStreamer ParamSpec flags
const (
ParameterControllable = C.GST_PARAM_CONTROLLABLE
ParameterMutablePlaying = C.GST_PARAM_MUTABLE_PLAYING
ParameterMutablePaused = C.GST_PARAM_MUTABLE_PAUSED
ParameterMutableReady = C.GST_PARAM_MUTABLE_READY
)

View File

@@ -2,6 +2,21 @@ package gst
/*
#include "gst.go.h"
extern GstURIType goURIHdlrGetURIType (GType type);
extern const gchar * const * goURIHdlrGetProtocols (GType type);
extern gchar * goURIHdlrGetURI (GstURIHandler * handler);
extern gboolean goURIHdlrSetURI (GstURIHandler * handler,
const gchar * uri,
GError ** error);
void uriHandlerInit (gpointer iface, gpointer iface_data)
{
((GstURIHandlerInterface*)iface)->get_type = goURIHdlrGetURIType;
((GstURIHandlerInterface*)iface)->get_protocols = goURIHdlrGetProtocols;
((GstURIHandlerInterface*)iface)->get_uri = goURIHdlrGetURI;
((GstURIHandlerInterface*)iface)->set_uri = goURIHdlrSetURI;
}
*/
import "C"
import (
@@ -14,7 +29,20 @@ 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.
var InterfaceURIHandler = glib.Type(C.GST_TYPE_URI_HANDLER)
var InterfaceURIHandler glib.Interface = &interfaceURIHandler{}
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)
}
// URIHandler represents an interface that elements can implement to provide URI handling
// capabilities.

View File

@@ -30,8 +30,6 @@ func wrapDevice(obj *glib.Object) *Device { return &Device{wrapO
func wrapElement(obj *glib.Object) *Element { return &Element{wrapObject(obj)} }
func wrapEvent(ev *C.GstEvent) *Event { return &Event{ptr: ev} }
func wrapGhostPad(obj *glib.Object) *GhostPad { return &GhostPad{wrapProxyPad(obj)} }
func wrapMainContext(ctx *C.GMainContext) *MainContext { return &MainContext{ptr: ctx} }
func wrapMainLoop(loop *C.GMainLoop) *MainLoop { return &MainLoop{ptr: loop} }
func wrapMapInfo(mapInfo *C.GstMapInfo) *MapInfo { return &MapInfo{ptr: mapInfo} }
func wrapMemory(mem *C.GstMemory) *Memory { return &Memory{ptr: mem} }
func wrapMessage(msg *C.GstMessage) *Message { return &Message{msg: msg} }
@@ -72,10 +70,6 @@ func wrapAllocationParams(obj *C.GstAllocationParams) *AllocationParams {
return &AllocationParams{ptr: obj}
}
func wrapElementClass(klass C.gpointer) *ElementClass {
return &ElementClass{&ObjectClass{ptr: C.toGObjectClass(unsafe.Pointer(klass))}}
}
// Marshallers
func uintptrToGVal(p uintptr) *C.GValue { return (*C.GValue)(C.toGValue(C.guintptr(p))) }

View File

@@ -1,101 +0,0 @@
package gstauto
import (
"bufio"
"io"
"os"
)
// Blank assertions to ensure interfaces are implemented.
var _ io.ReadCloser = &readCloser{}
var _ io.WriteCloser = &writeCloser{}
var _ io.ReadWriteCloser = &readWriteCloser{}
// readCloser is a struct that provides a read buffer that can also be written to
// internally.
type readCloser struct {
rReader, rWriter *os.File
rBuf *bufio.Reader
}
// newReadCloser returns a new readCloser.
func newReadCloser() (*readCloser, error) {
r, w, err := os.Pipe()
if err != nil {
return nil, err
}
return &readCloser{
rReader: r,
rWriter: w,
rBuf: bufio.NewReader(r),
}, nil
}
// Read implements a Reader for objects embdedding this struct.
func (r *readCloser) Read(p []byte) (int, error) { return r.rBuf.Read(p) }
// Close implements a Closer for objects embedding this struct.
func (r *readCloser) Close() error {
if err := r.rWriter.Close(); err != nil {
return err
}
return r.rReader.Close()
}
// writeCloser is a struct that provides a read buffer that can also be
// read from internally.
type writeCloser struct {
wReader, wWriter *os.File
wBuf *bufio.Writer
}
// newWriteCloser returns a new writeCloser.
func newWriteCloser() (*writeCloser, error) {
r, w, err := os.Pipe()
if err != nil {
return nil, err
}
return &writeCloser{
wReader: r,
wWriter: w,
wBuf: bufio.NewWriter(w),
}, nil
}
// Write implements a Writer for objects embedding this struct.
func (w *writeCloser) Write(p []byte) (int, error) { return w.wBuf.Write(p) }
// Close implements a Closer for objects embedding this struct.
func (w *writeCloser) Close() error {
if err := w.wWriter.Close(); err != nil {
return err
}
return w.wReader.Close()
}
// readWriteCloser is a struct that provides both read and write buffers.
type readWriteCloser struct {
*readCloser
*writeCloser
}
// newReadWriteCloser returns a new readWriteCloser.
func newReadWriteCloser() (*readWriteCloser, error) {
rCloser, err := newReadCloser()
if err != nil {
return nil, err
}
wCloser, err := newWriteCloser()
if err != nil {
return nil, err
}
return &readWriteCloser{readCloser: rCloser, writeCloser: wCloser}, nil
}
// Close implements a Closer for objects embedding this struct.
func (rw *readWriteCloser) Close() error {
if err := rw.writeCloser.Close(); err != nil {
return err
}
return rw.readCloser.Close()
}

View File

@@ -1,4 +0,0 @@
// Package gstauto contains helper methods and objects for building pipelines that
// satisfy most use cases. It provides an abstraction over the lower-level building
// blocks provided in the gst package.
package gstauto

View File

@@ -1,132 +0,0 @@
package gstauto
import (
"errors"
"github.com/tinyzimmer/go-gst/gst"
)
// PipelineElement represents an `GstElement` in a `GstPipeline` when building a Pipeline with `NewPipelineFromConfig`.
// The Name should coorespond to a valid gstreamer plugin name. The data are additional
// fields to set on the element. If SinkCaps is non-nil, they are applied to the sink of this
// element.
type PipelineElement struct {
Name string
SinkCaps *gst.Caps
Data map[string]interface{}
}
// GetName returns the name to use when creating Elements from this configuration.
func (p *PipelineElement) GetName() string { return p.Name }
// PipelineConfig represents a list of elements and their configurations
// to be used with NewPipelineFromConfig.
type PipelineConfig struct {
Elements []*PipelineElement
}
// GetElementByName returns the Element configuration for the given name.
func (p *PipelineConfig) GetElementByName(name string) *PipelineElement {
for _, elem := range p.Elements {
if name == elem.GetName() {
return elem
}
}
return nil
}
// ElementNames returns a string slice of the names of all the plugins.
func (p *PipelineConfig) ElementNames() []string {
names := make([]string, 0)
for _, elem := range p.Elements {
names = append(names, elem.GetName())
}
return names
}
// PushPluginToTop pushes a plugin to the top of the list of elements.
func (p *PipelineConfig) PushPluginToTop(elem *PipelineElement) {
newSlc := []*PipelineElement{elem}
newSlc = append(newSlc, p.Elements...)
p.Elements = newSlc
}
// Apply applies this configuration to the given Pipeline.
func (p *PipelineConfig) Apply(pipeline *gst.Pipeline) error {
// build all the elements
elementNames := p.ElementNames()
elements, err := gst.NewElementMany(elementNames...)
if err != nil {
return err
}
// iterate the element names and add them to the pipeline
for idx, name := range elementNames {
// get the current config and element
currentCfg := p.GetElementByName(name)
currentElem := elements[idx]
// Iterate any data with the plugin and set it on the element
for key, value := range currentCfg.Data {
if err := currentElem.Set(key, value); err != nil {
return err
}
}
// Add the element to the pipeline
if err := pipeline.Add(currentElem); err != nil {
return err
}
// If this is the first element continue
if idx == 0 {
continue
}
// get the last element in the chain
lastElemName := elementNames[idx-1]
lastElem := elements[idx-1]
lastCfg := p.GetElementByName(lastElemName)
if lastCfg == nil {
// this would never happen unless someone is messing with memory,
// but safety from panic
continue
}
// If there are sink caps on the last element, do a filtered link to this one and continue
if lastCfg.SinkCaps != nil {
if err := lastElem.LinkFiltered(currentElem, lastCfg.SinkCaps); err != nil {
return err
}
continue
}
// link the last element to this element
if err := lastElem.Link(currentElem); err != nil {
return err
}
}
return nil
}
// NewPipelineFromConfig builds a new pipeline from the given PipelineConfig. The plugins provided
// in the configuration will be linked in the order they are given.
func NewPipelineFromConfig(cfg *PipelineConfig) (*gst.Pipeline, error) {
if cfg.Elements == nil {
return nil, errors.New("Element cannot be empty in the configuration")
}
// create a new empty pipeline instance
pipeline, err := gst.NewPipeline("")
if err != nil {
return nil, err
}
if err = cfg.Apply(pipeline); err != nil {
runOrPrintErr(pipeline.Destroy)
return nil, err
}
return pipeline, nil
}

View File

@@ -1,36 +0,0 @@
package gstauto
import (
"io"
"github.com/tinyzimmer/go-gst/gst"
)
// Pipeliner is a the base interface for structs extending the functionality of
// the Pipeline object. It provides a single method which returns the underlying
// Pipeline object.
type Pipeliner interface {
io.Closer
// Pipeline should return the underlying pipeline
Pipeline() *gst.Pipeline
// Start should start the underlying pipeline.
Start() error
}
// ReadPipeliner is a Pipeliner that also implements a ReadCloser.
type ReadPipeliner interface {
Pipeliner
io.Reader
}
// WritePipeliner is a Pipeliner that also implements a WriteCloser.
type WritePipeliner interface {
Pipeliner
io.Writer
}
// ReadWritePipeliner is a Pipeliner that also implements a ReadWriteCloser.
type ReadWritePipeliner interface {
Pipeliner
io.ReadWriter
}

View File

@@ -1,76 +0,0 @@
package gstauto
import (
"github.com/tinyzimmer/go-gst/gst"
)
// Empty assignment to ensure PipelineReader satisfies the ReadPipeliner interface.
var _ ReadPipeliner = &PipelineReader{}
// PipelineReader is the base struct to be used to implement ReadPipeliners.
type PipelineReader struct {
*readCloser
pipeline *gst.Pipeline
}
// NewPipelineReader returns a new PipelineReader with an empty pipeline. Use an empty name
// to have gstreamer auto-generate one. This method is intended for use in the construction
// of other interfaces.
func NewPipelineReader(name string) (*PipelineReader, error) {
pipeline, err := gst.NewPipeline(name)
if err != nil {
return nil, err
}
rCloser, err := newReadCloser()
if err != nil {
runOrPrintErr(pipeline.Destroy)
return nil, err
}
return &PipelineReader{
readCloser: rCloser,
pipeline: pipeline,
}, nil
}
// NewPipelineReaderFromString returns a new PipelineReader with a pipeline populated
// by the provided gstreamer launch string. If you are looking to build a simple
// ReadPipeliner you probably want to use NewPipelineReaderSimpleFromString.
func NewPipelineReaderFromString(launchStr string) (*PipelineReader, error) {
pipeline, err := gst.NewPipelineFromString(launchStr)
if err != nil {
return nil, err
}
rCloser, err := newReadCloser()
if err != nil {
runOrPrintErr(pipeline.Destroy)
return nil, err
}
return &PipelineReader{
readCloser: rCloser,
pipeline: pipeline,
}, nil
}
// Pipeline returns the underlying Pipeline instance for this pipeliner. It implements the
// Pipeliner interface.
func (r *PipelineReader) Pipeline() *gst.Pipeline { return r.pipeline }
// Start sets the underlying Pipeline state to PLAYING.
func (r *PipelineReader) Start() error { return r.Pipeline().Start() }
// ReaderFd returns the file descriptor that can be written to for the read-buffer. This value
// is used when wanting to allow an underlying pipeline to write to the internal buffer (e.g. when using a fdsink).
func (r *PipelineReader) ReaderFd() int { return int(r.readCloser.rWriter.Fd()) }
// Close will stop and unref the underlying pipeline.
func (r *PipelineReader) Close() error {
if err := r.Pipeline().Destroy(); err != nil {
return err
}
return r.readCloser.Close()
}
// CloseAsync will close the underlying pipeline asynchronously. It is the caller's
// responsibility to call Unref on the pipeline and close buffers once it is no longer being used.
// This can be accomplished via calling a regular Close (which is idempotent).
func (r *PipelineReader) CloseAsync() error { return r.pipeline.SetState(gst.StateNull) }

View File

@@ -1,82 +0,0 @@
package gstauto
import (
"github.com/tinyzimmer/go-gst/gst"
)
// Empty assignment to ensure PipelineReadWriter satisfies the ReadWritePipeliner interface.
var _ ReadWritePipeliner = &PipelineReadWriter{}
// PipelineReadWriter is the base struct to be used to implement ReadWritePipeliners.
type PipelineReadWriter struct {
*readWriteCloser
pipeline *gst.Pipeline
}
// NewPipelineReadWriter returns a new PipelineReadWriter with an empty pipeline. Use an empty name
// to have gstreamer auto-generate one. This method is intended for use in the construction
// of other interfaces.
func NewPipelineReadWriter(name string) (*PipelineReadWriter, error) {
pipeline, err := gst.NewPipeline(name)
if err != nil {
return nil, err
}
rwCloser, err := newReadWriteCloser()
if err != nil {
runOrPrintErr(pipeline.Destroy)
return nil, err
}
return &PipelineReadWriter{
readWriteCloser: rwCloser,
pipeline: pipeline,
}, nil
}
// NewPipelineReadWriterFromString returns a new PipelineReadWriter with a pipeline populated
// by the provided gstreamer launch string. If you are looking to build a simple
// ReadWritePipeliner you probably want to use NewPipelineReadWriterSimpleFromString.
func NewPipelineReadWriterFromString(launchStr string) (*PipelineReadWriter, error) {
pipeline, err := gst.NewPipelineFromString(launchStr)
if err != nil {
return nil, err
}
rwCloser, err := newReadWriteCloser()
if err != nil {
runOrPrintErr(pipeline.Destroy)
return nil, err
}
return &PipelineReadWriter{
readWriteCloser: rwCloser,
pipeline: pipeline,
}, nil
}
// Pipeline returns the underlying Pipeline instance for this pipeliner. It implements the
// Pipeliner interface.
func (rw *PipelineReadWriter) Pipeline() *gst.Pipeline { return rw.pipeline }
// Start sets the underlying Pipeline state to PLAYING.
func (rw *PipelineReadWriter) Start() error { return rw.Pipeline().Start() }
// ReaderFd returns the file descriptor that can be written to for the read-buffer. This value
// is used when wanting to allow an underlying pipeline to write to the internal buffer
// (e.g. when using a fdsink).
func (rw *PipelineReadWriter) ReaderFd() int { return int(rw.readWriteCloser.readCloser.rWriter.Fd()) }
// WriterFd returns the file descriptor that can be used to read from the write-buffer. This value
// is used when wanting to allow an underlying pipeline the ability to read data written to the buffer
// (e.g. when using a fdsrc).
func (rw *PipelineReadWriter) WriterFd() int { return int(rw.readWriteCloser.writeCloser.wReader.Fd()) }
// Close will stop and unref the underlying pipeline and read/write buffers.
func (rw *PipelineReadWriter) Close() error {
if err := rw.Pipeline().Destroy(); err != nil {
return err
}
return rw.readWriteCloser.Close()
}
// CloseAsync will close the underlying pipeline asynchronously. It is the caller's
// responsibility to call Unref on the pipeline and close buffers once it is no longer being used.
// This can be accomplished via calling a regular Close (which is idempotent).
func (rw *PipelineReadWriter) CloseAsync() error { return rw.pipeline.SetState(gst.StateNull) }

View File

@@ -1,59 +0,0 @@
package gstauto
import (
"github.com/tinyzimmer/go-gst/gst"
)
// Blank assignment to make sure PipelinerSimple satisfies the Pipeliner interface.
var _ Pipeliner = &PipelinerSimple{}
// PipelinerSimple is a simple struct that implements the Pipeliner interface.
// It doesn't provide any additional read/write capabilities. Its primary intention
// is for pipelines where the caller does not wish to personally read or write from
// either end of the buffer.
type PipelinerSimple struct {
pipeline *gst.Pipeline
}
// Pipeline implements the Pipeliner interface.
func (s *PipelinerSimple) Pipeline() *gst.Pipeline { return s.pipeline }
// Start sets the underlying Pipeline state to PLAYING.
func (s *PipelinerSimple) Start() error { return s.Pipeline().Start() }
// Close stops and unrefs the underlying pipeline.
func (s *PipelinerSimple) Close() error { return s.Pipeline().Destroy() }
// NewPipelinerSimple returns a new empty PipelinerSimple. Pass an empty string
// for name to use an auto-generated one.
func NewPipelinerSimple(name string) (*PipelinerSimple, error) {
pipeline, err := gst.NewPipeline(name)
if err != nil {
return nil, err
}
return &PipelinerSimple{pipeline: pipeline}, nil
}
// NewPipelinerSimpleFromString returns a new PipelinerSimpler from the given
// launch string.
func NewPipelinerSimpleFromString(launchStr string) (*PipelinerSimple, error) {
pipeline, err := gst.NewPipelineFromString(launchStr)
if err != nil {
return nil, err
}
return &PipelinerSimple{pipeline: pipeline}, nil
}
// NewPipelinerSimpleFromConfig returns a new PipelinerSimple from the given
// PipelineConfig.
func NewPipelinerSimpleFromConfig(cfg *PipelineConfig) (*PipelinerSimple, error) {
pipeline, err := gst.NewPipeline("")
if err != nil {
return nil, err
}
if err := cfg.Apply(pipeline); err != nil {
runOrPrintErr(pipeline.Destroy)
return nil, err
}
return &PipelinerSimple{pipeline: pipeline}, nil
}

View File

@@ -1,81 +0,0 @@
package gstauto
import (
"errors"
"fmt"
"strings"
"github.com/tinyzimmer/go-gst/gst"
)
// PipelineReaderSimple implements a ReadPipeliner that configures gstreamer
// to write directly to the internal read-buffer via an fdsink.
type PipelineReaderSimple struct {
*PipelineReader
}
// NewPipelineReaderSimpleFromString returns a new PipelineReaderSimple populated from
// the given launch string. An fdsink is added to the end of the launch string and tied
// to the read buffer.
func NewPipelineReaderSimpleFromString(launchStr string) (*PipelineReaderSimple, error) {
pipelineReader, err := NewPipelineReaderFromString(addFdSinkToStr(launchStr))
if err != nil {
return nil, err
}
defer func() {
if err != nil {
runOrPrintErr(pipelineReader.Pipeline().Destroy)
}
}()
// Retrieve the sinks in the pipeline, most of the time there is just one
var sinks []*gst.Element
sinks, err = pipelineReader.Pipeline().GetSinkElements()
if err != nil {
return nil, err
}
// Fetch the fdsink and reconfigure it to point to the read buffer.
for _, sink := range sinks {
if strings.Contains(sink.Name(), "fdsink") {
if err = sink.Set("fd", pipelineReader.ReaderFd()); err != nil {
return nil, err
}
}
}
// Return the pipeline
return &PipelineReaderSimple{pipelineReader}, nil
}
// NewPipelineReaderSimpleFromConfig returns a new PipelineReaderSimple populated from
// the given launch config. An fdsink is added to the end of the launch config and tied
// to the read buffer.
func NewPipelineReaderSimpleFromConfig(cfg *PipelineConfig) (*PipelineReaderSimple, error) {
if cfg.Elements == nil {
return nil, errors.New("Elements cannot be nil in the config")
}
pipelineReader, err := NewPipelineReader("")
if err != nil {
return nil, err
}
cfg.Elements = append(cfg.Elements, &PipelineElement{
Name: "fdsink",
Data: map[string]interface{}{
"fd": pipelineReader.ReaderFd(),
},
})
if err := cfg.Apply(pipelineReader.Pipeline()); err != nil {
runOrPrintErr(pipelineReader.Pipeline().Destroy)
return nil, err
}
return &PipelineReaderSimple{pipelineReader}, nil
}
func addFdSinkToStr(pstr string) string {
if pstr == "" {
return "fdsink"
}
return fmt.Sprintf("%s ! fdsink", pstr)
}

View File

@@ -1,96 +0,0 @@
package gstauto
import (
"errors"
"strings"
"github.com/tinyzimmer/go-gst/gst"
)
// PipelineReadWriterSimple implements a ReadWritePipeliner that configures gstreamer
// to read from the internal write-buffer via an fdsrc and write to the internal read-buffer
// via an fdsink.
type PipelineReadWriterSimple struct {
*PipelineReadWriter
}
// NewPipelineReadWriterSimpleFromString returns a new PipelineReadWriterSimple from
// the given launch string. An fdsrc listening on the write buffer and an fdsink to the read buffer
// are formatted into the provided string.
func NewPipelineReadWriterSimpleFromString(launchStr string) (*PipelineReadWriterSimple, error) {
pipelineReadWriter, err := NewPipelineReadWriterFromString(addFdSrcToStr(addFdSinkToStr(launchStr)))
if err != nil {
return nil, err
}
defer func() {
if err != nil {
runOrPrintErr(pipelineReadWriter.Pipeline().Destroy)
}
}()
// Retrieve the sinks in the pipeline, most of the time there is just one
var sinks []*gst.Element
sinks, err = pipelineReadWriter.Pipeline().GetSinkElements()
if err != nil {
return nil, err
}
// Fetch the fdsink and reconfigure it to point to the read buffer.
for _, sink := range sinks {
if strings.Contains(sink.Name(), "fdsink") {
if err = sink.Set("fd", pipelineReadWriter.ReaderFd()); err != nil {
return nil, err
}
}
}
// Retrieve the sources in the pipeline, most of the time there is just one
var sources []*gst.Element
sources, err = pipelineReadWriter.Pipeline().GetSourceElements()
if err != nil {
return nil, err
}
// Fetch the fdsrc and reconfigure it to point to the write buffer.
for _, source := range sources {
if strings.Contains(source.Name(), "fdsrc") {
if err = source.Set("fd", pipelineReadWriter.WriterFd()); err != nil {
return nil, err
}
}
}
// Return the pipeline
return &PipelineReadWriterSimple{pipelineReadWriter}, nil
}
// NewPipelineReadWriterSimpleFromConfig returns a new PipelineReadWriterSimple populated from
// the given launch config. An fdsrc is added to the start of the launch config and tied
// to the write buffer, and an fdsink is added to the end tied to the read-buffer.
func NewPipelineReadWriterSimpleFromConfig(cfg *PipelineConfig) (*PipelineReadWriterSimple, error) {
if cfg.Elements == nil {
return nil, errors.New("Elements cannot be nil in the config")
}
pipelineReadWriter, err := NewPipelineReadWriter("")
if err != nil {
return nil, err
}
cfg.PushPluginToTop(&PipelineElement{
Name: "fdsrc",
Data: map[string]interface{}{
"fd": pipelineReadWriter.WriterFd(),
},
})
cfg.Elements = append(cfg.Elements, &PipelineElement{
Name: "fdsink",
Data: map[string]interface{}{
"fd": pipelineReadWriter.ReaderFd(),
},
})
if err := cfg.Apply(pipelineReadWriter.Pipeline()); err != nil {
runOrPrintErr(pipelineReadWriter.Pipeline().Destroy)
return nil, err
}
return &PipelineReadWriterSimple{pipelineReadWriter}, nil
}

View File

@@ -1,81 +0,0 @@
package gstauto
import (
"errors"
"fmt"
"strings"
"github.com/tinyzimmer/go-gst/gst"
)
// PipelineWriterSimple implements a WritePipeliner that configures gstreamer
// to read directly from the internal write-buffer via a fdsrc.
type PipelineWriterSimple struct {
*PipelineWriter
}
// NewPipelineWriterSimpleFromString returns a new PipelineWriterSimple populated from
// the given launch string. An fdsrc is added to the beginning of the string and tied to
// the write buffer.
func NewPipelineWriterSimpleFromString(launchStr string) (*PipelineWriterSimple, error) {
pipelineWriter, err := NewPipelineWriterFromString(addFdSrcToStr(launchStr))
if err != nil {
return nil, err
}
defer func() {
if err != nil {
runOrPrintErr(pipelineWriter.Pipeline().Destroy)
}
}()
// Retrieve the sources in the pipeline, most of the time there is just one
var sources []*gst.Element
sources, err = pipelineWriter.Pipeline().GetSourceElements()
if err != nil {
return nil, err
}
// Fetch the fdsrc and reconfigure it to point to the write buffer.
for _, source := range sources {
if strings.Contains(source.Name(), "fdsrc") {
if err = source.Set("fd", pipelineWriter.WriterFd()); err != nil {
return nil, err
}
}
}
// Return the pipeline
return &PipelineWriterSimple{pipelineWriter}, nil
}
// NewPipelineWriterSimpleFromConfig returns a new PipelineWriterSimple populated from
// the given launch config. An fdsrc is added to the start of the launch config and tied
// to the write buffer.
func NewPipelineWriterSimpleFromConfig(cfg *PipelineConfig) (*PipelineWriterSimple, error) {
if cfg.Elements == nil {
return nil, errors.New("Elements cannot be nil in the config")
}
pipelineWriter, err := NewPipelineWriter("")
if err != nil {
return nil, err
}
cfg.PushPluginToTop(&PipelineElement{
Name: "fdsrc",
Data: map[string]interface{}{
"fd": pipelineWriter.WriterFd(),
},
})
if err := cfg.Apply(pipelineWriter.Pipeline()); err != nil {
runOrPrintErr(pipelineWriter.Pipeline().Destroy)
return nil, err
}
return &PipelineWriterSimple{pipelineWriter}, nil
}
func addFdSrcToStr(pstr string) string {
if pstr == "" {
return "fdsrc"
}
return fmt.Sprintf("fdsrc ! %s", pstr)
}

View File

@@ -1,77 +0,0 @@
package gstauto
import (
"github.com/tinyzimmer/go-gst/gst"
)
// Empty assignment to ensure PipelineWriter satisfies the WritePipeliner interface.
var _ WritePipeliner = &PipelineWriter{}
// PipelineWriter is the base struct to be used to implement WritePipeliners.
type PipelineWriter struct {
*writeCloser
pipeline *gst.Pipeline
}
// NewPipelineWriter returns a new PipelineWriter with an empty pipeline. Use an empty name
// to have gstreamer auto-generate one. This method is intended for use in the construction
// of other interfaces.
func NewPipelineWriter(name string) (*PipelineWriter, error) {
pipeline, err := gst.NewPipeline(name)
if err != nil {
return nil, err
}
wCloser, err := newWriteCloser()
if err != nil {
runOrPrintErr(pipeline.Destroy)
return nil, err
}
return &PipelineWriter{
writeCloser: wCloser,
pipeline: pipeline,
}, nil
}
// NewPipelineWriterFromString returns a new PipelineWriter with a pipeline populated
// by the provided gstreamer launch string. If you are looking to build a simple
// WritePipeliner you probably want to use NewPipelineWriterSimpleFromString.
func NewPipelineWriterFromString(launchStr string) (*PipelineWriter, error) {
pipeline, err := gst.NewPipelineFromString(launchStr)
if err != nil {
return nil, err
}
wCloser, err := newWriteCloser()
if err != nil {
runOrPrintErr(pipeline.Destroy)
return nil, err
}
return &PipelineWriter{
writeCloser: wCloser,
pipeline: pipeline,
}, nil
}
// Pipeline returns the underlying Pipeline instance for this pipeliner. It implements the
// Pipeliner interface.
func (w *PipelineWriter) Pipeline() *gst.Pipeline { return w.pipeline }
// Start sets the underlying Pipeline state to PLAYING.
func (w *PipelineWriter) Start() error { return w.Pipeline().Start() }
// WriterFd returns the file descriptor that can be used to read from the write-buffer. This value
// is used when wanting to allow an underlying pipeline the ability to read data written to
// the buffer (e.g. when using a fdsrc).
func (w *PipelineWriter) WriterFd() int { return int(w.writeCloser.wReader.Fd()) }
// Close will stop and unref the underlying pipeline.
func (w *PipelineWriter) Close() error {
if err := w.Pipeline().Destroy(); err != nil {
return err
}
return w.writeCloser.Close()
}
// CloseAsync will close the underlying pipeline asynchronously. It is the caller's
// responsibility to call Unref on the pipeline and close buffers once it is no longer being used.
// This can be accomplished via calling a regular Close (which is idempotent).
func (w *PipelineWriter) CloseAsync() error { return w.pipeline.SetState(gst.StateNull) }

View File

@@ -1,9 +0,0 @@
package gstauto
import "github.com/tinyzimmer/go-gst/gst"
func runOrPrintErr(f func() error) {
if err := f(); err != nil {
gst.CAT.Log(gst.LevelError, err.Error())
}
}

View File

@@ -1,110 +0,0 @@
package gst
/*
#include "gst.go.h"
extern void goClassInit (gpointer g_class, gpointer class_data);
extern void goInstanceInit (GTypeInstance * instance, gpointer g_class);
void cgoClassInit (gpointer g_class, gpointer class_data) { goClassInit(g_class, class_data); }
void cgoInstanceInit (GTypeInstance * instance, gpointer g_class) { goInstanceInit(instance, g_class); }
*/
import "C"
import (
"reflect"
"unsafe"
gopointer "github.com/mattn/go-pointer"
"github.com/tinyzimmer/go-glib/glib"
)
// GoElement is an interface to be implemented by GStreamer elements built using the
// go bindings. Select methods from other interfaces can be overridden and declared via
// the Extendable property provided at plugin registration.
//
// Typically, at the very least, an element will want to implement methods from the Element
// Extendable (and by extension the GoObject).
type GoElement interface{ GoObjectSubclass }
// Extendable is an interface implemented by extendable classes. It provides
// the methods necessary to setup the vmethods on the object it represents.
type Extendable interface {
// Type should return the type of the extended object
Type() glib.Type
// ClasSize should return the size of the extended class
ClassSize() int64
// InstanceSize should return the size of the object itself
InstanceSize() int64
// InitClass should take a pointer to a new subclass and a GoElement and override any
// methods implemented by the GoElement in the subclass.
InitClass(unsafe.Pointer, GoElement)
}
// GoObjectSubclass is an interface that abstracts on the GObjectClass. It should be implemented
// by plugins using the go bindings.
type GoObjectSubclass interface {
// New should return a new instantiated GoElement ready to be used.
New() GoElement
// TypeInit is called after the GType is registered and right before ClassInit. It is when the
// element should add any interfaces it plans to implement.
TypeInit(*TypeInstance)
// ClassInit is called on the element after registering it with GStreamer. This is when the element
// should install its properties and pad templates.
ClassInit(*ElementClass)
}
// FromObjectUnsafePrivate will return the GoElement addressed in the private data of the given GObject.
func FromObjectUnsafePrivate(obj unsafe.Pointer) GoElement {
ptr := gopointer.Restore(privateFromObj(obj))
return ptr.(GoElement)
}
type classData struct {
elem GoElement
ext Extendable
}
func gtypeForGoElement(name string, elem GoElement, extendable Extendable) C.GType {
registerMutex.Lock()
defer registerMutex.Unlock()
if registered, ok := registeredTypes[reflect.TypeOf(elem).String()]; ok {
return registered
}
classData := &classData{
elem: elem,
ext: extendable,
}
ptr := gopointer.Save(classData)
typeInfo := (*C.GTypeInfo)(C.malloc(C.sizeof_GTypeInfo))
defer C.free(unsafe.Pointer(typeInfo))
typeInfo.base_init = nil
typeInfo.base_finalize = nil
typeInfo.class_size = C.gushort(extendable.ClassSize())
typeInfo.class_finalize = nil
typeInfo.class_init = C.GClassInitFunc(C.cgoClassInit)
typeInfo.class_data = (C.gconstpointer)(ptr)
typeInfo.instance_size = C.gushort(extendable.InstanceSize())
typeInfo.n_preallocs = 0
typeInfo.instance_init = C.GInstanceInitFunc(C.cgoInstanceInit)
typeInfo.value_table = nil
gtype := C.g_type_register_static(
C.GType(extendable.Type()),
(*C.gchar)(C.CString(name)),
typeInfo,
C.GTypeFlags(0),
)
elem.TypeInit(&TypeInstance{gtype: gtype, gotype: elem})
registeredTypes[reflect.TypeOf(elem).String()] = gtype
return gtype
}
// privateFromObj returns the actual value of the address we stored in the object's private data.
func privateFromObj(obj unsafe.Pointer) unsafe.Pointer {
private := C.g_type_instance_get_private((*C.GTypeInstance)(obj), C.objectGType((*C.GObject)(obj)))
privAddr := (*unsafe.Pointer)(unsafe.Pointer(private))
return *privAddr
}

View File

@@ -1,11 +1,3 @@
package gst
// #include "gst.go.h"
import "C"
import "sync"
var registerMutex sync.RWMutex
var registeredTypes = make(map[string]C.GType)
var registeredClasses = make(map[C.gpointer]GoElement)
var globalURIHdlr URIHandler