/*
* Copyright (c) 2014-2021 gnome-mpv
*
* This file is part of Celluloid.
*
* Celluloid is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Celluloid is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Celluloid. If not, see .
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#ifdef GDK_WINDOWING_X11
#include
#include
#endif
#ifdef GDK_WINDOWING_WAYLAND
#include
#include
#endif
#ifdef GDK_WINDOWING_WIN32
#include
#include
#endif
#include "celluloid-mpv.h"
#include "celluloid-common.h"
#include "celluloid-def.h"
#include "celluloid-marshal.h"
#define get_private(mpv) \
((CelluloidMpvPrivate *)celluloid_mpv_get_instance_private(mpv))
typedef struct _CelluloidMpvPrivate CelluloidMpvPrivate;
enum
{
PROP_0,
PROP_WID,
PROP_READY,
N_PROPERTIES
};
struct _CelluloidMpvPrivate
{
mpv_handle *mpv_ctx;
mpv_render_context *render_ctx;
gboolean ready;
gchar *tmp_input_file;
GSList *log_level_list;
gboolean init_vo_config;
gboolean force_opengl;
gboolean use_opengl;
gint64 wid;
void *render_update_callback_data;
void (*render_update_callback)(void *data);
};
static void *
get_proc_address(void *fn_ctx, const gchar *name);
static void
set_property( GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec );
static void
get_property( GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec );
static
void dispose(GObject *object);
static
void finalize(GObject *object);
static
void wakeup_callback(void *data);
static void
mpv_property_changed(CelluloidMpv *mpv, const gchar *name, gpointer value);
static void
mpv_log_message( CelluloidMpv *mpv,
mpv_log_level log_level,
const gchar *prefix,
const gchar *text );
static void
mpv_event_notify(CelluloidMpv *mpv, gint event_id, gpointer event_data);
static gboolean
process_mpv_events(gpointer data);
static gboolean
check_mpv_version(const gchar *version);
static gpointer
get_wl_display(void);
static gpointer
get_x11_display(void);
static void
initialize(CelluloidMpv *mpv);
static void
load_file(CelluloidMpv *mpv, const gchar *uri, gboolean append);
static void
reset(CelluloidMpv *mpv);
G_DEFINE_TYPE_WITH_PRIVATE(CelluloidMpv, celluloid_mpv, G_TYPE_OBJECT)
static void *
get_proc_address(void *fn_ctx, const gchar *name)
{
GdkDisplay *display = gdk_display_get_default();
#ifdef GDK_WINDOWING_WAYLAND
if (GDK_IS_WAYLAND_DISPLAY(display))
return eglGetProcAddress(name);
#endif
#ifdef GDK_WINDOWING_X11
if (GDK_IS_X11_DISPLAY(display))
return (void *)(intptr_t)
glXGetProcAddressARB((const GLubyte *)name);
#endif
#ifdef GDK_WINDOWING_WIN32
if (GDK_IS_WIN32_DISPLAY(display))
return wglGetProcAddress(name);
#endif
g_assert_not_reached();
return NULL;
}
static void
set_property( GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec )
{
CelluloidMpvPrivate *priv = get_private(CELLULOID_MPV(object));
if(property_id == PROP_WID)
{
priv->wid = g_value_get_int64(value);
}
else if(property_id == PROP_READY)
{
priv->ready = g_value_get_boolean(value);
}
else
{
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
}
}
static void
get_property( GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec )
{
CelluloidMpvPrivate *priv = get_private(CELLULOID_MPV(object));
if(property_id == PROP_WID)
{
g_value_set_int64(value, priv->wid);
}
else if(property_id == PROP_READY)
{
g_value_set_boolean(value, priv->ready);
}
else
{
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
}
}
static void
dispose(GObject *object)
{
CelluloidMpv *mpv = CELLULOID_MPV(object);
if(get_private(mpv)->mpv_ctx)
{
celluloid_mpv_quit(mpv);
while(g_source_remove_by_user_data(object));
}
G_OBJECT_CLASS(celluloid_mpv_parent_class)->dispose(object);
}
static void
finalize(GObject *object)
{
G_OBJECT_CLASS(celluloid_mpv_parent_class)->finalize(object);
}
static void
wakeup_callback(void *data)
{
g_idle_add_full(G_PRIORITY_HIGH_IDLE, process_mpv_events, data, NULL);
}
static void
mpv_property_changed(CelluloidMpv *mpv, const gchar *name, gpointer value)
{
g_debug("Received mpv property change event for \"%s\"", name);
}
static void
mpv_event_notify(CelluloidMpv *mpv, gint event_id, gpointer event_data)
{
if(event_id == MPV_EVENT_PROPERTY_CHANGE)
{
mpv_event_property *prop = event_data;
g_signal_emit_by_name( mpv,
"mpv-property-changed",
prop->name,
prop->data );
}
else if(event_id == MPV_EVENT_IDLE)
{
celluloid_mpv_set_property_flag(mpv, "pause", TRUE);
}
else if(event_id == MPV_EVENT_END_FILE)
{
GSettings *settings = g_settings_new(CONFIG_ROOT);
const gchar *ignore_key = "ignore-playback-errors";
mpv_event_end_file *ef_event = event_data;
if( !g_settings_get_boolean(settings, ignore_key) &&
ef_event->reason == MPV_END_FILE_REASON_ERROR )
{
const gchar *err;
gchar *msg;
err = mpv_error_string(ef_event->error);
msg = g_strdup_printf
( _("Playback was terminated "
"abnormally. Reason: %s."),
err );
celluloid_mpv_set_property_flag(mpv, "pause", TRUE);
g_signal_emit_by_name(mpv, "error", msg);
g_free(msg);
}
g_object_unref(settings);
}
else if(event_id == MPV_EVENT_LOG_MESSAGE)
{
mpv_event_log_message* message = event_data;
g_signal_emit_by_name( mpv,
"mpv-log-message",
message->log_level,
message->prefix,
message->text );
}
else if(event_id == MPV_EVENT_CLIENT_MESSAGE)
{
mpv_event_client_message *event_cmsg = event_data;
gchar* msg = strnjoinv( " ",
event_cmsg->args,
(gsize)event_cmsg->num_args );
g_signal_emit_by_name(mpv, "message", msg);
g_free(msg);
}
else if(event_id == MPV_EVENT_SHUTDOWN)
{
g_signal_emit_by_name(mpv, "shutdown");
}
}
static gboolean
process_mpv_events(gpointer data)
{
CelluloidMpv *mpv = data;
CelluloidMpvPrivate *priv = get_private(mpv);
gboolean done = !mpv;
while(!done)
{
mpv_event *event = priv->mpv_ctx?
mpv_wait_event(priv->mpv_ctx, 0):
NULL;
if(event)
{
if( !priv->mpv_ctx ||
event->event_id == MPV_EVENT_SHUTDOWN ||
event->event_id == MPV_EVENT_NONE )
{
done = TRUE;
}
g_signal_emit_by_name( mpv,
"mpv-event-notify",
event->event_id,
event->data );
}
else
{
done = TRUE;
}
}
return FALSE;
}
static gboolean
check_mpv_version(const gchar *version)
{
guint64 min_version[] = {MIN_MPV_MAJOR, MIN_MPV_MINOR, MIN_MPV_PATCH};
const guint min_version_length = G_N_ELEMENTS(min_version);
gchar **tokens = NULL;
gboolean done = FALSE;
gboolean result = TRUE;
/* Skip to the version number */
if(strncmp(version, "mpv ", 4) == 0)
{
tokens = g_strsplit(version+4, ".", (gint)min_version_length);
}
done = !tokens || g_strv_length(tokens) != min_version_length;
result = !done;
for(guint i = 0; i < min_version_length && !done && result; i++)
{
gchar *endptr = NULL;
guint64 token = g_ascii_strtoull(tokens[i], &endptr, 10);
/* If the token is equal to the minimum, continue checking the
* rest of the tokens. If it is greater, just skip them.
*/
result &= !(*endptr) && (token >= min_version[i]);
done = result && (token >= min_version[i]);
}
g_strfreev(tokens);
return result;
}
static gpointer
get_wl_display(void)
{
gpointer wl_display = NULL;
#ifdef GDK_WINDOWING_WAYLAND
GdkDisplay *display = gdk_display_get_default();
if(GDK_IS_WAYLAND_DISPLAY(display))
{
wl_display = gdk_wayland_display_get_wl_display(display);
}
#endif
return wl_display;
}
static gpointer
get_x11_display(void)
{
gpointer x11_display = NULL;
#ifdef GDK_WINDOWING_X11
GdkDisplay *display = gdk_display_get_default();
if(GDK_IS_X11_DISPLAY(display))
{
x11_display = gdk_x11_display_get_xdisplay(display);
}
#endif
return x11_display;
}
static void
initialize(CelluloidMpv *mpv)
{
CelluloidMpvPrivate *priv = get_private(mpv);
gchar *current_vo = NULL;
gchar *mpv_version = NULL;
if(priv->wid == 0)
{
g_info("Forcing --vo=null");
mpv_set_option_string(priv->mpv_ctx, "vo", "null");
}
else
{
g_info("Forcing --vo=libmpv");
mpv_set_option_string(priv->mpv_ctx, "vo", "libmpv");
}
mpv_set_wakeup_callback(priv->mpv_ctx, wakeup_callback, mpv);
mpv_initialize(priv->mpv_ctx);
mpv_version = celluloid_mpv_get_property_string(mpv, "mpv-version");
current_vo = celluloid_mpv_get_property_string(mpv, "current-vo");
priv->use_opengl = (!current_vo && priv->wid != 0);
g_info("Using %s", mpv_version);
if(!check_mpv_version(mpv_version))
{
g_warning( "Minimum mpv version requirement (%d.%d.%d) not met",
MIN_MPV_MAJOR,
MIN_MPV_MINOR,
MIN_MPV_PATCH );
}
priv->ready = TRUE;
g_object_notify(G_OBJECT(mpv), "ready");
mpv_free(current_vo);
mpv_free(mpv_version);
}
static void
load_file(CelluloidMpv *mpv, const gchar *uri, gboolean append)
{
CelluloidMpvPrivate *priv = get_private(mpv);
gchar *path = get_path_from_uri(uri);
const gchar *load_cmd[] = {"loadfile", path, NULL, NULL};
gint64 playlist_count = 0;
g_assert(uri);
g_info( "Loading file (append=%s): %s", append?"TRUE":"FALSE", uri);
mpv_get_property( priv->mpv_ctx,
"playlist-count",
MPV_FORMAT_INT64,
&playlist_count );
load_cmd[2] = (append && playlist_count > 0)?"append":"replace";
if(!append)
{
celluloid_mpv_set_property_flag(mpv, "pause", FALSE);
}
g_assert(priv->mpv_ctx);
mpv_request_event(priv->mpv_ctx, MPV_EVENT_END_FILE, 0);
mpv_command(priv->mpv_ctx, load_cmd);
mpv_request_event(priv->mpv_ctx, MPV_EVENT_END_FILE, 1);
g_free(path);
}
static void
reset(CelluloidMpv *mpv)
{
CelluloidMpvPrivate *priv = get_private(mpv);
gchar *loop_file_str;
gchar *loop_playlist_str;
gboolean loop_file;
gboolean loop_playlist;
loop_file_str = celluloid_mpv_get_property_string
(mpv, "loop-file");
loop_playlist_str = celluloid_mpv_get_property_string
(mpv, "loop-playlist");
loop_file = (g_strcmp0(loop_file_str, "inf") == 0);
loop_playlist = (g_strcmp0(loop_playlist_str, "inf") == 0);
mpv_free(loop_file_str);
mpv_free(loop_playlist_str);
/* Reset priv->mpv_ctx */
priv->ready = FALSE;
g_object_notify(G_OBJECT(mpv), "ready");
celluloid_mpv_command_string(mpv, "write-watch-later-config");
celluloid_mpv_quit(mpv);
priv->mpv_ctx = mpv_create();
celluloid_mpv_initialize(mpv);
celluloid_mpv_set_render_update_callback
( mpv,
priv->render_update_callback,
priv->render_update_callback_data );
celluloid_mpv_set_property_string
(mpv, "loop-file", loop_file?"inf":"no");
celluloid_mpv_set_property_string
(mpv, "loop-playlist", loop_playlist?"inf":"no");
}
static void
mpv_log_message( CelluloidMpv *mpv,
mpv_log_level log_level,
const gchar *prefix,
const gchar *text )
{
}
static void
celluloid_mpv_class_init(CelluloidMpvClass* klass)
{
GObjectClass *obj_class = G_OBJECT_CLASS(klass);
GParamSpec *pspec = NULL;
klass->mpv_event_notify = mpv_event_notify;
klass->mpv_log_message = mpv_log_message;
klass->mpv_property_changed = mpv_property_changed;
klass->initialize = initialize;
klass->load_file = load_file;
klass->reset = reset;
obj_class->set_property = set_property;
obj_class->get_property = get_property;
obj_class->dispose = dispose;
obj_class->finalize = finalize;
pspec = g_param_spec_int64
( "wid",
"WID",
"The ID of the window to attach to",
G_MININT64,
G_MAXINT64,
-1,
G_PARAM_CONSTRUCT_ONLY|G_PARAM_READWRITE );
g_object_class_install_property(obj_class, PROP_WID, pspec);
pspec = g_param_spec_boolean
( "ready",
"Ready",
"Whether mpv is initialized and ready to receive commands",
FALSE,
G_PARAM_READABLE );
g_object_class_install_property(obj_class, PROP_READY, pspec);
g_signal_new( "error",
G_TYPE_FROM_CLASS(klass),
G_SIGNAL_RUN_FIRST,
0,
NULL,
NULL,
g_cclosure_marshal_VOID__STRING,
G_TYPE_NONE,
1,
G_TYPE_STRING );
g_signal_new( "mpv-event-notify",
G_TYPE_FROM_CLASS(klass),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET(CelluloidMpvClass, mpv_event_notify),
NULL,
NULL,
g_cclosure_gen_marshal_VOID__INT_POINTER,
G_TYPE_NONE,
2,
G_TYPE_INT,
G_TYPE_POINTER );
g_signal_new( "mpv-log-message",
G_TYPE_FROM_CLASS(klass),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET(CelluloidMpvClass, mpv_log_message),
NULL,
NULL,
g_cclosure_gen_marshal_VOID__INT_STRING_STRING,
G_TYPE_NONE,
3,
G_TYPE_INT,
G_TYPE_STRING,
G_TYPE_STRING );
g_signal_new( "mpv-property-changed",
G_TYPE_FROM_CLASS(klass),
G_SIGNAL_RUN_FIRST,
G_STRUCT_OFFSET(CelluloidMpvClass, mpv_property_changed),
NULL,
NULL,
g_cclosure_gen_marshal_VOID__STRING_POINTER,
G_TYPE_NONE,
2,
G_TYPE_STRING,
G_TYPE_POINTER );
g_signal_new( "message",
G_TYPE_FROM_CLASS(klass),
G_SIGNAL_RUN_FIRST,
0,
NULL,
NULL,
g_cclosure_marshal_VOID__STRING,
G_TYPE_NONE,
1,
G_TYPE_STRING );
g_signal_new( "window-resize",
G_TYPE_FROM_CLASS(klass),
G_SIGNAL_RUN_FIRST,
0,
NULL,
NULL,
g_cclosure_gen_marshal_VOID__INT64_INT64,
G_TYPE_NONE,
2,
G_TYPE_INT64,
G_TYPE_INT64 );
g_signal_new( "window-move",
G_TYPE_FROM_CLASS(klass),
G_SIGNAL_RUN_FIRST,
0,
NULL,
NULL,
g_cclosure_gen_marshal_VOID__BOOLEAN_BOOLEAN_POINTER_POINTER,
G_TYPE_NONE,
4,
G_TYPE_BOOLEAN,
G_TYPE_BOOLEAN,
G_TYPE_POINTER,
G_TYPE_POINTER );
g_signal_new( "shutdown",
G_TYPE_FROM_CLASS(klass),
G_SIGNAL_RUN_FIRST,
0,
NULL,
NULL,
g_cclosure_marshal_VOID__VOID,
G_TYPE_NONE,
0 );
}
static void
celluloid_mpv_init(CelluloidMpv *mpv)
{
CelluloidMpvPrivate *priv = get_private(mpv);
setlocale(LC_NUMERIC, "C");
priv->mpv_ctx = mpv_create();
priv->render_ctx = NULL;
priv->ready = FALSE;
priv->init_vo_config = TRUE;
priv->use_opengl = FALSE;
priv->wid = -1;
priv->render_update_callback_data = NULL;
priv->render_update_callback = NULL;
}
CelluloidMpv *
celluloid_mpv_new(gint64 wid)
{
return CELLULOID_MPV(g_object_new(celluloid_mpv_get_type(), "wid", wid, NULL));
}
inline mpv_render_context *
celluloid_mpv_get_render_context(CelluloidMpv *mpv)
{
return get_private(mpv)->render_ctx;
}
inline gboolean
celluloid_mpv_get_use_opengl_cb(CelluloidMpv *mpv)
{
return get_private(mpv)->use_opengl;
}
void
celluloid_mpv_initialize(CelluloidMpv *mpv)
{
CELLULOID_MPV_GET_CLASS(mpv)->initialize(mpv);
}
void
celluloid_mpv_init_gl(CelluloidMpv *mpv)
{
CelluloidMpvPrivate *priv = get_private(mpv);
mpv_opengl_init_params init_params =
{.get_proc_address = get_proc_address};
mpv_render_param params[] =
{ {MPV_RENDER_PARAM_API_TYPE, MPV_RENDER_API_TYPE_OPENGL},
{MPV_RENDER_PARAM_OPENGL_INIT_PARAMS, &init_params},
{MPV_RENDER_PARAM_WL_DISPLAY, get_wl_display()},
{MPV_RENDER_PARAM_X11_DISPLAY, get_x11_display()},
{0, NULL} };
gint rc = mpv_render_context_create( &priv->render_ctx,
priv->mpv_ctx,
params );
if(rc >= 0)
{
g_debug("Initialized render context");
}
else
{
g_critical("Failed to initialize render context");
}
}
void
celluloid_mpv_reset(CelluloidMpv *mpv)
{
CELLULOID_MPV_GET_CLASS(mpv)->reset(mpv);
}
void
celluloid_mpv_quit(CelluloidMpv *mpv)
{
CelluloidMpvPrivate *priv = get_private(mpv);
g_info("Terminating mpv");
celluloid_mpv_command_string(mpv, "quit");
if(priv->render_ctx)
{
g_debug("Uninitializing render context");
mpv_render_context_free(priv->render_ctx);
priv->render_ctx = NULL;
}
g_assert(priv->mpv_ctx);
mpv_terminate_destroy(priv->mpv_ctx);
priv->mpv_ctx = NULL;
}
void
celluloid_mpv_load_track(CelluloidMpv *mpv, const gchar *uri, TrackType type)
{
const gchar *cmd[3] = {NULL};
gchar *path = g_filename_from_uri(uri, NULL, NULL);
switch(type)
{
case TRACK_TYPE_AUDIO:
cmd[0] = "audio-add";
break;
case TRACK_TYPE_VIDEO:
cmd[0] = "video-add";
break;
case TRACK_TYPE_SUBTITLE:
cmd[0] = "sub-add";
break;
default:
g_assert_not_reached();
break;
}
cmd[1] = path?:uri;
g_debug("Loading external track %s with type %d", cmd[1], type);
celluloid_mpv_command(mpv, cmd);
g_free(path);
}
void
celluloid_mpv_load_file(CelluloidMpv *mpv, const gchar *uri, gboolean append)
{
CELLULOID_MPV_GET_CLASS(mpv)->load_file(mpv, uri, append);
}
void
celluloid_mpv_load(CelluloidMpv *mpv, const gchar *uri, gboolean append)
{
const gchar *subtitle_exts[] = SUBTITLE_EXTS;
if(extension_matches(uri, subtitle_exts))
{
celluloid_mpv_load_track(mpv, uri, TRACK_TYPE_SUBTITLE);
}
else
{
celluloid_mpv_load_file(mpv, uri, append);
}
}
gint
celluloid_mpv_command(CelluloidMpv *mpv, const gchar **cmd)
{
CelluloidMpvPrivate *priv = get_private(mpv);
gint rc = MPV_ERROR_UNINITIALIZED;
if(priv->mpv_ctx)
{
rc = mpv_command(priv->mpv_ctx, cmd);
}
if(rc < 0)
{
gchar *cmd_str = g_strjoinv(" ", (gchar **)cmd);
g_warning( "Failed to run mpv command \"%s\". Reason: %s.",
cmd_str,
mpv_error_string(rc) );
g_free(cmd_str);
}
return rc;
}
gint
celluloid_mpv_command_async(CelluloidMpv *mpv, const gchar **cmd)
{
CelluloidMpvPrivate *priv = get_private(mpv);
gint rc = MPV_ERROR_UNINITIALIZED;
if(priv->mpv_ctx)
{
rc = mpv_command_async(priv->mpv_ctx, 0, cmd);
}
if(rc < 0)
{
gchar *cmd_str = g_strjoinv(" ", (gchar **)cmd);
g_warning( "Failed to dispatch async mpv command \"%s\". "
"Reason: %s.",
cmd_str,
mpv_error_string(rc) );
g_free(cmd_str);
}
return rc;
}
gint
celluloid_mpv_command_string(CelluloidMpv *mpv, const gchar *cmd)
{
CelluloidMpvPrivate *priv = get_private(mpv);
gint rc = MPV_ERROR_UNINITIALIZED;
if(priv->mpv_ctx)
{
rc = mpv_command_string(priv->mpv_ctx, cmd);
}
if(rc < 0)
{
g_warning( "Failed to run mpv command string \"%s\". "
"Reason: %s.",
cmd,
mpv_error_string(rc) );
}
return rc;
}
gint
celluloid_mpv_set_option_string( CelluloidMpv *mpv,
const gchar *name,
const gchar *value )
{
return mpv_set_option_string(get_private(mpv)->mpv_ctx, name, value);
}
gint
celluloid_mpv_get_property( CelluloidMpv *mpv,
const gchar *name,
mpv_format format,
void *data )
{
CelluloidMpvPrivate *priv = get_private(mpv);
gint rc = MPV_ERROR_UNINITIALIZED;
if(priv->mpv_ctx)
{
rc = mpv_get_property(priv->mpv_ctx, name, format, data);
}
if(rc < 0)
{
g_info( "Failed to retrieve property \"%s\" "
"using mpv format %d. Reason: %s.",
name,
format,
mpv_error_string(rc) );
}
return rc;
}
gchar *
celluloid_mpv_get_property_string(CelluloidMpv *mpv, const gchar *name)
{
CelluloidMpvPrivate *priv = get_private(mpv);
gchar *value = NULL;
if(priv->mpv_ctx)
{
value = mpv_get_property_string(priv->mpv_ctx, name);
}
if(!value)
{
g_info("Failed to retrieve property \"%s\" as string.", name);
}
return value;
}
gboolean
celluloid_mpv_get_property_flag(CelluloidMpv *mpv, const gchar *name)
{
CelluloidMpvPrivate *priv = get_private(mpv);
gboolean value = FALSE;
gint rc = MPV_ERROR_UNINITIALIZED;
if(priv->mpv_ctx)
{
rc = mpv_get_property
(priv->mpv_ctx, name, MPV_FORMAT_FLAG, &value);
}
if(rc < 0)
{
g_info( "Failed to retrieve property \"%s\" as flag. "
"Reason: %s.",
name,
mpv_error_string(rc) );
}
return value;
}
gint
celluloid_mpv_set_property( CelluloidMpv *mpv,
const gchar *name,
mpv_format format,
void *data )
{
CelluloidMpvPrivate *priv = get_private(mpv);
gint rc = MPV_ERROR_UNINITIALIZED;
if(priv->mpv_ctx)
{
rc = mpv_set_property(priv->mpv_ctx, name, format, data);
}
if(rc < 0)
{
g_info( "Failed to set property \"%s\" using mpv format %d. "
"Reason: %s.",
name,
format,
mpv_error_string(rc) );
}
return rc;
}
gint
celluloid_mpv_set_property_string( CelluloidMpv *mpv,
const gchar *name,
const char *data )
{
CelluloidMpvPrivate *priv = get_private(mpv);
gint rc = MPV_ERROR_UNINITIALIZED;
if(priv->mpv_ctx)
{
rc = mpv_set_property_string(priv->mpv_ctx, name, data);
}
if(rc < 0)
{
g_info( "Failed to set property \"%s\" as string. Reason: %s.",
name,
mpv_error_string(rc) );
}
return rc;
}
gint
celluloid_mpv_set_property_flag( CelluloidMpv *mpv,
const gchar *name,
gboolean value )
{
CelluloidMpvPrivate *priv = get_private(mpv);
gint rc = MPV_ERROR_UNINITIALIZED;
if(priv->mpv_ctx)
{
rc = mpv_set_property
(priv->mpv_ctx, name, MPV_FORMAT_FLAG, &value);
}
if(rc < 0)
{
g_info( "Failed to set property \"%s\" as flag. Reason: %s.",
name,
mpv_error_string(rc) );
}
return rc;
}
void
celluloid_mpv_set_render_update_callback( CelluloidMpv *mpv,
mpv_render_update_fn func,
void *data )
{
CelluloidMpvPrivate *priv = get_private(mpv);
priv->render_update_callback = func;
priv->render_update_callback_data = data;
if(priv->render_ctx)
{
mpv_render_context_set_update_callback
(priv->render_ctx, func, data);
}
}
guint64
celluloid_mpv_render_context_update(CelluloidMpv *mpv)
{
return mpv_render_context_update(get_private(mpv)->render_ctx);
}
gint
celluloid_mpv_load_config_file(CelluloidMpv *mpv, const gchar *filename)
{
return mpv_load_config_file(get_private(mpv)->mpv_ctx, filename);
}
gint
celluloid_mpv_observe_property( CelluloidMpv *mpv,
guint64 reply_userdata,
const gchar *name,
mpv_format format )
{
return mpv_observe_property( get_private(mpv)->mpv_ctx,
reply_userdata,
name,
format );
}
gint
celluloid_mpv_request_log_messages(CelluloidMpv *mpv, const gchar *min_level)
{
return mpv_request_log_messages(get_private(mpv)->mpv_ctx, min_level);
}