package mpvembed /* #cgo pkg-config: mpv #include #include #include 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 }