diff --git a/Makefile b/Makefile index d462035..f6f0e59 100644 --- a/Makefile +++ b/Makefile @@ -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 diff --git a/examples/common.go b/examples/common.go index 496e179..9836795 100644 --- a/examples/common.go +++ b/examples/common.go @@ -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 { diff --git a/examples/custom_events/main.go b/examples/custom_events/main.go index 68ad779..f92ede2 100644 --- a/examples/custom_events/main.go +++ b/examples/custom_events/main.go @@ -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 { diff --git a/examples/decodebin/main.go b/examples/decodebin/main.go index 77218a0..b01f971 100644 --- a/examples/decodebin/main.go +++ b/examples/decodebin/main.go @@ -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 diff --git a/examples/events/main.go b/examples/events/main.go index be1485d..e62b12e 100644 --- a/examples/events/main.go +++ b/examples/events/main.go @@ -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) }) } diff --git a/examples/gif-encoder/main.go b/examples/gif-encoder/main.go index 51f65e6..8072b92 100644 --- a/examples/gif-encoder/main.go +++ b/examples/gif-encoder/main.go @@ -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. diff --git a/examples/launch/main.go b/examples/launch/main.go index fa8bb07..e3f55cd 100644 --- a/examples/launch/main.go +++ b/examples/launch/main.go @@ -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) }) } diff --git a/examples/pad-probes/main.go b/examples/pad-probes/main.go index 328c055..83d283d 100644 --- a/examples/pad-probes/main.go +++ b/examples/pad-probes/main.go @@ -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. diff --git a/examples/playbin/main.go b/examples/playbin/main.go index 90eb84f..1bdf399 100644 --- a/examples/playbin/main.go +++ b/examples/playbin/main.go @@ -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 ") } diff --git a/examples/plugins/gofilesink/filesink.go b/examples/plugins/gofilesink/filesink.go index 9820973..aed041e 100644 --- a/examples/plugins/gofilesink/filesink.go +++ b/examples/plugins/gofilesink/filesink.go @@ -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 ", ) 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 diff --git a/examples/plugins/gofilesrc/filesrc.go b/examples/plugins/gofilesrc/filesrc.go index df3883b..14aef15 100644 --- a/examples/plugins/gofilesrc/filesrc.go +++ b/examples/plugins/gofilesrc/filesrc.go @@ -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 ", ) 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 diff --git a/examples/plugins/minio/common.go b/examples/plugins/minio/common.go deleted file mode 100644 index 3de8b9e..0000000 --- a/examples/plugins/minio/common.go +++ /dev/null @@ -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), - } -} diff --git a/examples/plugins/minio/miniosink.go b/examples/plugins/minio/miniosink.go deleted file mode 100644 index 1bf48c5..0000000 --- a/examples/plugins/minio/miniosink.go +++ /dev/null @@ -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 ", - ) - 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 -} diff --git a/examples/plugins/minio/miniosrc.go b/examples/plugins/minio/miniosrc.go deleted file mode 100644 index 6f5701c..0000000 --- a/examples/plugins/minio/miniosrc.go +++ /dev/null @@ -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 ", - ) - 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 -} diff --git a/examples/plugins/minio/plugin.go b/examples/plugins/minio/plugin.go deleted file mode 100644 index f14970d..0000000 --- a/examples/plugins/minio/plugin.go +++ /dev/null @@ -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() } diff --git a/examples/plugins/websocketsrc/websocketsrc.go b/examples/plugins/websocketsrc/websocketsrc.go index 74ac06b..8993ea1 100644 --- a/examples/plugins/websocketsrc/websocketsrc.go +++ b/examples/plugins/websocketsrc/websocketsrc.go @@ -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 ", ) - klass.AddPadTemplate(gst.NewPadTemplate( + class.AddPadTemplate(gst.NewPadTemplate( "src", gst.PadDirectionSource, gst.PadPresenceAlways, gst.NewAnyCaps(), )) - klass.InstallProperties(properties) + class.InstallProperties(properties) } // * Object * // diff --git a/examples/queries/main.go b/examples/queries/main.go index 549b904..f8e3712 100644 --- a/examples/queries/main.go +++ b/examples/queries/main.go @@ -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 ") diff --git a/examples/toc/main.go b/examples/toc/main.go index 311d29b..c843904 100644 --- a/examples/toc/main.go +++ b/examples/toc/main.go @@ -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 { diff --git a/go.mod b/go.mod index c180a5f..6054cf4 100644 --- a/go.mod +++ b/go.mod @@ -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 ) diff --git a/go.sum b/go.sum index 3625e09..57d0146 100644 --- a/go.sum +++ b/go.sum @@ -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= diff --git a/gst/app/gst_app_sink.go b/gst/app/gst_app_sink.go index eafd6cf..e777f88 100644 --- a/gst/app/gst_app_sink.go +++ b/gst/app/gst_app_sink.go @@ -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) { diff --git a/gst/app/gst_app_src.go b/gst/app/gst_app_src.go index 1e812f8..e432c7a 100644 --- a/gst/app/gst_app_src.go +++ b/gst/app/gst_app_src.go @@ -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) { diff --git a/gst/app/wrappers.go b/gst/app/wrappers.go index fa04b88..1d45b96 100644 --- a/gst/app/wrappers.go +++ b/gst/app/wrappers.go @@ -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 } diff --git a/gst/base/gst_base_sink_exports.go b/gst/base/gst_base_sink_exports.go index e59edcd..389f9f4 100644 --- a/gst/base/gst_base_sink_exports.go +++ b/gst/base/gst_base_sink_exports.go @@ -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)))) diff --git a/gst/base/gst_base_sink_impl.go b/gst/base/gst_base_sink_impl.go index 2776edb..44306bc 100644 --- a/gst/base/gst_base_sink_impl.go +++ b/gst/base/gst_base_sink_impl.go @@ -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) diff --git a/gst/base/gst_base_src_exports.go b/gst/base/gst_base_src_exports.go index c5a236f..5446b00 100644 --- a/gst/base/gst_base_src_exports.go +++ b/gst/base/gst_base_src_exports.go @@ -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 }) diff --git a/gst/base/gst_base_src_impl.go b/gst/base/gst_base_src_impl.go index 7b18aa6..062304e 100644 --- a/gst/base/gst_base_src_impl.go +++ b/gst/base/gst_base_src_impl.go @@ -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) diff --git a/gst/base/gst_base_transform_exports.go b/gst/base/gst_base_transform_exports.go index 939b9a6..8c48104 100644 --- a/gst/base/gst_base_transform_exports.go +++ b/gst/base/gst_base_transform_exports.go @@ -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) }) diff --git a/gst/base/gst_base_transform_impl.go b/gst/base/gst_base_transform_impl.go index 1d2b0af..e324801 100644 --- a/gst/base/gst_base_transform_impl.go +++ b/gst/base/gst_base_transform_impl.go @@ -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) diff --git a/gst/base/gst_push_src_exports.go b/gst/base/gst_push_src_exports.go index ce07afb..8e87475 100644 --- a/gst/base/gst_push_src_exports.go +++ b/gst/base/gst_push_src_exports.go @@ -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)))) diff --git a/gst/base/gst_push_src_impl.go b/gst/base/gst_push_src_impl.go index b42645c..b794fdb 100644 --- a/gst/base/gst_push_src_impl.go +++ b/gst/base/gst_push_src_impl.go @@ -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) diff --git a/gst/cgo_exports.go b/gst/cgo_exports.go index 51a85fa..68f760b 100644 --- a/gst/cgo_exports.go +++ b/gst/cgo_exports.go @@ -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))) -} diff --git a/gst/g_error.go b/gst/g_error.go deleted file mode 100644 index 553b712..0000000 --- a/gst/g_error.go +++ /dev/null @@ -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, - } -} diff --git a/gst/g_main_loop.go b/gst/g_main_loop.go deleted file mode 100644 index 1dc6450..0000000 --- a/gst/g_main_loop.go +++ /dev/null @@ -1,117 +0,0 @@ -package gst - -/* -#include -*/ -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()) } diff --git a/gst/g_object.go b/gst/g_object.go deleted file mode 100644 index 17abdae..0000000 --- a/gst/g_object.go +++ /dev/null @@ -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) - } -} diff --git a/gst/g_object_class.go b/gst/g_object_class.go deleted file mode 100644 index f65e6cd..0000000 --- a/gst/g_object_class.go +++ /dev/null @@ -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, - ) -} diff --git a/gst/g_param_spec.go b/gst/g_param_spec.go deleted file mode 100644 index 88496c6..0000000 --- a/gst/g_param_spec.go +++ /dev/null @@ -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, ", ") -} diff --git a/gst/g_param_spec_constructors.go b/gst/g_param_spec_constructors.go deleted file mode 100644 index ae68827..0000000 --- a/gst/g_param_spec_constructors.go +++ /dev/null @@ -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} -} diff --git a/gst/gst.go.h b/gst/gst.go.h index dac3544..0e6c708 100644 --- a/gst/gst.go.h +++ b/gst/gst.go.h @@ -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 */ diff --git a/gst/gst_element.go b/gst/gst_element.go index ce37199..44eaebc 100644 --- a/gst/gst_element.go +++ b/gst/gst_element.go @@ -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) diff --git a/gst/gst_element_class.go b/gst/gst_element_class.go index 54e8af7..45368e1 100644 --- a/gst/gst_element_class.go +++ b/gst/gst_element_class.go @@ -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 { diff --git a/gst/gst_element_exports.go b/gst/gst_element_exports.go index e96d122..3b58ac3 100644 --- a/gst/gst_element_exports.go +++ b/gst/gst_element_exports.go @@ -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)) diff --git a/gst/gst_errors.go b/gst/gst_errors.go index 0c914ae..ddc4a80 100644 --- a/gst/gst_errors.go +++ b/gst/gst_errors.go @@ -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, + } +} diff --git a/gst/gst_object.go b/gst/gst_object.go index 8f9f833..c9e6bb0 100644 --- a/gst/gst_object.go +++ b/gst/gst_object.go @@ -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 } diff --git a/gst/gst_param_flags.go b/gst/gst_param_flags.go new file mode 100644 index 0000000..df58004 --- /dev/null +++ b/gst/gst_param_flags.go @@ -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 +) diff --git a/gst/gst_uri_handler.go b/gst/gst_uri_handler.go index 0d30983..ccb3d17 100644 --- a/gst/gst_uri_handler.go +++ b/gst/gst_uri_handler.go @@ -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. diff --git a/gst/gst_wrappers.go b/gst/gst_wrappers.go index 0a01f5c..b065548 100644 --- a/gst/gst_wrappers.go +++ b/gst/gst_wrappers.go @@ -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))) } diff --git a/gst/gstauto/bufio.go b/gst/gstauto/bufio.go deleted file mode 100644 index 8842e00..0000000 --- a/gst/gstauto/bufio.go +++ /dev/null @@ -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() -} diff --git a/gst/gstauto/doc.go b/gst/gstauto/doc.go deleted file mode 100644 index c5624f3..0000000 --- a/gst/gstauto/doc.go +++ /dev/null @@ -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 diff --git a/gst/gstauto/pipeline_config.go b/gst/gstauto/pipeline_config.go deleted file mode 100644 index 6470329..0000000 --- a/gst/gstauto/pipeline_config.go +++ /dev/null @@ -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 -} diff --git a/gst/gstauto/pipeline_interfaces.go b/gst/gstauto/pipeline_interfaces.go deleted file mode 100644 index 53e205d..0000000 --- a/gst/gstauto/pipeline_interfaces.go +++ /dev/null @@ -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 -} diff --git a/gst/gstauto/pipeline_reader.go b/gst/gstauto/pipeline_reader.go deleted file mode 100644 index f36f53b..0000000 --- a/gst/gstauto/pipeline_reader.go +++ /dev/null @@ -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) } diff --git a/gst/gstauto/pipeline_readwriter.go b/gst/gstauto/pipeline_readwriter.go deleted file mode 100644 index 35b285a..0000000 --- a/gst/gstauto/pipeline_readwriter.go +++ /dev/null @@ -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) } diff --git a/gst/gstauto/pipeline_simple.go b/gst/gstauto/pipeline_simple.go deleted file mode 100644 index 69ea8c5..0000000 --- a/gst/gstauto/pipeline_simple.go +++ /dev/null @@ -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 -} diff --git a/gst/gstauto/pipeline_simple_reader.go b/gst/gstauto/pipeline_simple_reader.go deleted file mode 100644 index 9d6d904..0000000 --- a/gst/gstauto/pipeline_simple_reader.go +++ /dev/null @@ -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) -} diff --git a/gst/gstauto/pipeline_simple_readwriter.go b/gst/gstauto/pipeline_simple_readwriter.go deleted file mode 100644 index e02a0b9..0000000 --- a/gst/gstauto/pipeline_simple_readwriter.go +++ /dev/null @@ -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 -} diff --git a/gst/gstauto/pipeline_simple_writer.go b/gst/gstauto/pipeline_simple_writer.go deleted file mode 100644 index bf4f1db..0000000 --- a/gst/gstauto/pipeline_simple_writer.go +++ /dev/null @@ -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) -} diff --git a/gst/gstauto/pipeline_writer.go b/gst/gstauto/pipeline_writer.go deleted file mode 100644 index f17a893..0000000 --- a/gst/gstauto/pipeline_writer.go +++ /dev/null @@ -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) } diff --git a/gst/gstauto/util.go b/gst/gstauto/util.go deleted file mode 100644 index 8f2094c..0000000 --- a/gst/gstauto/util.go +++ /dev/null @@ -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()) - } -} diff --git a/gst/interfaces.go b/gst/interfaces.go deleted file mode 100644 index ea2d2f5..0000000 --- a/gst/interfaces.go +++ /dev/null @@ -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 -} diff --git a/gst/register.go b/gst/register.go index a1e1aca..074a8f1 100644 --- a/gst/register.go +++ b/gst/register.go @@ -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