summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--input/input.c10
-rw-r--r--input/input.h3
-rw-r--r--player/client.c2
-rw-r--r--player/core.h6
-rw-r--r--player/loadfile.c27
-rw-r--r--player/main.c8
-rw-r--r--player/misc.c2
7 files changed, 47 insertions, 11 deletions
diff --git a/input/input.c b/input/input.c
index 9525dbcbb1..f0f9f64e9b 100644
--- a/input/input.c
+++ b/input/input.c
@@ -144,7 +144,8 @@ struct input_ctx {
struct cmd_queue cmd_queue;
- struct mp_cancel *cancel;
+ void (*cancel)(void *cancel_ctx);
+ void *cancel_ctx;
void (*wakeup_cb)(void *ctx);
void *wakeup_ctx;
@@ -809,7 +810,7 @@ int mp_input_queue_cmd(struct input_ctx *ictx, mp_cmd_t *cmd)
input_lock(ictx);
if (cmd) {
if (ictx->cancel && test_abort_cmd(ictx, cmd))
- mp_cancel_trigger(ictx->cancel);
+ ictx->cancel(ictx->cancel_ctx);
queue_add_tail(&ictx->cmd_queue, cmd);
mp_input_wakeup(ictx);
}
@@ -1335,10 +1336,11 @@ void mp_input_uninit(struct input_ctx *ictx)
talloc_free(ictx);
}
-void mp_input_set_cancel(struct input_ctx *ictx, struct mp_cancel *cancel)
+void mp_input_set_cancel(struct input_ctx *ictx, void (*cb)(void *c), void *c)
{
input_lock(ictx);
- ictx->cancel = cancel;
+ ictx->cancel = cb;
+ ictx->cancel_ctx = c;
input_unlock(ictx);
}
diff --git a/input/input.h b/input/input.h
index 5b5edd580d..fb928e0808 100644
--- a/input/input.h
+++ b/input/input.h
@@ -242,8 +242,7 @@ void mp_input_wakeup(struct input_ctx *ictx);
// Used to asynchronously abort playback. Needed because the core still can
// block on network in some situations.
-struct mp_cancel;
-void mp_input_set_cancel(struct input_ctx *ictx, struct mp_cancel *cancel);
+void mp_input_set_cancel(struct input_ctx *ictx, void (*cb)(void *c), void *c);
// If this returns true, use Right Alt key as Alt Gr to produce special
// characters. If false, count Right Alt as the modifier Alt key.
diff --git a/player/client.c b/player/client.c
index 88926f3544..31a55332d2 100644
--- a/player/client.c
+++ b/player/client.c
@@ -982,7 +982,7 @@ static int run_client_command(mpv_handle *ctx, struct mp_cmd *cmd, mpv_node *res
return MPV_ERROR_INVALID_PARAMETER;
if (mp_input_is_abort_cmd(cmd))
- mp_cancel_trigger(ctx->mpctx->playback_abort);
+ mp_abort_playback_async(ctx->mpctx);
cmd->sender = ctx->name;
diff --git a/player/core.h b/player/core.h
index d7ff507524..ad61500741 100644
--- a/player/core.h
+++ b/player/core.h
@@ -430,6 +430,11 @@ typedef struct MPContext {
struct mp_ipc_ctx *ipc_ctx;
struct mpv_opengl_cb_context *gl_cb_ctx;
+
+ pthread_mutex_t lock;
+
+ // --- The following fields are protected by lock
+ struct mp_cancel *demuxer_cancel; // cancel handle for MPContext.demuxer
} MPContext;
// audio.c
@@ -460,6 +465,7 @@ struct playlist_entry *mp_check_playlist_resume(struct MPContext *mpctx,
struct playlist *playlist);
// loadfile.c
+void mp_abort_playback_async(struct MPContext *mpctx);
void uninit_player(struct MPContext *mpctx, unsigned int mask);
struct track *mp_add_external_file(struct MPContext *mpctx, char *filename,
enum stream_type filter);
diff --git a/player/loadfile.c b/player/loadfile.c
index 872db20399..e59acbc8d4 100644
--- a/player/loadfile.c
+++ b/player/loadfile.c
@@ -57,6 +57,17 @@
#include "command.h"
#include "libmpv/client.h"
+// Called by foreign threads when playback should be stopped and such.
+void mp_abort_playback_async(struct MPContext *mpctx)
+{
+ mp_cancel_trigger(mpctx->playback_abort);
+
+ pthread_mutex_lock(&mpctx->lock);
+ if (mpctx->demuxer_cancel)
+ mp_cancel_trigger(mpctx->demuxer_cancel);
+ pthread_mutex_unlock(&mpctx->lock);
+}
+
static void uninit_demuxer(struct MPContext *mpctx)
{
for (int r = 0; r < NUM_PTRACKS; r++) {
@@ -80,6 +91,11 @@ static void uninit_demuxer(struct MPContext *mpctx)
free_demuxer_and_stream(mpctx->demuxer);
mpctx->demuxer = NULL;
+
+ pthread_mutex_lock(&mpctx->lock);
+ talloc_free(mpctx->demuxer_cancel);
+ mpctx->demuxer_cancel = NULL;
+ pthread_mutex_unlock(&mpctx->lock);
}
#define APPEND(s, ...) mp_snprintf_cat(s, sizeof(s), __VA_ARGS__)
@@ -808,11 +824,14 @@ static void open_demux_reentrant(struct MPContext *mpctx)
{
struct demux_open_args args = {
.global = mpctx->global,
- .cancel = mpctx->playback_abort,
+ .cancel = mp_cancel_new(NULL),
.log = mpctx->log,
.stream_flags = mpctx->playing->stream_flags,
.url = talloc_strdup(NULL, mpctx->stream_open_filename),
};
+ pthread_mutex_lock(&mpctx->lock);
+ mpctx->demuxer_cancel = args.cancel;
+ pthread_mutex_unlock(&mpctx->lock);
if (mpctx->opts->load_unsafe_playlists)
args.stream_flags = 0;
mpctx_run_reentrant(mpctx, open_demux_thread, &args);
@@ -820,6 +839,10 @@ static void open_demux_reentrant(struct MPContext *mpctx)
mpctx->demuxer = args.demux;
} else {
mpctx->error_playing = args.err;
+ pthread_mutex_lock(&mpctx->lock);
+ talloc_free(mpctx->demuxer_cancel);
+ mpctx->demuxer_cancel = NULL;
+ pthread_mutex_unlock(&mpctx->lock);
}
talloc_free(args.url);
}
@@ -1170,7 +1193,7 @@ terminate_playback:
if (mpctx->step_frames)
opts->pause = 1;
- mp_cancel_trigger(mpctx->playback_abort);
+ mp_abort_playback_async(mpctx);
// time to uninit all, except global stuff:
uninit_complex_filters(mpctx);
diff --git a/player/main.c b/player/main.c
index 3a07e0f539..8f54b98728 100644
--- a/player/main.c
+++ b/player/main.c
@@ -311,6 +311,12 @@ static int cfg_include(void *ctx, char *filename, int flags)
return r;
}
+static void abort_playback_cb(void *ctx)
+{
+ struct MPContext *mpctx = ctx;
+ mp_abort_playback_async(mpctx);
+}
+
struct MPContext *mp_create(void)
{
char *enable_talloc = getenv("MPV_LEAK_REPORT");
@@ -361,7 +367,7 @@ struct MPContext *mp_create(void)
cocoa_set_input_context(mpctx->input);
#endif
- mp_input_set_cancel(mpctx->input, mpctx->playback_abort);
+ mp_input_set_cancel(mpctx->input, abort_playback_cb, mpctx);
char *verbose_env = getenv("MPV_VERBOSE");
if (verbose_env)
diff --git a/player/misc.c b/player/misc.c
index eb4c1c031e..032342e84a 100644
--- a/player/misc.c
+++ b/player/misc.c
@@ -287,7 +287,7 @@ int mpctx_run_reentrant(struct MPContext *mpctx, void (*thread_fn)(void *arg),
mp_idle(mpctx);
if (mpctx->stop_play)
- mp_cancel_trigger(mpctx->playback_abort);
+ mp_abort_playback_async(mpctx);
pthread_mutex_lock(&args.mutex);
success |= args.done;