clipboard: add clipboard API

This adds a clipboard API with multiple backend and format support.
--clipboard-enable option can be toggled at runtime to turn native
clipboard on and off.
This commit is contained in:
nanahi
2024-11-07 23:33:36 -05:00
committed by Kacper Michajłow
parent af82f7cf29
commit e1d30c4c5a
11 changed files with 306 additions and 2 deletions

View File

@@ -0,0 +1,44 @@
/*
* This file is part of mpv.
*
* mpv is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* mpv 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with mpv. If not, see <http://www.gnu.org/licenses/>.
*/
#include "common/common.h"
#include "clipboard.h"
static int init(struct clipboard_ctx *cl, struct clipboard_init_params *params)
{
return CLIPBOARD_FAILED;
}
static int get_data(struct clipboard_ctx *cl, struct clipboard_access_params *params,
struct clipboard_data *out, void *talloc_ctx)
{
return CLIPBOARD_FAILED;
}
static int set_data(struct clipboard_ctx *cl, struct clipboard_access_params *params,
struct clipboard_data *data)
{
return CLIPBOARD_FAILED;
}
const struct clipboard_backend clipboard_backend_vo = {
.name = "vo",
.desc = "VO clipboard",
.init = init,
.get_data = get_data,
.set_data = set_data,
};

View File

@@ -0,0 +1,45 @@
/*
* This file is part of mpv.
*
* mpv is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* mpv 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with mpv. If not, see <http://www.gnu.org/licenses/>.
*/
#include <windows.h>
#include "common/common.h"
#include "clipboard.h"
static int init(struct clipboard_ctx *cl, struct clipboard_init_params *params)
{
return CLIPBOARD_FAILED;
}
static int get_data(struct clipboard_ctx *cl, struct clipboard_access_params *params,
struct clipboard_data *out, void *talloc_ctx)
{
return CLIPBOARD_FAILED;
}
static int set_data(struct clipboard_ctx *cl, struct clipboard_access_params *params,
struct clipboard_data *data)
{
return CLIPBOARD_FAILED;
}
const struct clipboard_backend clipboard_backend_win32 = {
.name = "win32",
.desc = "Windows clipboard",
.init = init,
.get_data = get_data,
.set_data = set_data,
};

View File

@@ -0,0 +1,108 @@
/*
* This file is part of mpv.
*
* mpv is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* mpv 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with mpv. If not, see <http://www.gnu.org/licenses/>.
*/
#include "common/common.h"
#include "options/m_config.h"
#include "player/core.h"
#include "clipboard.h"
struct clipboard_opts {
bool enabled;
};
#define OPT_BASE_STRUCT struct clipboard_opts
const struct m_sub_options clipboard_conf = {
.opts = (const struct m_option[]) {
{"enable", OPT_BOOL(enabled), .flags = UPDATE_CLIPBOARD},
{0}
},
.defaults = &(const struct clipboard_opts) {
.enabled = true,
},
.size = sizeof(struct clipboard_opts)
};
// backend list
extern const struct clipboard_backend clipboard_backend_win32;
extern const struct clipboard_backend clipboard_backend_vo;
static const struct clipboard_backend *const clipboard_backend_list[] = {
#if HAVE_WIN32_DESKTOP
&clipboard_backend_win32,
#endif
&clipboard_backend_vo,
};
struct clipboard_ctx *mp_clipboard_create(struct clipboard_init_params *params,
struct mpv_global *global)
{
struct clipboard_ctx *cl = talloc_ptrtype(NULL, cl);
*cl = (struct clipboard_ctx) {
.log = mp_log_new(cl, global->log, "clipboard"),
.global = global,
};
for (int i = 0; i < MP_ARRAY_SIZE(clipboard_backend_list); i++) {
const struct clipboard_backend *backend = clipboard_backend_list[i];
if (backend->init(cl, params) == CLIPBOARD_SUCCESS) {
MP_VERBOSE(cl, "Initialized %s clipboard backend.\n", backend->name);
cl->backend = backend;
goto success;
}
}
MP_WARN(cl, "Failed to initialize any clipboard backend.\n");
talloc_free(cl);
return NULL;
success:
return cl;
}
void mp_clipboard_destroy(struct clipboard_ctx *cl)
{
if (cl && cl->backend->uninit)
cl->backend->uninit(cl);
talloc_free(cl);
}
int mp_clipboard_get_data(struct clipboard_ctx *cl, struct clipboard_access_params *params,
struct clipboard_data *out, void *talloc_ctx)
{
if (cl && cl->backend->get_data)
return cl->backend->get_data(cl, params, out, talloc_ctx);
return CLIPBOARD_FAILED;
}
int mp_clipboard_set_data(struct clipboard_ctx *cl, struct clipboard_access_params *params,
struct clipboard_data *data)
{
if (cl && cl->backend->set_data)
return cl->backend->set_data(cl, params, data);
return CLIPBOARD_FAILED;
}
void reinit_clipboard(struct MPContext *mpctx)
{
mp_clipboard_destroy(mpctx->clipboard);
mpctx->clipboard = NULL;
struct clipboard_opts *opts = mp_get_config_group(NULL, mpctx->global, &clipboard_conf);
if (opts->enabled) {
mpctx->clipboard = mp_clipboard_create(&(struct clipboard_init_params){0}, mpctx->global);
}
talloc_free(opts);
}

