mirror of
https://github.com/mpv-player/mpv
synced 2024-09-09 01:16:56 +02:00
client API: add mpv_get_wakeup_pipe convenience function
Should make integreating with some event loops easier. Untested.
This commit is contained in:
parent
33f822b715
commit
4e5cea86c2
@ -1010,7 +1010,7 @@ typedef struct mpv_event_end_file {
|
||||
* 3: the player received the quit command
|
||||
* Other values should be treated as unknown.
|
||||
*/
|
||||
int reason;
|
||||
int reason;
|
||||
} mpv_event_end_file;
|
||||
|
||||
typedef struct mpv_event_script_input_dispatch {
|
||||
@ -1158,9 +1158,40 @@ void mpv_wakeup(mpv_handle *ctx);
|
||||
* If you actually want to do processing in a callback, spawn a thread that
|
||||
* does nothing but call mpv_wait_event() in a loop and dispatches the result
|
||||
* to a callback.
|
||||
*
|
||||
* Only one wakeup callback can be set.
|
||||
*
|
||||
* @param cb function that should be called if a wakeup is required
|
||||
* @param d arbitrary userdata passed to cb
|
||||
*/
|
||||
void mpv_set_wakeup_callback(mpv_handle *ctx, void (*cb)(void *d), void *d);
|
||||
|
||||
/**
|
||||
* Return a UNIX file descriptor referring to the read end of a pipe. This
|
||||
* pipe can be used to wake up a poll() based processing loop. The purpose of
|
||||
* this function is very similar to mpv_set_wakeup_callback(), and provides
|
||||
* a primitive mechanism to handle coordinating a foreign event loop and the
|
||||
* libmpv event loop.
|
||||
*
|
||||
* This is in fact implemented using mpv_set_wakeup_callback(), and each
|
||||
* callback invocation writes a single 0 byte to the pipe. When the pipe
|
||||
* becomes readable, the code calling poll() (or select()) on the pipe should
|
||||
* read all contents of the pipe and then call mpv_wait_event(c, 0) until
|
||||
* no new events are returned. The pipe contents do not matter and can just
|
||||
* be discarded.
|
||||
*
|
||||
* Note that this call lazily creates the pipe, and always returns the same
|
||||
* handle once it's created. The client API will destroy both the read and
|
||||
* write ends of the pipe in mpv_destroy(). If you need something more
|
||||
* complex, it's better to implement your own mechanisms using
|
||||
* mpv_set_wakeup_callback().
|
||||
*
|
||||
* On Windows, this will always return -1.
|
||||
*
|
||||
* @return A UNIX FD of the read end of the wakeup pipe, -1 on error.
|
||||
*/
|
||||
int mpv_get_wakeup_pipe(mpv_handle *ctx);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -29,7 +29,7 @@
|
||||
// On error, false is returned (and errno set).
|
||||
bool mp_set_cloexec(int fd)
|
||||
{
|
||||
#if defined(FD_CLOEXEC) && defined(F_SETFD)
|
||||
#if defined(F_SETFD)
|
||||
if (fd >= 0) {
|
||||
int flags = fcntl(fd, F_GETFD);
|
||||
if (flags == -1)
|
||||
|
@ -34,6 +34,9 @@
|
||||
#ifndef O_CLOEXEC
|
||||
#define O_CLOEXEC 0
|
||||
#endif
|
||||
#ifndef FD_CLOEXEC
|
||||
#define FD_CLOEXEC 0
|
||||
#endif
|
||||
|
||||
bool mp_set_cloexec(int fd);
|
||||
|
||||
|
@ -14,6 +14,8 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
|
||||
@ -26,11 +28,14 @@
|
||||
#include "options/m_property.h"
|
||||
#include "osdep/threads.h"
|
||||
#include "osdep/timer.h"
|
||||
#include "osdep/io.h"
|
||||
|
||||
#include "command.h"
|
||||
#include "core.h"
|
||||
#include "client.h"
|
||||
|
||||
#include "config.h"
|
||||
|
||||
/*
|
||||
* Locking hierarchy:
|
||||
*
|
||||
@ -88,6 +93,7 @@ struct mpv_handle {
|
||||
bool choke_warning;
|
||||
void (*wakeup_cb)(void *d);
|
||||
void *wakeup_cb_ctx;
|
||||
int wakeup_pipe[2];
|
||||
|
||||
mpv_event *events; // ringbuffer of max_events entries
|
||||
int max_events; // allocated number of entries in events
|
||||
@ -176,6 +182,7 @@ struct mpv_handle *mp_new_client(struct mp_client_api *clients, const char *name
|
||||
.events = talloc_array(client, mpv_event, num_events),
|
||||
.max_events = num_events,
|
||||
.event_mask = ((uint64_t)-1) & ~(1ULL << MPV_EVENT_TICK),
|
||||
.wakeup_pipe = {-1, -1},
|
||||
};
|
||||
pthread_mutex_init(&client->lock, NULL);
|
||||
pthread_cond_init(&client->wakeup, NULL);
|
||||
@ -202,6 +209,8 @@ static void wakeup_client(struct mpv_handle *ctx)
|
||||
pthread_cond_signal(&ctx->wakeup);
|
||||
if (ctx->wakeup_cb)
|
||||
ctx->wakeup_cb(ctx->wakeup_cb_ctx);
|
||||
if (ctx->wakeup_pipe[0] == -1)
|
||||
write(ctx->wakeup_pipe[0], &(char){0}, 1);
|
||||
}
|
||||
|
||||
void mpv_set_wakeup_callback(mpv_handle *ctx, void (*cb)(void *d), void *d)
|
||||
@ -250,6 +259,10 @@ void mpv_destroy(mpv_handle *ctx)
|
||||
mp_msg_log_buffer_destroy(ctx->messages);
|
||||
pthread_cond_destroy(&ctx->wakeup);
|
||||
pthread_mutex_destroy(&ctx->lock);
|
||||
if (ctx->wakeup_pipe[0] != -1) {
|
||||
close(ctx->wakeup_pipe[0]);
|
||||
close(ctx->wakeup_pipe[1]);
|
||||
}
|
||||
talloc_free(ctx);
|
||||
ctx = NULL;
|
||||
// shutdown_clients() sleeps to avoid wasting CPU
|
||||
@ -1233,6 +1246,25 @@ int mpv_request_log_messages(mpv_handle *ctx, const char *min_level)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mpv_get_wakeup_pipe(mpv_handle *ctx)
|
||||
{
|
||||
pthread_mutex_lock(&ctx->lock);
|
||||
#if defined(F_SETFL)
|
||||
if (ctx->wakeup_pipe[0] == -1) {
|
||||
if (pipe(ctx->wakeup_pipe) != 0)
|
||||
goto fail;
|
||||
for (int i = 0; i < 2; i++) {
|
||||
mp_set_cloexec(ctx->wakeup_pipe[i]);
|
||||
int ret = fcntl(ctx->wakeup_pipe[i], F_GETFL);
|
||||
fcntl(ctx->wakeup_pipe[i], F_SETFL, ret | O_NONBLOCK);
|
||||
}
|
||||
}
|
||||
fail:
|
||||
#endif
|
||||
pthread_mutex_unlock(&ctx->lock);
|
||||
return ctx->wakeup_pipe[1];
|
||||
}
|
||||
|
||||
unsigned long mpv_client_api_version(void)
|
||||
{
|
||||
return MPV_CLIENT_API_VERSION;
|
||||
|
Loading…
Reference in New Issue
Block a user