forked from Leak_Technologies/VideoTools
181 lines
5.1 KiB
Go
181 lines
5.1 KiB
Go
package mpvembed
|
|
|
|
/*
|
|
#cgo pkg-config: mpv
|
|
#include <mpv/client.h>
|
|
#include <stdlib.h>
|
|
#include <locale.h>
|
|
|
|
static inline const char* mpv_errstr(int err) { return mpv_error_string(err); }
|
|
*/
|
|
import "C"
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"unsafe"
|
|
)
|
|
|
|
// Client wraps a libmpv handle.
|
|
type Client struct {
|
|
handle *C.mpv_handle
|
|
}
|
|
|
|
// New creates a new mpv client.
|
|
func New() (*Client, error) {
|
|
// Ensure numeric locale is C to satisfy mpv.
|
|
C.setlocale(C.int(C.LC_NUMERIC), C.CString("C"))
|
|
h := C.mpv_create()
|
|
if h == nil {
|
|
return nil, errors.New("mpv_create returned nil")
|
|
}
|
|
return &Client{handle: h}, nil
|
|
}
|
|
|
|
// Initialize must be called before issuing commands.
|
|
func (c *Client) Initialize() error {
|
|
if c.handle == nil {
|
|
return errors.New("mpv handle is nil")
|
|
}
|
|
if res := C.mpv_initialize(c.handle); res < 0 {
|
|
return fmt.Errorf("mpv_initialize failed: %s", C.GoString(C.mpv_errstr(res)))
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Destroy terminates and frees the client.
|
|
func (c *Client) Destroy() {
|
|
if c.handle != nil {
|
|
C.mpv_terminate_destroy(c.handle)
|
|
c.handle = nil
|
|
}
|
|
}
|
|
|
|
// SetOptionString sets an option before initialize.
|
|
func (c *Client) SetOptionString(name, value string) error {
|
|
if c.handle == nil {
|
|
return errors.New("mpv handle is nil")
|
|
}
|
|
cname := C.CString(name)
|
|
defer C.free(unsafe.Pointer(cname))
|
|
cval := C.CString(value)
|
|
defer C.free(unsafe.Pointer(cval))
|
|
if res := C.mpv_set_option_string(c.handle, cname, cval); res < 0 {
|
|
return fmt.Errorf("mpv_set_option_string %s failed: %s", name, C.GoString(C.mpv_errstr(res)))
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// SetOptionInt sets an integer option.
|
|
func (c *Client) SetOptionInt(name string, val int64) error {
|
|
if c.handle == nil {
|
|
return errors.New("mpv handle is nil")
|
|
}
|
|
cname := C.CString(name)
|
|
defer C.free(unsafe.Pointer(cname))
|
|
cval := C.longlong(val)
|
|
if res := C.mpv_set_option(c.handle, cname, C.mpv_format(C.MPV_FORMAT_INT64), unsafe.Pointer(&cval)); res < 0 {
|
|
return fmt.Errorf("mpv_set_option %s failed: %s", name, C.GoString(C.mpv_errstr(res)))
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// SetWID binds a native window ID to mpv (for embedding).
|
|
func (c *Client) SetWID(wid uint64) error {
|
|
return c.SetOptionInt("wid", int64(wid))
|
|
}
|
|
|
|
// Command issues an mpv command with arguments.
|
|
func (c *Client) Command(args ...string) error {
|
|
if c.handle == nil {
|
|
return errors.New("mpv handle is nil")
|
|
}
|
|
// Build a NULL-terminated array of *char
|
|
cargs := make([]*C.char, len(args)+1)
|
|
for i, a := range args {
|
|
cstr := C.CString(a)
|
|
defer C.free(unsafe.Pointer(cstr))
|
|
cargs[i] = cstr
|
|
}
|
|
cargs[len(args)] = nil
|
|
if res := C.mpv_command(c.handle, &cargs[0]); res < 0 {
|
|
return fmt.Errorf("mpv_command %v failed: %s", args, C.GoString(C.mpv_errstr(res)))
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// SetPropertyBool sets a boolean property.
|
|
func (c *Client) SetPropertyBool(name string, v bool) error {
|
|
if c.handle == nil {
|
|
return errors.New("mpv handle is nil")
|
|
}
|
|
cname := C.CString(name)
|
|
defer C.free(unsafe.Pointer(cname))
|
|
cval := C.int(0)
|
|
if v {
|
|
cval = 1
|
|
}
|
|
if res := C.mpv_set_property(c.handle, cname, C.mpv_format(C.MPV_FORMAT_FLAG), unsafe.Pointer(&cval)); res < 0 {
|
|
return fmt.Errorf("mpv_set_property %s failed: %s", name, C.GoString(C.mpv_errstr(res)))
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// SetPropertyDouble sets a double property.
|
|
func (c *Client) SetPropertyDouble(name string, v float64) error {
|
|
if c.handle == nil {
|
|
return errors.New("mpv handle is nil")
|
|
}
|
|
cname := C.CString(name)
|
|
defer C.free(unsafe.Pointer(cname))
|
|
cval := C.double(v)
|
|
if res := C.mpv_set_property(c.handle, cname, C.mpv_format(C.MPV_FORMAT_DOUBLE), unsafe.Pointer(&cval)); res < 0 {
|
|
return fmt.Errorf("mpv_set_property %s failed: %s", name, C.GoString(C.mpv_errstr(res)))
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// GetPropertyDouble gets a double property.
|
|
func (c *Client) GetPropertyDouble(name string) (float64, error) {
|
|
if c.handle == nil {
|
|
return 0, errors.New("mpv handle is nil")
|
|
}
|
|
cname := C.CString(name)
|
|
defer C.free(unsafe.Pointer(cname))
|
|
var out C.double
|
|
if res := C.mpv_get_property(c.handle, cname, C.mpv_format(C.MPV_FORMAT_DOUBLE), unsafe.Pointer(&out)); res < 0 {
|
|
return 0, fmt.Errorf("mpv_get_property %s failed: %s", name, C.GoString(C.mpv_errstr(res)))
|
|
}
|
|
return float64(out), nil
|
|
}
|
|
|
|
// GetPropertyInt64 gets an int64 property.
|
|
func (c *Client) GetPropertyInt64(name string) (int64, error) {
|
|
if c.handle == nil {
|
|
return 0, errors.New("mpv handle is nil")
|
|
}
|
|
cname := C.CString(name)
|
|
defer C.free(unsafe.Pointer(cname))
|
|
var out C.longlong
|
|
if res := C.mpv_get_property(c.handle, cname, C.mpv_format(C.MPV_FORMAT_INT64), unsafe.Pointer(&out)); res < 0 {
|
|
return 0, fmt.Errorf("mpv_get_property %s failed: %s", name, C.GoString(C.mpv_errstr(res)))
|
|
}
|
|
return int64(out), nil
|
|
}
|
|
|
|
// GetPropertyString gets a string property.
|
|
func (c *Client) GetPropertyString(name string) (string, error) {
|
|
if c.handle == nil {
|
|
return "", errors.New("mpv handle is nil")
|
|
}
|
|
cname := C.CString(name)
|
|
defer C.free(unsafe.Pointer(cname))
|
|
var out *C.char
|
|
if res := C.mpv_get_property(c.handle, cname, C.mpv_format(C.MPV_FORMAT_STRING), unsafe.Pointer(&out)); res < 0 {
|
|
return "", fmt.Errorf("mpv_get_property %s failed: %s", name, C.GoString(C.mpv_errstr(res)))
|
|
}
|
|
if out == nil {
|
|
return "", nil
|
|
}
|
|
return C.GoString(out), nil
|
|
}
|