summaryrefslogtreecommitdiffstats
path: root/player/client.c
diff options
context:
space:
mode:
Diffstat (limited to 'player/client.c')
-rw-r--r--player/client.c433
1 files changed, 157 insertions, 276 deletions
diff --git a/player/client.c b/player/client.c
index 0babacf147..5087f89885 100644
--- a/player/client.c
+++ b/player/client.c
@@ -13,14 +13,15 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <math.h>
+#include <stdatomic.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <math.h>
-#include <assert.h>
#include "common/common.h"
#include "common/global.h"
@@ -39,7 +40,6 @@
#include "options/m_property.h"
#include "options/path.h"
#include "options/parse_configfile.h"
-#include "osdep/atomic.h"
#include "osdep/threads.h"
#include "osdep/timer.h"
#include "osdep/io.h"
@@ -64,7 +64,7 @@
struct mp_client_api {
struct MPContext *mpctx;
- pthread_mutex_t lock;
+ mp_mutex lock;
// -- protected by lock
@@ -83,7 +83,6 @@ struct mp_client_api {
int num_custom_protocols;
struct mpv_render_context *render_context;
- struct mpv_opengl_cb_context *gl_cb_ctx;
};
struct observe_property {
@@ -107,7 +106,7 @@ struct observe_property {
};
struct mpv_handle {
- // -- immmutable
+ // -- immutable
char name[MAX_CLIENT_NAME];
struct mp_log *log;
struct MPContext *mpctx;
@@ -119,10 +118,10 @@ struct mpv_handle {
struct mpv_event_property cur_property_event;
struct observe_property *cur_property;
- pthread_mutex_t lock;
+ mp_mutex lock;
- pthread_mutex_t wakeup_lock;
- pthread_cond_t wakeup;
+ mp_mutex wakeup_lock;
+ mp_cond wakeup;
// -- protected by wakeup_lock
bool need_wakeup;
@@ -186,7 +185,7 @@ void mp_clients_init(struct MPContext *mpctx)
.mpctx = mpctx,
};
mpctx->global->client_api = mpctx->clients;
- pthread_mutex_init(&mpctx->clients->lock, NULL);
+ mp_mutex_init(&mpctx->clients->lock);
}
void mp_clients_destroy(struct MPContext *mpctx)
@@ -195,8 +194,6 @@ void mp_clients_destroy(struct MPContext *mpctx)
return;
assert(mpctx->clients->num_clients == 0);
- TA_FREEP(&mpctx->clients->gl_cb_ctx);
-
// The API user is supposed to call mpv_render_context_free(). It's simply
// not allowed not to do this.
if (mpctx->clients->render_context) {
@@ -204,7 +201,7 @@ void mp_clients_destroy(struct MPContext *mpctx)
abort();
}
- pthread_mutex_destroy(&mpctx->clients->lock);
+ mp_mutex_destroy(&mpctx->clients->lock);
talloc_free(mpctx->clients);
mpctx->clients = NULL;
}
@@ -214,14 +211,14 @@ void mp_clients_destroy(struct MPContext *mpctx)
bool mp_clients_all_initialized(struct MPContext *mpctx)
{
bool all_ok = true;
- pthread_mutex_lock(&mpctx->clients->lock);
+ mp_mutex_lock(&mpctx->clients->lock);
for (int n = 0; n < mpctx->clients->num_clients; n++) {
struct mpv_handle *ctx = mpctx->clients->clients[n];
- pthread_mutex_lock(&ctx->lock);
+ mp_mutex_lock(&ctx->lock);
all_ok &= ctx->fuzzy_initialized;
- pthread_mutex_unlock(&ctx->lock);
+ mp_mutex_unlock(&ctx->lock);
}
- pthread_mutex_unlock(&mpctx->clients->lock);
+ mp_mutex_unlock(&mpctx->clients->lock);
return all_ok;
}
@@ -256,15 +253,15 @@ static struct mpv_handle *find_client(struct mp_client_api *clients,
bool mp_client_id_exists(struct MPContext *mpctx, int64_t id)
{
- pthread_mutex_lock(&mpctx->clients->lock);
+ mp_mutex_lock(&mpctx->clients->lock);
bool r = find_client_id(mpctx->clients, id);
- pthread_mutex_unlock(&mpctx->clients->lock);
+ mp_mutex_unlock(&mpctx->clients->lock);
return r;
}
struct mpv_handle *mp_new_client(struct mp_client_api *clients, const char *name)
{
- pthread_mutex_lock(&clients->lock);
+ mp_mutex_lock(&clients->lock);
char nname[MAX_CLIENT_NAME];
for (int n = 1; n < 1000; n++) {
@@ -281,7 +278,7 @@ struct mpv_handle *mp_new_client(struct mp_client_api *clients, const char *name
}
if (!nname[0] || clients->shutting_down) {
- pthread_mutex_unlock(&clients->lock);
+ mp_mutex_unlock(&clients->lock);
return NULL;
}
@@ -299,9 +296,9 @@ struct mpv_handle *mp_new_client(struct mp_client_api *clients, const char *name
.event_mask = (1ULL << INTERNAL_EVENT_BASE) - 1, // exclude internal events
.wakeup_pipe = {-1, -1},
};
- pthread_mutex_init(&client->lock, NULL);
- pthread_mutex_init(&client->wakeup_lock, NULL);
- pthread_cond_init(&client->wakeup, NULL);
+ mp_mutex_init(&client->lock);
+ mp_mutex_init(&client->wakeup_lock);
+ mp_cond_init(&client->wakeup);
snprintf(client->name, sizeof(client->name), "%s", nname);
@@ -311,7 +308,7 @@ struct mpv_handle *mp_new_client(struct mp_client_api *clients, const char *name
if (clients->num_clients == 1 && !clients->mpctx->is_cli)
client->fuzzy_initialized = true;
- pthread_mutex_unlock(&clients->lock);
+ mp_mutex_unlock(&clients->lock);
mpv_request_event(client, MPV_EVENT_TICK, 0);
@@ -320,9 +317,9 @@ struct mpv_handle *mp_new_client(struct mp_client_api *clients, const char *name
void mp_client_set_weak(struct mpv_handle *ctx)
{
- pthread_mutex_lock(&ctx->lock);
+ mp_mutex_lock(&ctx->lock);
ctx->is_weak = true;
- pthread_mutex_unlock(&ctx->lock);
+ mp_mutex_unlock(&ctx->lock);
}
const char *mpv_client_name(mpv_handle *ctx)
@@ -347,52 +344,41 @@ struct mpv_global *mp_client_get_global(struct mpv_handle *ctx)
static void wakeup_client(struct mpv_handle *ctx)
{
- pthread_mutex_lock(&ctx->wakeup_lock);
+ mp_mutex_lock(&ctx->wakeup_lock);
if (!ctx->need_wakeup) {
ctx->need_wakeup = true;
- pthread_cond_broadcast(&ctx->wakeup);
+ mp_cond_broadcast(&ctx->wakeup);
if (ctx->wakeup_cb)
ctx->wakeup_cb(ctx->wakeup_cb_ctx);
if (ctx->wakeup_pipe[0] != -1)
(void)write(ctx->wakeup_pipe[1], &(char){0}, 1);
}
- pthread_mutex_unlock(&ctx->wakeup_lock);
+ mp_mutex_unlock(&ctx->wakeup_lock);
}
// Note: the caller has to deal with sporadic wakeups.
static int wait_wakeup(struct mpv_handle *ctx, int64_t end)
{
int r = 0;
- pthread_mutex_unlock(&ctx->lock);
- pthread_mutex_lock(&ctx->wakeup_lock);
- if (!ctx->need_wakeup) {
- struct timespec ts = mp_time_us_to_timespec(end);
- r = pthread_cond_timedwait(&ctx->wakeup, &ctx->wakeup_lock, &ts);
- }
+ mp_mutex_unlock(&ctx->lock);
+ mp_mutex_lock(&ctx->wakeup_lock);
+ if (!ctx->need_wakeup)
+ r = mp_cond_timedwait_until(&ctx->wakeup, &ctx->wakeup_lock, end);
if (r == 0)
ctx->need_wakeup = false;
- pthread_mutex_unlock(&ctx->wakeup_lock);
- pthread_mutex_lock(&ctx->lock);
+ mp_mutex_unlock(&ctx->wakeup_lock);
+ mp_mutex_lock(&ctx->lock);
return r;
}
void mpv_set_wakeup_callback(mpv_handle *ctx, void (*cb)(void *d), void *d)
{
- pthread_mutex_lock(&ctx->wakeup_lock);
+ mp_mutex_lock(&ctx->wakeup_lock);
ctx->wakeup_cb = cb;
ctx->wakeup_cb_ctx = d;
if (ctx->wakeup_cb)
ctx->wakeup_cb(ctx->wakeup_cb_ctx);
- pthread_mutex_unlock(&ctx->wakeup_lock);
-}
-
-void mpv_suspend(mpv_handle *ctx)
-{
- MP_ERR(ctx, "mpv_suspend() is deprecated and does nothing.\n");
-}
-
-void mpv_resume(mpv_handle *ctx)
-{
+ mp_mutex_unlock(&ctx->wakeup_lock);
}
static void lock_core(mpv_handle *ctx)
@@ -407,10 +393,10 @@ static void unlock_core(mpv_handle *ctx)
void mpv_wait_async_requests(mpv_handle *ctx)
{
- pthread_mutex_lock(&ctx->lock);
+ mp_mutex_lock(&ctx->lock);
while (ctx->reserved_events || ctx->async_counter)
wait_wakeup(ctx, INT64_MAX);
- pthread_mutex_unlock(&ctx->lock);
+ mp_mutex_unlock(&ctx->lock);
}
// Send abort signal to all matching work items.
@@ -419,7 +405,7 @@ void mpv_wait_async_requests(mpv_handle *ctx)
static void abort_async(struct MPContext *mpctx, mpv_handle *ctx,
int type, uint64_t id)
{
- pthread_mutex_lock(&mpctx->abort_lock);
+ mp_mutex_lock(&mpctx->abort_lock);
// Destroy all => ensure any newly appearing work is aborted immediately.
if (ctx == NULL)
@@ -434,12 +420,12 @@ static void abort_async(struct MPContext *mpctx, mpv_handle *ctx,
}
}
- pthread_mutex_unlock(&mpctx->abort_lock);
+ mp_mutex_unlock(&mpctx->abort_lock);
}
-static void get_thread(void *ptr)
+static void get_thread_id(void *ptr)
{
- *(pthread_t *)ptr = pthread_self();
+ *(mp_thread_id *)ptr = mp_thread_current_id();
}
static void mp_destroy_client(mpv_handle *ctx, bool terminate)
@@ -455,7 +441,7 @@ static void mp_destroy_client(mpv_handle *ctx, bool terminate)
if (terminate)
mpv_command(ctx, (const char*[]){"quit", NULL});
- pthread_mutex_lock(&ctx->lock);
+ mp_mutex_lock(&ctx->lock);
ctx->destroying = true;
@@ -467,7 +453,7 @@ static void mp_destroy_client(mpv_handle *ctx, bool terminate)
prop_unref(ctx->cur_property);
ctx->cur_property = NULL;
- pthread_mutex_unlock(&ctx->lock);
+ mp_mutex_unlock(&ctx->lock);
abort_async(mpctx, ctx, 0, 0);
@@ -479,7 +465,7 @@ static void mp_destroy_client(mpv_handle *ctx, bool terminate)
osd_set_external_remove_owner(mpctx->osd, ctx);
mp_input_remove_sections_by_owner(mpctx->input, ctx->name);
- pthread_mutex_lock(&clients->lock);
+ mp_mutex_lock(&clients->lock);
for (int n = 0; n < clients->num_clients; n++) {
if (clients->clients[n] == ctx) {
@@ -491,9 +477,9 @@ static void mp_destroy_client(mpv_handle *ctx, bool terminate)
ctx->num_events--;
}
mp_msg_log_buffer_destroy(ctx->messages);
- pthread_cond_destroy(&ctx->wakeup);
- pthread_mutex_destroy(&ctx->wakeup_lock);
- pthread_mutex_destroy(&ctx->lock);
+ mp_cond_destroy(&ctx->wakeup);
+ mp_mutex_destroy(&ctx->wakeup_lock);
+ mp_mutex_destroy(&ctx->lock);
if (ctx->wakeup_pipe[0] != -1) {
close(ctx->wakeup_pipe[0]);
close(ctx->wakeup_pipe[1]);
@@ -525,7 +511,7 @@ static void mp_destroy_client(mpv_handle *ctx, bool terminate)
// mp_hook_test_completion() also relies on this a bit.
mp_wakeup_core(mpctx);
- pthread_mutex_unlock(&clients->lock);
+ mp_mutex_unlock(&clients->lock);
// Note that even if num_clients==0, having set have_terminator keeps mpctx
// and the core thread alive.
@@ -536,17 +522,17 @@ static void mp_destroy_client(mpv_handle *ctx, bool terminate)
mpctx->stop_play = PT_QUIT;
mp_dispatch_unlock(mpctx->dispatch);
- pthread_t playthread;
- mp_dispatch_run(mpctx->dispatch, get_thread, &playthread);
+ mp_thread_id playthread;
+ mp_dispatch_run(mpctx->dispatch, get_thread_id, &playthread);
// Ask the core thread to stop.
- pthread_mutex_lock(&clients->lock);
+ mp_mutex_lock(&clients->lock);
clients->terminate_core_thread = true;
- pthread_mutex_unlock(&clients->lock);
+ mp_mutex_unlock(&clients->lock);
mp_wakeup_core(mpctx);
// Blocking wait for all clients and core thread to terminate.
- pthread_join(playthread, NULL);
+ mp_thread_join_id(playthread);
mp_destroy(mpctx);
}
@@ -557,11 +543,6 @@ void mpv_destroy(mpv_handle *ctx)
mp_destroy_client(ctx, false);
}
-void mpv_detach_destroy(mpv_handle *ctx)
-{
- mpv_destroy(ctx);
-}
-
void mpv_terminate_destroy(mpv_handle *ctx)
{
mp_destroy_client(ctx, true);
@@ -576,7 +557,7 @@ void mp_shutdown_clients(struct MPContext *mpctx)
// Forcefully abort async work after 2 seconds of waiting.
double abort_time = mp_time_sec() + 2;
- pthread_mutex_lock(&clients->lock);
+ mp_mutex_lock(&clients->lock);
// Prevent that new clients can appear.
clients->shutting_down = true;
@@ -585,7 +566,7 @@ void mp_shutdown_clients(struct MPContext *mpctx)
while (clients->num_clients || mpctx->outstanding_async ||
!(mpctx->is_cli || clients->terminate_core_thread))
{
- pthread_mutex_unlock(&clients->lock);
+ mp_mutex_unlock(&clients->lock);
double left = abort_time - mp_time_sec();
if (left >= 0) {
@@ -600,26 +581,26 @@ void mp_shutdown_clients(struct MPContext *mpctx)
mp_client_broadcast_event(mpctx, MPV_EVENT_SHUTDOWN, NULL);
mp_wait_events(mpctx);
- pthread_mutex_lock(&clients->lock);
+ mp_mutex_lock(&clients->lock);
}
- pthread_mutex_unlock(&clients->lock);
+ mp_mutex_unlock(&clients->lock);
}
bool mp_is_shutting_down(struct MPContext *mpctx)
{
struct mp_client_api *clients = mpctx->clients;
- pthread_mutex_lock(&clients->lock);
+ mp_mutex_lock(&clients->lock);
bool res = clients->shutting_down;
- pthread_mutex_unlock(&clients->lock);
+ mp_mutex_unlock(&clients->lock);
return res;
}
-static void *core_thread(void *p)
+static MP_THREAD_VOID core_thread(void *p)
{
struct MPContext *mpctx = p;
- mpthread_set_name("mpv core");
+ mp_thread_set_name("core");
while (!mpctx->initialized && mpctx->stop_play != PT_QUIT)
mp_idle(mpctx);
@@ -632,7 +613,7 @@ static void *core_thread(void *p)
// the last mpv_handle.
mp_shutdown_clients(mpctx);
- return NULL;
+ MP_THREAD_RETURN();
}
mpv_handle *mpv_create(void)
@@ -649,8 +630,8 @@ mpv_handle *mpv_create(void)
return NULL;
}
- pthread_t thread;
- if (pthread_create(&thread, NULL, core_thread, mpctx) != 0) {
+ mp_thread thread;
+ if (mp_thread_create(&thread, core_thread, mpctx) != 0) {
ctx->clients->have_terminator = true; // avoid blocking
mpv_terminate_destroy(ctx);
mp_destroy(mpctx);
@@ -723,13 +704,13 @@ static void dup_event_data(struct mpv_event *ev)
static int reserve_reply(struct mpv_handle *ctx)
{
int res = MPV_ERROR_EVENT_QUEUE_FULL;
- pthread_mutex_lock(&ctx->lock);
+ mp_mutex_lock(&ctx->lock);
if (ctx->reserved_events + ctx->num_events < ctx->max_events && !ctx->choked)
{
ctx->reserved_events++;
res = 0;
}
- pthread_mutex_unlock(&ctx->lock);
+ mp_mutex_unlock(&ctx->lock);
return res;
}
@@ -749,7 +730,7 @@ static int append_event(struct mpv_handle *ctx, struct mpv_event event, bool cop
static int send_event(struct mpv_handle *ctx, struct mpv_event *event, bool copy)
{
- pthread_mutex_lock(&ctx->lock);
+ mp_mutex_lock(&ctx->lock);
uint64_t mask = 1ULL << event->event_id;
if (ctx->property_event_masks & mask)
notify_property_events(ctx, event->event_id);
@@ -765,7 +746,7 @@ static int send_event(struct mpv_handle *ctx, struct mpv_event *event, bool copy
ctx->choked = true;
}
}
- pthread_mutex_unlock(&ctx->lock);
+ mp_mutex_unlock(&ctx->lock);
return r;
}
@@ -775,20 +756,20 @@ static void send_reply(struct mpv_handle *ctx, uint64_t userdata,
struct mpv_event *event)
{
event->reply_userdata = userdata;
- pthread_mutex_lock(&ctx->lock);
+ mp_mutex_lock(&ctx->lock);
// If this fails, reserve_reply() probably wasn't called.
assert(ctx->reserved_events > 0);
ctx->reserved_events--;
if (append_event(ctx, *event, false) < 0)
- abort(); // not reached
- pthread_mutex_unlock(&ctx->lock);
+ MP_ASSERT_UNREACHABLE();
+ mp_mutex_unlock(&ctx->lock);
}
void mp_client_broadcast_event(struct MPContext *mpctx, int event, void *data)
{
struct mp_client_api *clients = mpctx->clients;
- pthread_mutex_lock(&clients->lock);
+ mp_mutex_lock(&clients->lock);
for (int n = 0; n < clients->num_clients; n++) {
struct mpv_event event_data = {
@@ -798,7 +779,7 @@ void mp_client_broadcast_event(struct MPContext *mpctx, int event, void *data)
send_event(clients->clients[n], &event_data, true);
}
- pthread_mutex_unlock(&clients->lock);
+ mp_mutex_unlock(&clients->lock);
}
// Like mp_client_broadcast_event(), but can be called from any thread.
@@ -831,7 +812,7 @@ int mp_client_send_event(struct MPContext *mpctx, const char *client_name,
.reply_userdata = reply_userdata,
};
- pthread_mutex_lock(&clients->lock);
+ mp_mutex_lock(&clients->lock);
struct mpv_handle *ctx = find_client(clients, client_name);
if (ctx) {
@@ -841,7 +822,7 @@ int mp_client_send_event(struct MPContext *mpctx, const char *client_name,
talloc_free(data);
}
- pthread_mutex_unlock(&clients->lock);
+ mp_mutex_unlock(&clients->lock);
return r;
}
@@ -863,16 +844,9 @@ int mp_client_send_event_dup(struct MPContext *mpctx, const char *client_name,
return mp_client_send_event(mpctx, client_name, 0, event, event_data.data);
}
-static bool deprecated_events[] = {
- [MPV_EVENT_TRACKS_CHANGED] = true,
- [MPV_EVENT_TRACK_SWITCHED] = true,
+static const bool deprecated_events[] = {
[MPV_EVENT_IDLE] = true,
- [MPV_EVENT_PAUSE] = true,
- [MPV_EVENT_UNPAUSE] = true,
[MPV_EVENT_TICK] = true,
- [MPV_EVENT_SCRIPT_INPUT_DISPATCH] = true,
- [MPV_EVENT_METADATA_UPDATE] = true,
- [MPV_EVENT_CHAPTER_CHANGE] = true,
};
int mpv_request_event(mpv_handle *ctx, mpv_event_id event, int enable)
@@ -882,7 +856,7 @@ int mpv_request_event(mpv_handle *ctx, mpv_event_id event, int enable)
if (event == MPV_EVENT_SHUTDOWN && !enable)
return MPV_ERROR_INVALID_PARAMETER;
assert(event < (int)INTERNAL_EVENT_BASE); // excluded above; they have no name
- pthread_mutex_lock(&ctx->lock);
+ mp_mutex_lock(&ctx->lock);
uint64_t bit = 1ULL << event;
ctx->event_mask = enable ? ctx->event_mask | bit : ctx->event_mask & ~bit;
if (enable && event < MP_ARRAY_SIZE(deprecated_events) &&
@@ -891,7 +865,7 @@ int mpv_request_event(mpv_handle *ctx, mpv_event_id event, int enable)
MP_WARN(ctx, "The '%s' event is deprecated and will be removed.\n",
mpv_event_name(event));
}
- pthread_mutex_unlock(&ctx->lock);
+ mp_mutex_unlock(&ctx->lock);
return 0;
}
@@ -920,7 +894,7 @@ mpv_event *mpv_wait_event(mpv_handle *ctx, double timeout)
{
mpv_event *event = ctx->cur_event;
- pthread_mutex_lock(&ctx->lock);
+ mp_mutex_lock(&ctx->lock);
if (!ctx->fuzzy_initialized)
mp_wakeup_core(ctx->clients->mpctx);
@@ -929,7 +903,7 @@ mpv_event *mpv_wait_event(mpv_handle *ctx, double timeout)
if (timeout < 0)
timeout = 1e20;
- int64_t deadline = mp_add_timeout(mp_time_us(), timeout);
+ int64_t deadline = mp_time_ns_add(mp_time_ns(), timeout);
*event = (mpv_event){0};
talloc_free_children(event);
@@ -978,17 +952,17 @@ mpv_event *mpv_wait_event(mpv_handle *ctx, double timeout)
}
ctx->queued_wakeup = false;
- pthread_mutex_unlock(&ctx->lock);
+ mp_mutex_unlock(&ctx->lock);
return event;
}
void mpv_wakeup(mpv_handle *ctx)
{
- pthread_mutex_lock(&ctx->lock);
+ mp_mutex_lock(&ctx->lock);
ctx->queued_wakeup = true;
wakeup_client(ctx);
- pthread_mutex_unlock(&ctx->lock);
+ mp_mutex_unlock(&ctx->lock);
}
// map client API types to internal types
@@ -1361,6 +1335,12 @@ int mpv_set_property(mpv_handle *ctx, const char *name, mpv_format format,
return req.status;
}
+int mpv_del_property(mpv_handle *ctx, const char *name)
+{
+ const char* args[] = { "del", name, NULL };
+ return mpv_command(ctx, args);
+}
+
int mpv_set_property_string(mpv_handle *ctx, const char *name, const char *data)
{
return mpv_set_property(ctx, name, MPV_FORMAT_STRING, &data);
@@ -1420,7 +1400,7 @@ static void getproperty_fn(void *arg)
struct getproperty_request *req = arg;
const struct m_option *type = get_mp_type_get(req->format);
- union m_option_value xdata = {0};
+ union m_option_value xdata = m_option_value_default;
void *data = req->data ? req->data : &xdata;
int err = -1;
@@ -1564,7 +1544,7 @@ int mpv_observe_property(mpv_handle *ctx, uint64_t userdata,
if (format == MPV_FORMAT_OSD_STRING)
return MPV_ERROR_PROPERTY_FORMAT;
- pthread_mutex_lock(&ctx->lock);
+ mp_mutex_lock(&ctx->lock);
assert(!ctx->destroying);
struct observe_property *prop = talloc_ptrtype(ctx, prop);
talloc_set_destructor(prop, property_free);
@@ -1578,6 +1558,8 @@ int mpv_observe_property(mpv_handle *ctx, uint64_t userdata,
.type = type,
.change_ts = 1, // force initial event
.refcount = 1,
+ .value = m_option_value_default,
+ .value_ret = m_option_value_default,
};
ctx->properties_change_ts += 1;
MP_TARRAY_APPEND(ctx, ctx->properties, ctx->num_properties, prop);
@@ -1585,14 +1567,14 @@ int mpv_observe_property(mpv_handle *ctx, uint64_t userdata,
ctx->new_property_events = true;
ctx->cur_property_index = 0;
ctx->has_pending_properties = true;
- pthread_mutex_unlock(&ctx->lock);
+ mp_mutex_unlock(&ctx->lock);
mp_wakeup_core(ctx->mpctx);
return 0;
}
int mpv_unobserve_property(mpv_handle *ctx, uint64_t userdata)
{
- pthread_mutex_lock(&ctx->lock);
+ mp_mutex_lock(&ctx->lock);
int count = 0;
for (int n = ctx->num_properties - 1; n >= 0; n--) {
struct observe_property *prop = ctx->properties[n];
@@ -1606,10 +1588,34 @@ int mpv_unobserve_property(mpv_handle *ctx, uint64_t userdata)
count++;
}
}
- pthread_mutex_unlock(&ctx->lock);
+ mp_mutex_unlock(&ctx->lock);
return count;
}
+static bool property_shared_prefix(const char *a0, const char *b0)
+{
+ bstr a = bstr0(a0);
+ bstr b = bstr0(b0);
+
+ // Treat options and properties as equivalent.
+ bstr_eatstart0(&a, "options/");
+ bstr_eatstart0(&b, "options/");
+
+ // Compare the potentially-common portion
+ if (memcmp(a.start, b.start, MPMIN(a.len, b.len)))
+ return false;
+
+ // If lengths were equal, we're done
+ if (a.len == b.len)
+ return true;
+
+ // Check for a slash in the first non-common byte of the longer string
+ if (a.len > b.len)
+ return a.start[b.len] == '/';
+ else
+ return b.start[a.len] == '/';
+}
+
// Broadcast that a property has changed.
void mp_client_property_change(struct MPContext *mpctx, const char *name)
{
@@ -1617,22 +1623,23 @@ void mp_client_property_change(struct MPContext *mpctx, const char *name)
int id = mp_get_property_id(mpctx, name);
bool any_pending = false;
- pthread_mutex_lock(&clients->lock);
+ mp_mutex_lock(&clients->lock);
for (int n = 0; n < clients->num_clients; n++) {
struct mpv_handle *client = clients->clients[n];
- pthread_mutex_lock(&client->lock);
+ mp_mutex_lock(&client->lock);
for (int i = 0; i < client->num_properties; i++) {
- if (client->properties[i]->id == id) {
+ if (client->properties[i]->id == id &&
+ property_shared_prefix(name, client->properties[i]->name)) {
client->properties[i]->change_ts += 1;
client->has_pending_properties = true;
any_pending = true;
}
}
- pthread_mutex_unlock(&client->lock);
+ mp_mutex_unlock(&client->lock);
}
- pthread_mutex_unlock(&clients->lock);
+ mp_mutex_unlock(&clients->lock);
// If we're inside mp_dispatch_queue_process(), this will cause the playloop
// to be re-run (to get mp_client_send_property_changes() called). If we're
@@ -1675,7 +1682,7 @@ static void send_client_property_changes(struct mpv_handle *ctx)
bool changed = false;
if (prop->format) {
const struct m_option *type = prop->type;
- union m_option_value val = {0};
+ union m_option_value val = m_option_value_default;
struct getproperty_request req = {
.mpctx = ctx->mpctx,
.name = prop->name,
@@ -1689,9 +1696,9 @@ static void send_client_property_changes(struct mpv_handle *ctx)
// or similar things are involved).
prop->refcount += 1; // keep prop alive (esp. prop->name)
ctx->async_counter += 1; // keep ctx alive
- pthread_mutex_unlock(&ctx->lock);
+ mp_mutex_unlock(&ctx->lock);
getproperty_fn(&req);
- pthread_mutex_lock(&ctx->lock);
+ mp_mutex_lock(&ctx->lock);
ctx->async_counter -= 1;
prop_unref(prop);
@@ -1748,22 +1755,22 @@ void mp_client_send_property_changes(struct MPContext *mpctx)
{
struct mp_client_api *clients = mpctx->clients;
- pthread_mutex_lock(&clients->lock);
+ mp_mutex_lock(&clients->lock);
uint64_t cur_ts = clients->clients_list_change_ts;
for (int n = 0; n < clients->num_clients; n++) {
struct mpv_handle *ctx = clients->clients[n];
- pthread_mutex_lock(&ctx->lock);
+ mp_mutex_lock(&ctx->lock);
if (!ctx->has_pending_properties || ctx->destroying) {
- pthread_mutex_unlock(&ctx->lock);
+ mp_mutex_unlock(&ctx->lock);
continue;
}
// Keep ctx->lock locked (unlock order does not matter).
- pthread_mutex_unlock(&clients->lock);
+ mp_mutex_unlock(&clients->lock);
send_client_property_changes(ctx);
- pthread_mutex_unlock(&ctx->lock);
- pthread_mutex_lock(&clients->lock);
+ mp_mutex_unlock(&ctx->lock);
+ mp_mutex_lock(&clients->lock);
if (cur_ts != clients->clients_list_change_ts) {
// List changed; need to start over. Do it in the next iteration.
mp_wakeup_core(mpctx);
@@ -1771,7 +1778,7 @@ void mp_client_send_property_changes(struct MPContext *mpctx)
}
}
- pthread_mutex_unlock(&clients->lock);
+ mp_mutex_unlock(&clients->lock);
}
// Set ctx->cur_event to a generated property change event, if there is any
@@ -1841,7 +1848,7 @@ int mpv_hook_continue(mpv_handle *ctx, uint64_t id)
int mpv_load_config_file(mpv_handle *ctx, const char *filename)
{
lock_core(ctx);
- int r = m_config_parse_config_file(ctx->mpctx->mconfig, filename, NULL, 0);
+ int r = m_config_parse_config_file(ctx->mpctx->mconfig, ctx->mpctx->global, filename, NULL, 0);
unlock_core(ctx);
if (r == 0)
return MPV_ERROR_INVALID_PARAMETER;
@@ -1878,7 +1885,7 @@ int mpv_request_log_messages(mpv_handle *ctx, const char *min_level)
if (level < 0 && strcmp(min_level, "no") != 0)
return MPV_ERROR_INVALID_PARAMETER;
- pthread_mutex_lock(&ctx->lock);
+ mp_mutex_lock(&ctx->lock);
if (level < 0 || level != ctx->messages_level) {
mp_msg_log_buffer_destroy(ctx->messages);
ctx->messages = NULL;
@@ -1893,7 +1900,7 @@ int mpv_request_log_messages(mpv_handle *ctx, const char *min_level)
mp_msg_log_buffer_set_silent(ctx->messages, silent);
}
wakeup_client(ctx);
- pthread_mutex_unlock(&ctx->lock);
+ mp_mutex_unlock(&ctx->lock);
return 0;
}
@@ -1925,13 +1932,13 @@ static bool gen_log_message_event(struct mpv_handle *ctx)
int mpv_get_wakeup_pipe(mpv_handle *ctx)
{
- pthread_mutex_lock(&ctx->wakeup_lock);
+ mp_mutex_lock(&ctx->wakeup_lock);
if (ctx->wakeup_pipe[0] == -1) {
if (mp_make_wakeup_pipe(ctx->wakeup_pipe) >= 0)
(void)write(ctx->wakeup_pipe[1], &(char){0}, 1);
}
int fd = ctx->wakeup_pipe[0];
- pthread_mutex_unlock(&ctx->wakeup_lock);
+ mp_mutex_unlock(&ctx->wakeup_lock);
return fd;
}
@@ -2098,21 +2105,14 @@ static const char *const event_table[] = {
[MPV_EVENT_START_FILE] = "start-file",
[MPV_EVENT_END_FILE] = "end-file",
[MPV_EVENT_FILE_LOADED] = "file-loaded",
- [MPV_EVENT_TRACKS_CHANGED] = "tracks-changed",
- [MPV_EVENT_TRACK_SWITCHED] = "track-switched",
[MPV_EVENT_IDLE] = "idle",
- [MPV_EVENT_PAUSE] = "pause",
- [MPV_EVENT_UNPAUSE] = "unpause",
[MPV_EVENT_TICK] = "tick",
- [MPV_EVENT_SCRIPT_INPUT_DISPATCH] = "script-input-dispatch",
[MPV_EVENT_CLIENT_MESSAGE] = "client-message",
[MPV_EVENT_VIDEO_RECONFIG] = "video-reconfig",
[MPV_EVENT_AUDIO_RECONFIG] = "audio-reconfig",
- [MPV_EVENT_METADATA_UPDATE] = "metadata-update",
[MPV_EVENT_SEEK] = "seek",
[MPV_EVENT_PLAYBACK_RESTART] = "playback-restart",
[MPV_EVENT_PROPERTY_CHANGE] = "property-change",
- [MPV_EVENT_CHAPTER_CHANGE] = "chapter-change",
[MPV_EVENT_QUEUE_OVERFLOW] = "event-queue-overflow",
[MPV_EVENT_HOOK] = "hook",
};
@@ -2129,9 +2129,14 @@ void mpv_free(void *data)
talloc_free(data);
}
+int64_t mpv_get_time_ns(mpv_handle *ctx)
+{
+ return mp_time_ns();
+}
+
int64_t mpv_get_time_us(mpv_handle *ctx)
{
- return mp_time_us();
+ return mp_time_ns() / 1000;
}
#include "video/out/libmpv.h"
@@ -2161,14 +2166,14 @@ bool mp_set_main_render_context(struct mp_client_api *client_api,
{
assert(ctx);
- pthread_mutex_lock(&client_api->lock);
+ mp_mutex_lock(&client_api->lock);
bool is_set = !!client_api->render_context;
bool is_same = client_api->render_context == ctx;
// Can set if it doesn't remove another existing ctx.
bool res = is_same || !is_set;
if (res)
client_api->render_context = active ? ctx : NULL;
- pthread_mutex_unlock(&client_api->lock);
+ mp_mutex_unlock(&client_api->lock);
return res;
}
@@ -2177,134 +2182,10 @@ struct mpv_render_context *
mp_client_api_acquire_render_context(struct mp_client_api *ca)
{
struct mpv_render_context *res = NULL;
- pthread_mutex_lock(&ca->lock);
+ mp_mutex_lock(&ca->lock);
if (ca->render_context && mp_render_context_acquire(ca->render_context))
res = ca->render_context;
- pthread_mutex_unlock(&ca->lock);
- return res;
-}
-
-// Emulation of old opengl_cb API.
-
-#include "libmpv/opengl_cb.h"
-#include "libmpv/render_gl.h"
-
-struct mpv_opengl_cb_context {
- struct mp_client_api *client_api;
- mpv_opengl_cb_update_fn callback;
- void *callback_ctx;
-};
-
-static mpv_opengl_cb_context *opengl_cb_get_context(mpv_handle *ctx)
-{
- pthread_mutex_lock(&ctx->clients->lock);
- mpv_opengl_cb_context *cb = ctx->clients->gl_cb_ctx;
- if (!cb) {
- cb = talloc_zero(NULL, struct mpv_opengl_cb_context);
- cb->client_api = ctx->clients;
- cb->client_api->gl_cb_ctx = cb;
- }
- pthread_mutex_unlock(&ctx->clients->lock);
- return cb;
-}
-
-void mpv_opengl_cb_set_update_callback(mpv_opengl_cb_context *ctx,
- mpv_opengl_cb_update_fn callback,
- void *callback_ctx)
-{
- // This was probably supposed to be thread-safe, but we don't care. It's
- // compatibility code, and if you have problems, use the new API.
- if (ctx->client_api->render_context) {
- mpv_render_context_set_update_callback(ctx->client_api->render_context,
- callback, callback_ctx);
- }
- // Nasty thing: could set this even while not initialized, so we need to
- // preserve it.
- ctx->callback = callback;
- ctx->callback_ctx = callback_ctx;
-}
-
-int mpv_opengl_cb_init_gl(mpv_opengl_cb_context *ctx, const char *exts,
- mpv_opengl_cb_get_proc_address_fn get_proc_address,
- void *get_proc_address_ctx)
-{
- if (ctx->client_api->render_context)
- return MPV_ERROR_INVALID_PARAMETER;
-
- // mpv_render_context_create() only calls mp_client_get_global() on it.
- mpv_handle dummy = {.mpctx = ctx->client_api->mpctx};
-
- mpv_render_param params[] = {
- {MPV_RENDER_PARAM_API_TYPE, MPV_RENDER_API_TYPE_OPENGL},
- {MPV_RENDER_PARAM_OPENGL_INIT_PARAMS, &(mpv_opengl_init_params){
- .get_proc_address = get_proc_address,
- .get_proc_address_ctx = get_proc_address_ctx,
- .extra_exts = exts,
- }},
- // Hack for explicit legacy hwdec loading. We really want to make it
- // impossible for proper render API users to trigger this.
- {(mpv_render_param_type)-1, ctx->client_api->mpctx->global},
- {0}
- };
- int err = mpv_render_context_create(&ctx->client_api->render_context,
- &dummy, params);
- if (err >= 0) {
- mpv_render_context_set_update_callback(ctx->client_api->render_context,
- ctx->callback, ctx->callback_ctx);
- }
- return err;
-}
-
-int mpv_opengl_cb_draw(mpv_opengl_cb_context *ctx, int fbo, int w, int h)
-{
- if (!ctx->client_api->render_context)
- return MPV_ERROR_INVALID_PARAMETER;
-
- mpv_render_param params[] = {
- {MPV_RENDER_PARAM_OPENGL_FBO, &(mpv_opengl_fbo){
- .fbo = fbo,
- .w = w,
- .h = abs(h),
- }},
- {MPV_RENDER_PARAM_FLIP_Y, &(int){h < 0}},
- {0}
- };
- return mpv_render_context_render(ctx->client_api->render_context, params);
-}
-
-int mpv_opengl_cb_report_flip(mpv_opengl_cb_context *ctx, int64_t time)
-{
- if (!ctx->client_api->render_context)
- return MPV_ERROR_INVALID_PARAMETER;
-
- mpv_render_context_report_swap(ctx->client_api->render_context);
- return 0;
-}
-
-int mpv_opengl_cb_uninit_gl(mpv_opengl_cb_context *ctx)
-{
- if (ctx->client_api->render_context)
- mpv_render_context_free(ctx->client_api->render_context);
- ctx->client_api->render_context = NULL;
- return 0;
-}
-
-int mpv_opengl_cb_render(mpv_opengl_cb_context *ctx, int fbo, int vp[4])
-{
- return mpv_opengl_cb_draw(ctx, fbo, vp[2], vp[3]);
-}
-
-void *mpv_get_sub_api(mpv_handle *ctx, mpv_sub_api sub_api)
-{
- if (!ctx->mpctx->initialized)
- return NULL;
- void *res = NULL;
- switch (sub_api) {
- case MPV_SUB_API_OPENGL_CB:
- res = opengl_cb_get_context(ctx);
- break;
- default:;
- }