mirror of
https://github.com/go-gst/go-gst.git
synced 2025-10-05 07:56:51 +08:00
314 lines
9.6 KiB
Go
314 lines
9.6 KiB
Go
package gst
|
|
|
|
import (
|
|
"fmt"
|
|
"runtime"
|
|
"strings"
|
|
"unsafe"
|
|
|
|
"github.com/diamondburned/gotk4/pkg/gobject/v2"
|
|
)
|
|
|
|
// #cgo pkg-config: gstreamer-1.0
|
|
// #cgo CFLAGS: -Wno-deprecated-declarations
|
|
// #include <gst/gst.h>
|
|
import "C"
|
|
|
|
// NewMessagePropertyNotify wraps gst_message_new_property_notify
|
|
//
|
|
// The function takes the following parameters:
|
|
//
|
|
// - src Object: The #GstObject whose property changed (may or may not be a #GstElement)
|
|
// - propertyName string: name of the property that changed
|
|
// - val any (nullable): new property value, or %NULL
|
|
//
|
|
// The function returns the following values:
|
|
//
|
|
// - goret *Message
|
|
func NewMessagePropertyNotify(src Object, propertyName string, val any) *Message {
|
|
var carg1 *C.GstObject // in, none, converted
|
|
var carg2 *C.gchar // in, none, string, casted *C.gchar
|
|
var carg3 *C.GValue // in, full, converted, nullable
|
|
var cret *C.GstMessage // return, full, converted
|
|
|
|
carg1 = (*C.GstObject)(UnsafeObjectToGlibNone(src))
|
|
carg2 = (*C.gchar)(unsafe.Pointer(C.CString(propertyName)))
|
|
defer C.free(unsafe.Pointer(carg2))
|
|
if val != nil {
|
|
carg3 = (*C.GValue)(gobject.UnsafeValueToGlibFull(gobject.NewValue(val)))
|
|
}
|
|
|
|
cret = C.gst_message_new_property_notify(carg1, carg2, carg3)
|
|
runtime.KeepAlive(src)
|
|
runtime.KeepAlive(propertyName)
|
|
runtime.KeepAlive(val)
|
|
|
|
var goret *Message
|
|
|
|
goret = UnsafeMessageFromGlibFull(unsafe.Pointer(cret))
|
|
|
|
return goret
|
|
}
|
|
|
|
// ParsePropertyNotify wraps gst_message_parse_property_notify
|
|
// The function returns the following values:
|
|
//
|
|
// - object Object: location where to store a
|
|
// pointer to the object whose property got changed, or %NULL
|
|
// - propertyName string: return location for
|
|
// the name of the property that got changed, or %NULL
|
|
// - propertyValue *gobject.Value (nullable): return location for
|
|
// the new value of the property that got changed, or %NULL. This will
|
|
// only be set if the property notify watch was told to include the value
|
|
// when it was set up
|
|
//
|
|
// Parses a property-notify message. These will be posted on the bus only
|
|
// when set up with gst_element_add_property_notify_watch() or
|
|
// gst_element_add_property_deep_notify_watch().
|
|
func (message *Message) ParsePropertyNotify() (Object, string, any) {
|
|
var carg0 *C.GstMessage // in, none, converted
|
|
var carg1 *C.GstObject // out, none, converted
|
|
var carg2 *C.gchar // out, none, string, casted *C.gchar
|
|
var carg3 *C.GValue // out, none, converted, nullable
|
|
|
|
carg0 = (*C.GstMessage)(UnsafeMessageToGlibNone(message))
|
|
|
|
C.gst_message_parse_property_notify(carg0, &carg1, &carg2, &carg3)
|
|
runtime.KeepAlive(message)
|
|
|
|
var object Object
|
|
var propertyName string
|
|
var propertyValue any
|
|
|
|
object = UnsafeObjectFromGlibNone(unsafe.Pointer(carg1))
|
|
propertyName = C.GoString((*C.char)(unsafe.Pointer(carg2)))
|
|
if carg3 != nil {
|
|
propertyValue = gobject.ValueFromNative(unsafe.Pointer(carg3)).GoValue()
|
|
}
|
|
|
|
return object, propertyName, propertyValue
|
|
}
|
|
|
|
// GetStreamStatusObject wraps gst_message_get_stream_status_object
|
|
// The function returns the following values:
|
|
//
|
|
// - goret *gobject.Value
|
|
//
|
|
// Extracts the object managing the streaming thread from @message.
|
|
func (message *Message) GetStreamStatusObject() any {
|
|
var carg0 *C.GstMessage // in, none, converted
|
|
var cret *C.GValue // return, none, converted
|
|
|
|
carg0 = (*C.GstMessage)(UnsafeMessageToGlibNone(message))
|
|
|
|
cret = C.gst_message_get_stream_status_object(carg0)
|
|
runtime.KeepAlive(message)
|
|
|
|
var goret any
|
|
|
|
goret = gobject.ValueFromNative(unsafe.Pointer(cret)).GoValue()
|
|
|
|
return goret
|
|
}
|
|
|
|
// Type returns the MessageType of the message.
|
|
func (message *Message) Type() MessageType {
|
|
return MessageType(message.message.native._type)
|
|
}
|
|
|
|
// Source returns the source object of the message.
|
|
func (message *Message) Source() Object {
|
|
return UnsafeObjectFromGlibNone(unsafe.Pointer(message.message.native.src))
|
|
}
|
|
|
|
// String implements a stringer on the message. It iterates over the type of the message
|
|
// and applies the correct parser, then dumps a string of the basic contents of the
|
|
// message. This function can be expensive and should only be used for debugging purposes
|
|
// or in routines where latency is not a concern.
|
|
//
|
|
// This stringer really just helps in keeping track of making sure all message types are
|
|
// accounted for in some way. It's the devil, writing it was the devil, and I hope you
|
|
// enjoy being able to `fmt.Println(msg)`.
|
|
func (m *Message) String() string {
|
|
msg := fmt.Sprintf("[%s] %s - ", m.Source().GetName(), m.Type().String())
|
|
switch m.Type() {
|
|
|
|
case MessageEos:
|
|
msg += "End-of-stream reached in the pipeline"
|
|
|
|
case MessageInfo:
|
|
info, err := m.ParseInfo()
|
|
msg += fmt.Sprintf("Info: %s, err: %v", info, err)
|
|
|
|
case MessageWarning:
|
|
info, err := m.ParseWarning()
|
|
msg += fmt.Sprintf("Warning: %s, err: %v", info, err)
|
|
|
|
case MessageError:
|
|
info, err := m.ParseError()
|
|
msg += fmt.Sprintf("Error: %s, err: %v", info, err)
|
|
|
|
case MessageTag:
|
|
tags := m.ParseTag()
|
|
|
|
_ = tags // TODO
|
|
msg += "Tags: TODO"
|
|
|
|
case MessageBuffering:
|
|
mode, avgIn, avgOut, bufferingLeft := m.ParseBufferingStats()
|
|
msg += fmt.Sprintf(
|
|
"Buffering %s - %d%% complete (avg in %d/sec, avg out %d/sec, time left %d)",
|
|
mode,
|
|
m.ParseBuffering(),
|
|
avgIn,
|
|
avgOut,
|
|
bufferingLeft,
|
|
)
|
|
|
|
case MessageStateChanged:
|
|
oldstate, newstate, pending := m.ParseStateChanged()
|
|
|
|
msg += fmt.Sprintf("State changed from %s to %s (pending %s)", oldstate, newstate, pending)
|
|
|
|
case MessageStateDirty:
|
|
msg += "(DEPRECATED MESSAGE) An element changed state in a streaming thread"
|
|
|
|
case MessageStepDone:
|
|
format, amount, rate, flush, intermediate, duration, eos := m.ParseStepDone()
|
|
|
|
msg += fmt.Sprintf(
|
|
"Step done with format %s, amount %d, rate %f, flush %v, intermediate %v, duration %d, eos %v",
|
|
format.String(),
|
|
amount,
|
|
rate,
|
|
flush,
|
|
intermediate,
|
|
duration,
|
|
eos,
|
|
)
|
|
|
|
case MessageClockProvide:
|
|
msg += "Element has clock provide capability"
|
|
|
|
case MessageClockLost:
|
|
msg += "Lost a clock"
|
|
|
|
case MessageNewClock:
|
|
clock := m.ParseNewClock()
|
|
msg += fmt.Sprintf("New clock: %s (%s)", clock.GetName(), clock.GoValueType())
|
|
|
|
case MessageStructureChange:
|
|
chgType, elem, busy := m.ParseStructureChange()
|
|
msg += fmt.Sprintf("Structure change of type %s from %s. (in progress: %v)", chgType.String(), elem.GetName(), busy)
|
|
|
|
case MessageStreamStatus:
|
|
statusType, elem := m.ParseStreamStatus()
|
|
msg += fmt.Sprintf("Stream status from %s: %s", elem.GetName(), statusType.String())
|
|
|
|
case MessageApplication:
|
|
msg += "Message posted by the application, possibly via an application-specific element."
|
|
|
|
case MessageElement:
|
|
msg += "Internal element message posted"
|
|
|
|
case MessageSegmentStart:
|
|
format, pos := m.ParseSegmentStart()
|
|
msg += fmt.Sprintf("Segment started at %d %s", pos, format.String())
|
|
|
|
case MessageSegmentDone:
|
|
format, pos := m.ParseSegmentDone()
|
|
msg += fmt.Sprintf("Segment started at %d %s", pos, format.String())
|
|
|
|
case MessageDurationChanged:
|
|
msg += "The duration of the pipeline changed"
|
|
|
|
case MessageLatency:
|
|
msg += "Element's latency has changed"
|
|
|
|
case MessageAsyncStart:
|
|
msg += "Async task started"
|
|
|
|
case MessageAsyncDone:
|
|
msg += "Async task completed"
|
|
if dur := m.ParseAsyncDone(); dur > 0 {
|
|
msg += fmt.Sprintf(" in %d", dur)
|
|
}
|
|
|
|
case MessageRequestState:
|
|
msg += fmt.Sprintf("State change request to %s", m.ParseRequestState().String())
|
|
|
|
case MessageStepStart:
|
|
active, format, amount, rate, flush, intermediate := m.ParseStepStart()
|
|
|
|
msg += fmt.Sprintf("Step started with active %v, format %s, amount %d, rate %f, flush %v, intermediate %v",
|
|
active, format.String(), amount, rate, flush, intermediate,
|
|
)
|
|
|
|
case MessageQos:
|
|
format, processed, dropped := m.ParseQosStats()
|
|
|
|
msg += fmt.Sprintf("Qos stats: format %s, processed %d, dropped %d", format.String(), processed, dropped)
|
|
|
|
case MessageProgress:
|
|
progressType, code, text := m.ParseProgress()
|
|
msg += fmt.Sprintf("%s - %s - %s", strings.ToUpper(progressType.String()), code, text)
|
|
|
|
case MessageToc:
|
|
toc, updated := m.ParseToc()
|
|
_ = toc // TODO: also show some info about the toc
|
|
msg += fmt.Sprintf("Message toc updated: %t", updated)
|
|
|
|
case MessageResetTime:
|
|
msg += fmt.Sprintf("Running time: %s", m.ParseResetTime())
|
|
|
|
case MessageStreamStart:
|
|
msg += "Pipeline stream is starting"
|
|
|
|
case MessageNeedContext:
|
|
msg += "Element needs context"
|
|
|
|
case MessageHaveContext:
|
|
ctx := m.ParseHaveContext()
|
|
_ = ctx // TODO
|
|
msg += fmt.Sprintf("Received context of type %s", "ctx.GetType()")
|
|
|
|
case MessageExtended:
|
|
msg += "Extended message type"
|
|
|
|
case MessageDeviceAdded:
|
|
device := m.ParseDeviceAdded()
|
|
msg += fmt.Sprintf("Device %s added", device.GetDisplayName())
|
|
|
|
case MessageDeviceRemoved:
|
|
device := m.ParseDeviceRemoved()
|
|
msg += fmt.Sprintf("Device %s removed", device.GetDisplayName())
|
|
|
|
case MessageDeviceChanged:
|
|
device, _ := m.ParseDeviceChanged()
|
|
msg += fmt.Sprintf("Device %s had its properties updated", device.GetDisplayName())
|
|
|
|
case MessagePropertyNotify:
|
|
obj, propName, propVal := m.ParsePropertyNotify()
|
|
|
|
msg += fmt.Sprintf("Object %s had property '%s' changed to %+v", obj.GetName(), propName, propVal)
|
|
|
|
case MessageStreamCollection:
|
|
collection := m.ParseStreamCollection()
|
|
msg += fmt.Sprintf("New stream collection with upstream id: %s", collection.GetUpstreamID())
|
|
|
|
case MessageStreamsSelected:
|
|
collection := m.ParseStreamsSelected()
|
|
msg += fmt.Sprintf("Stream with upstream id '%s' has selected new streams", collection.GetUpstreamID())
|
|
|
|
case MessageRedirect:
|
|
msg += fmt.Sprintf("Received redirect message with %d entries", m.GetNumRedirectEntries())
|
|
|
|
case MessageUnknown:
|
|
msg += "Unknown message type"
|
|
|
|
case MessageAny:
|
|
msg += "Message did not match any known types"
|
|
}
|
|
return msg
|
|
}
|