summaryrefslogtreecommitdiffstats
path: root/player/loadfile.c
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2020-03-07 02:52:10 +0100
committerwm4 <wm4@nowhere>2020-03-07 02:52:10 +0100
commitba70b150fbe89c00e4ef7dcb975ec695b49dac8d (patch)
tree0114edb0a97b4c585b77a8496ff9b77eb118c856 /player/loadfile.c
parent8a4f812b76befa9529591e274cefdd2f234fb450 (diff)
downloadmpv-ba70b150fbe89c00e4ef7dcb975ec695b49dac8d.tar.bz2
mpv-ba70b150fbe89c00e4ef7dcb975ec695b49dac8d.tar.xz
client API: provide ways to finish property changes on file changes
When the current file changes (or rather, when starting/finishing playback of a playlist entry), clients tend to have the problem that it's hard to tell whether a property change notification (via mpv_observe_property() and mechanisms layered on top of it) is from the previous or new playlist entry. The previous commit probably helps, but all the asynchronity is still a bit unhelpful. Try to make this better by adding new hooks, that are run before/after playback init/deinit. This is similar to the existing hooks, except they're outside of "initialized" playback, which excludes that you might accidentally get an overlap between the current and the previous/next playlist entry. That still doesn't seem quite enough, since normally, property change notifications come after the hook event. So basically a client would have to explicitly "drain" the event queue within the hook, and make the hook continue only after that is done. Knowing when property notifications are done is another asynchronous nightmare (how exactly it works keeps changing within client.c, and an API user probably can't tell anymore when all pending properties are truly done). So introduce another guarantee: properties that were changed before the hook happens will be returned before the hook event is returned. That means the client will have received all pending property notifications from the previous playlist entry (or whatever) before the hook is entered. As another minor complication, we shouldn't just keep the hook pending until _all_ property notifications are done, since the client's hook could produce new ones. (Or just consider things like the demuxer thread hammering the client with cache update events, while the "on_preloaded" hook is run.) So there is some extra untested, fragile logic in client.c to handle this (the waiting_for_hook flag). This probably works, but was barely tested. Not sure if this helps anyone, but I think it's fine for my own purposes. (I really hated this aspect of the API whenever I used it myself.)
Diffstat (limited to 'player/loadfile.c')
-rw-r--r--player/loadfile.c11
1 files changed, 9 insertions, 2 deletions
diff --git a/player/loadfile.c b/player/loadfile.c
index d2bdb47ccd..9eb58c0f4d 100644
--- a/player/loadfile.c
+++ b/player/loadfile.c
@@ -931,7 +931,8 @@ static void process_hooks(struct MPContext *mpctx, char *name)
while (!mp_hook_test_completion(mpctx, name)) {
mp_idle(mpctx);
- // We have no idea what blocks a hook, so just do a full abort.
+ // We have no idea what blocks a hook, so just do a full abort. This
+ // does nothing for hooks that happen outside of playback.
if (mpctx->stop_play)
mp_abort_playback_async(mpctx);
}
@@ -1374,13 +1375,17 @@ static void play_current_file(struct MPContext *mpctx)
double playback_start = -1e100;
assert(mpctx->stop_play);
+ mpctx->stop_play = 0;
+
+ process_hooks(mpctx, "on_before_start_file");
+ if (mpctx->stop_play)
+ return;
mp_notify(mpctx, MPV_EVENT_START_FILE, NULL);
mp_cancel_reset(mpctx->playback_abort);
mpctx->error_playing = MPV_ERROR_LOADING_FAILED;
- mpctx->stop_play = 0;
mpctx->filename = NULL;
mpctx->shown_aframes = 0;
mpctx->shown_vframes = 0;
@@ -1701,6 +1706,8 @@ terminate_playback:
}
assert(mpctx->stop_play);
+
+ process_hooks(mpctx, "on_after_end_file");
}
// Determine the next file to play. Note that if this function returns non-NULL,