summaryrefslogtreecommitdiffstats
path: root/player
diff options
context:
space:
mode:
Diffstat (limited to 'player')
-rw-r--r--player/audio.c87
-rw-r--r--player/client.c355
-rw-r--r--player/command.c1726
-rw-r--r--player/command.h7
-rw-r--r--player/configfiles.c266
-rw-r--r--player/core.h81
-rw-r--r--player/external_files.c109
-rw-r--r--player/external_files.h2
-rw-r--r--player/javascript.c165
-rw-r--r--player/javascript/defaults.js120
-rw-r--r--player/javascript/meson.build6
-rw-r--r--player/loadfile.c430
-rw-r--r--player/lua.c180
-rw-r--r--player/lua/auto_profiles.lua67
-rw-r--r--player/lua/console.lua1043
-rw-r--r--player/lua/defaults.lua86
-rw-r--r--player/lua/input.lua69
-rw-r--r--player/lua/meson.build11
-rw-r--r--player/lua/options.lua17
-rw-r--r--player/lua/osc.lua536
-rw-r--r--player/lua/stats.lua1003
-rw-r--r--player/lua/ytdl_hook.lua456
-rw-r--r--player/main.c77
-rw-r--r--player/meson.build11
-rw-r--r--player/misc.c27
-rw-r--r--player/osd.c17
-rw-r--r--player/playloop.c102
-rw-r--r--player/screenshot.c135
-rw-r--r--player/scripting.c112
-rw-r--r--player/sub.c86
-rw-r--r--player/video.c170
31 files changed, 5372 insertions, 2187 deletions
diff --git a/player/audio.c b/player/audio.c
index 50c0faaf09..da91dd4340 100644
--- a/player/audio.c
+++ b/player/audio.c
@@ -22,7 +22,6 @@
#include <math.h>
#include <assert.h>
-#include "config.h"
#include "mpv_talloc.h"
#include "common/msg.h"
@@ -64,9 +63,17 @@ static void update_speed_filters(struct MPContext *mpctx)
speed = 1.0;
}
- if (mpctx->display_sync_active && mpctx->opts->video_sync == VS_DISP_ADROP) {
- drop *= speed * resample;
- resample = speed = 1.0;
+ if (mpctx->display_sync_active) {
+ switch (mpctx->video_out->opts->video_sync) {
+ case VS_DISP_ADROP:
+ drop *= speed * resample;
+ resample = speed = 1.0;
+ break;
+ case VS_DISP_TEMPO:
+ speed = mpctx->audio_speed;
+ resample = 1.0;
+ break;
+ }
}
mp_output_chain_set_audio_speed(ao_c->filter, speed, resample, drop);
@@ -168,6 +175,7 @@ void audio_update_volume(struct MPContext *mpctx)
float gain = MPMAX(opts->softvol_volume / 100.0, 0);
gain = pow(gain, 3);
gain *= compute_replaygain(mpctx);
+ gain *= db_gain(opts->softvol_gain);
if (opts->softvol_mute == 1)
gain = 0.0;
@@ -183,11 +191,24 @@ void update_playback_speed(struct MPContext *mpctx)
update_speed_filters(mpctx);
}
+static bool has_video_track(struct MPContext *mpctx)
+{
+ if (mpctx->vo_chain && mpctx->vo_chain->is_coverart)
+ return false;
+
+ for (int n = 0; n < mpctx->num_tracks; n++) {
+ struct track *track = mpctx->tracks[n];
+ if (track->type == STREAM_VIDEO && !track->attached_picture && !track->image)
+ return true;
+ }
+
+ return false;
+}
+
static void ao_chain_reset_state(struct ao_chain *ao_c)
{
ao_c->last_out_pts = MP_NOPTS_VALUE;
ao_c->out_eof = false;
- ao_c->underrun = false;
ao_c->start_pts_known = false;
ao_c->start_pts = MP_NOPTS_VALUE;
ao_c->untimed_throttle = false;
@@ -281,8 +302,7 @@ static bool keep_weak_gapless_format(struct mp_aframe *old, struct mp_aframe* ne
{
bool res = false;
struct mp_aframe *new_mod = mp_aframe_new_ref(new);
- if (!new_mod)
- abort();
+ MP_HANDLE_OOM(new_mod);
// If the sample formats are compatible (== libswresample generally can
// convert them), keep the AO. On other changes, recreate it.
@@ -314,6 +334,7 @@ static void ao_chain_set_ao(struct ao_chain *ao_c, struct ao *ao)
mp_async_queue_set_notifier(ao_c->queue_filter, ao_c->ao_filter);
// Make sure filtering never stops with frames stuck in access filter.
mp_filter_set_high_priority(ao_c->queue_filter, true);
+ audio_update_volume(ao_c->mpctx);
}
if (ao_c->filter->ao_needs_update)
@@ -322,7 +343,7 @@ static void ao_chain_set_ao(struct ao_chain *ao_c, struct ao *ao)
mp_filter_wakeup(ao_c->ao_filter);
}
-static void reinit_audio_filters_and_output(struct MPContext *mpctx)
+static int reinit_audio_filters_and_output(struct MPContext *mpctx)
{
struct MPOpts *opts = mpctx->opts;
struct ao_chain *ao_c = mpctx->ao_chain;
@@ -333,8 +354,7 @@ static void reinit_audio_filters_and_output(struct MPContext *mpctx)
// The "ideal" filter output format
struct mp_aframe *out_fmt = mp_aframe_new_ref(ao_c->filter->output_aformat);
- if (!out_fmt)
- abort();
+ MP_HANDLE_OOM(out_fmt);
if (!mp_aframe_config_is_valid(out_fmt)) {
talloc_free(out_fmt);
@@ -359,13 +379,13 @@ static void reinit_audio_filters_and_output(struct MPContext *mpctx)
{
ao_chain_set_ao(ao_c, mpctx->ao);
talloc_free(out_fmt);
- return;
+ return 0;
}
// Wait until all played.
if (mpctx->ao && ao_is_playing(mpctx->ao)) {
talloc_free(out_fmt);
- return;
+ return 0;
}
// Format change during syncing. Force playback start early, then wait.
if (ao_c->ao_queue && mp_async_queue_get_frames(ao_c->ao_queue) &&
@@ -374,11 +394,11 @@ static void reinit_audio_filters_and_output(struct MPContext *mpctx)
mpctx->audio_status = STATUS_READY;
mp_wakeup_core(mpctx);
talloc_free(out_fmt);
- return;
+ return 0;
}
if (mpctx->audio_status == STATUS_READY) {
talloc_free(out_fmt);
- return;
+ return 0;
}
uninit_audio_out(mpctx);
@@ -411,6 +431,9 @@ static void reinit_audio_filters_and_output(struct MPContext *mpctx)
opts->audio_output_channels.num_chmaps);
}
+ if (!has_video_track(mpctx))
+ ao_flags |= AO_INIT_MEDIA_ROLE_MUSIC;
+
mpctx->ao_filter_fmt = out_fmt;
mpctx->ao = ao_init_best(mpctx->global, ao_flags, mp_wakeup_core_cb,
@@ -446,7 +469,7 @@ static void reinit_audio_filters_and_output(struct MPContext *mpctx)
reset_audio_state(mpctx);
mp_output_chain_reset_harder(ao_c->filter);
mp_wakeup_core(mpctx); // reinit with new format next time
- return;
+ return 0;
}
MP_ERR(mpctx, "Could not open/initialize audio device -> no sound.\n");
@@ -464,7 +487,8 @@ static void reinit_audio_filters_and_output(struct MPContext *mpctx)
ao_c->ao_resume_time =
opts->audio_wait_open > 0 ? mp_time_sec() + opts->audio_wait_open : 0;
- ao_set_paused(mpctx->ao, get_internal_paused(mpctx));
+ bool eof = mpctx->audio_status == STATUS_EOF;
+ ao_set_paused(mpctx->ao, get_internal_paused(mpctx), eof);
ao_chain_set_ao(ao_c, mpctx->ao);
@@ -477,12 +501,13 @@ static void reinit_audio_filters_and_output(struct MPContext *mpctx)
mp_wakeup_core(mpctx);
mp_notify(mpctx, MPV_EVENT_AUDIO_RECONFIG, NULL);
- return;
+ return 0;
init_error:
uninit_audio_chain(mpctx);
uninit_audio_out(mpctx);
error_on_track(mpctx, track);
+ return -1;
}
int init_audio_decoder(struct MPContext *mpctx, struct track *track)
@@ -516,7 +541,8 @@ void reinit_audio_chain(struct MPContext *mpctx)
struct track *track = NULL;
track = mpctx->current_track[0][STREAM_AUDIO];
if (!track || !track->stream) {
- uninit_audio_out(mpctx);
+ if (!mpctx->encode_lavc_ctx)
+ uninit_audio_out(mpctx);
error_on_track(mpctx, track);
return;
}
@@ -592,7 +618,7 @@ double playing_audio_pts(struct MPContext *mpctx)
double pts = written_audio_pts(mpctx);
if (pts == MP_NOPTS_VALUE || !mpctx->ao)
return pts;
- return pts - mpctx->audio_speed * ao_get_delay(mpctx->ao);
+ return pts - ao_get_delay(mpctx->ao);
}
// This garbage is needed for untimed AOs. These consume audio infinitely fast,
@@ -634,7 +660,7 @@ static void ao_process(struct mp_filter *f)
return;
}
- // Due to mp_async_queue_set_notifier() thhis function is called when the
+ // Due to mp_async_queue_set_notifier() this function is called when the
// queue becomes full. This affects state changes in the normal playloop,
// so wake it up. But avoid redundant wakeups during normal playback.
if (mpctx->audio_status != STATUS_PLAYING &&
@@ -698,7 +724,8 @@ static void ao_process(struct mp_filter *f)
mpctx->shown_aframes += samples;
double real_samplerate = mp_aframe_get_rate(af) / mpctx->audio_speed;
- mpctx->delay += samples / real_samplerate;
+ if (mpctx->video_status != STATUS_EOF)
+ mpctx->delay += samples / real_samplerate;
ao_c->last_out_pts = mp_aframe_end_pts(af);
update_throttle(mpctx);
@@ -802,7 +829,8 @@ void audio_start_ao(struct MPContext *mpctx)
double pts = MP_NOPTS_VALUE;
if (!get_sync_pts(mpctx, &pts))
return;
- double apts = playing_audio_pts(mpctx); // (basically including mpctx->delay)
+ double apts = written_audio_pts(mpctx);
+ apts -= apts != MP_NOPTS_VALUE ? mpctx->audio_speed * ao_get_delay(mpctx->ao) : 0;
if (pts != MP_NOPTS_VALUE && apts != MP_NOPTS_VALUE && pts < apts &&
mpctx->video_status != STATUS_EOF)
{
@@ -818,10 +846,13 @@ void audio_start_ao(struct MPContext *mpctx)
}
MP_VERBOSE(mpctx, "starting audio playback\n");
+ ao_c->audio_started = true;
ao_start(ao_c->ao);
mpctx->audio_status = STATUS_PLAYING;
- if (ao_c->out_eof)
+ if (ao_c->out_eof) {
mpctx->audio_status = STATUS_DRAINING;
+ MP_VERBOSE(mpctx, "audio draining\n");
+ }
ao_c->underrun = false;
mpctx->logged_async_diff = -1;
mp_wakeup_core(mpctx);
@@ -849,8 +880,10 @@ void fill_audio_out_buffers(struct MPContext *mpctx)
return;
}
- if (ao_c->filter->ao_needs_update)
- reinit_audio_filters_and_output(mpctx);
+ if (ao_c->filter->ao_needs_update) {
+ if (reinit_audio_filters_and_output(mpctx) < 0)
+ return;
+ }
if (mpctx->vo_chain && ao_c->track && ao_c->track->dec &&
mp_decoder_wrapper_get_pts_reset(ao_c->track->dec))
@@ -870,8 +903,10 @@ void fill_audio_out_buffers(struct MPContext *mpctx)
// until the old audio is fully played.
// (Buggy if AO underruns.)
if (mpctx->ao && ao_is_playing(mpctx->ao) &&
- mpctx->video_status != STATUS_EOF)
+ mpctx->video_status != STATUS_EOF) {
+ MP_VERBOSE(mpctx, "blocked, waiting for old audio to play\n");
ok = false;
+ }
if (ao_c->start_pts_known != ok || ao_c->start_pts != pts) {
ao_c->start_pts_known = ok;
diff --git a/player/client.c b/player/client.c
index 27f42afd74..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
@@ -106,7 +106,7 @@ struct observe_property {
};
struct mpv_handle {
- // -- immmutable
+ // -- immutable
char name[MAX_CLIENT_NAME];
struct mp_log *log;
struct MPContext *mpctx;
@@ -118,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;
@@ -185,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)
@@ -201,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;
}
@@ -211,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;
}
@@ -253,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++) {
@@ -278,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;
}
@@ -296,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);
@@ -308,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);
@@ -317,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)
@@ -344,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)
@@ -404,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.
@@ -416,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)
@@ -431,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)
@@ -452,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;
@@ -464,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);
@@ -476,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) {
@@ -488,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]);
@@ -522,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.
@@ -533,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);
}
@@ -554,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);
@@ -573,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;
@@ -582,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) {
@@ -597,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);
@@ -629,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)
@@ -646,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);
@@ -720,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;
}
@@ -746,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);
@@ -762,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;
}
@@ -772,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 = {
@@ -795,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.
@@ -828,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) {
@@ -838,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;
}
@@ -860,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)
@@ -879,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) &&
@@ -888,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