View File

@@ -0,0 +1,88 @@
/*
* This file is part of mpv.
*
* mpv is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* mpv 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with mpv. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "common/common.h"
#include "common/global.h"
#include "video/mp_image.h"
struct clipboard_ctx;
struct MPContext;
enum clipboard_data_type {
CLIPBOARD_DATA_TEXT,
CLIPBOARD_DATA_IMAGE,
};
enum clipboard_target {
CLIPBOARD_TARGET_CLIPBOARD,
CLIPBOARD_TARGET_PRIMARY_SELECTION,
};
enum clipboard_result {
CLIPBOARD_SUCCESS = 0,
CLIPBOARD_FAILED = -1,
};
struct clipboard_data {
enum clipboard_data_type type;
union {
char *text;
struct mp_image *image;
} u;
};
struct clipboard_init_params {
int flags;
};
struct clipboard_access_params {
int flags;
enum clipboard_data_type type;
enum clipboard_target target;
};
struct clipboard_backend {
const char *name;
const char *desc;
// Return 0 on success, otherwise -1
int (*init)(struct clipboard_ctx *cl, struct clipboard_init_params *params);
void (*uninit)(struct clipboard_ctx *cl);
int (*get_data)(struct clipboard_ctx *cl, struct clipboard_access_params *params,
struct clipboard_data *out, void *talloc_ctx);
int (*set_data)(struct clipboard_ctx *cl, struct clipboard_access_params *params,
struct clipboard_data *data);
};
struct clipboard_ctx {
const struct clipboard_backend *backend; // clipboard description structure
struct mp_log *log;
void *priv; // backend-specific internal data
struct mpv_global *global;
};
struct clipboard_ctx *mp_clipboard_create(struct clipboard_init_params *params,
struct mpv_global *global);
void mp_clipboard_destroy(struct clipboard_ctx *cl);
int mp_clipboard_get_data(struct clipboard_ctx *cl, struct clipboard_access_params *params,
struct clipboard_data *out, void *talloc_ctx);
int mp_clipboard_set_data(struct clipboard_ctx *cl, struct clipboard_access_params *params,
struct clipboard_data *data);
void reinit_clipboard(struct MPContext *mpctx);

View File

@@ -32,6 +32,7 @@
#include "mpv_talloc.h"
#include "client.h"
#include "clipboard/clipboard.h"
#include "external_files.h"
#include "common/av_common.h"
#include "common/codecs.h"
@@ -7520,6 +7521,9 @@ void mp_option_change_callback(void *ctx, struct m_config_option *co, int flags,
if (flags & UPDATE_INPUT)
mp_input_update_opts(mpctx->input);
if (flags & UPDATE_CLIPBOARD)
reinit_clipboard(mpctx);
if (flags & UPDATE_SUB_EXTS)
mp_update_subtitle_exts(mpctx->opts);

View File

@@ -24,6 +24,7 @@
#include "libmpv/client.h"
#include "audio/aframe.h"
#include "clipboard/clipboard.h"
#include "common/common.h"
#include "filters/f_output_chain.h"
#include "filters/filter.h"
@@ -286,6 +287,8 @@ typedef struct MPContext {
bool playback_initialized; // playloop can be run/is running
int error_playing;
struct clipboard_ctx *clipboard;
// Return code to use with PT_QUIT
int quit_custom_rc;
bool has_quit_custom_rc;

View File

@@ -197,6 +197,7 @@ void mp_destroy(struct MPContext *mpctx)
}
mp_input_uninit(mpctx->input);
mp_clipboard_destroy(mpctx->clipboard);
uninit_libav(mpctx->global);