mirror of
https://github.com/mpv-player/mpv.git
synced 2024-09-20 03:52:22 +02:00
client API: add API function that ensures total destruction
mpv_destroy() should perhaps better be called mpv_detach(), because it destroys only the handle, not necessarily the player. The player is only terminated if a quit command is sent. This function quits automatically, and additionally waits until the player is completely destroyed. It removes the possibility that the player core is still uninitializing, while all client handles are already destroyed. (Although in practice, the difference is usually not important.)
This commit is contained in:
parent
d64bd9efa1
commit
500ce69a06
@ -316,10 +316,27 @@ int mpv_initialize(mpv_handle *ctx);
|
||||
* Disconnect and destroy the client context. ctx will be deallocated with this
|
||||
* API call. This leaves the player running. If you want to be sure that the
|
||||
* player is terminated, send a "quit" command, and wait until the
|
||||
* MPV_EVENT_SHUTDOWN event is received.
|
||||
* MPV_EVENT_SHUTDOWN event is received, or use mpv_terminate_destroy().
|
||||
*/
|
||||
void mpv_destroy(mpv_handle *ctx);
|
||||
|
||||
/**
|
||||
* Similar to mpv_destroy(), but brings the player and all clients down as well,
|
||||
* and waits until all of them are destroyed. This function blocks. The
|
||||
* advantage over mpv_destroy() is that while mpv_destroy() merely detaches
|
||||
* the client handle from the player, this function quits the player, waits
|
||||
* until all other clients are destroyed (i.e. all mpv_handles are detached),
|
||||
* and also waits for the final termination of the player.
|
||||
*
|
||||
* Since mpv_destroy() is called somewhere on the way, it's not safe to call
|
||||
* other functions concurrently on the same context.
|
||||
*
|
||||
* If this is called on a mpv_handle that was not created with mpv_create(),
|
||||
* this function will merely send a quit command and then call mpv_destroy(),
|
||||
* without waiting for the actual shutdown.
|
||||
*/
|
||||
void mpv_terminate_destroy(mpv_handle *ctx);
|
||||
|
||||
/**
|
||||
* Load a config file. This loads and parses the file, and sets every entry in
|
||||
* the config file's default section as if mpv_set_option_string() is called.
|
||||
|
@ -77,6 +77,7 @@ struct observe_property {
|
||||
struct mpv_handle {
|
||||
// -- immmutable
|
||||
char *name;
|
||||
bool owner;
|
||||
struct mp_log *log;
|
||||
struct MPContext *mpctx;
|
||||
struct mp_client_api *clients;
|
||||
@ -299,11 +300,41 @@ void mpv_destroy(mpv_handle *ctx)
|
||||
assert(!ctx);
|
||||
}
|
||||
|
||||
static void get_thread(void *ptr)
|
||||
{
|
||||
*(pthread_t *)ptr = pthread_self();
|
||||
}
|
||||
|
||||
void mpv_terminate_destroy(mpv_handle *ctx)
|
||||
{
|
||||
mpv_command(ctx, (const char*[]){"quit", NULL});
|
||||
|
||||
if (!ctx->owner) {
|
||||
mpv_destroy(ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
mp_dispatch_lock(ctx->mpctx->dispatch);
|
||||
assert(ctx->mpctx->autodetach);
|
||||
ctx->mpctx->autodetach = false;
|
||||
mp_dispatch_unlock(ctx->mpctx->dispatch);
|
||||
|
||||
pthread_t playthread;
|
||||
mp_dispatch_run(ctx->mpctx->dispatch, get_thread, &playthread);
|
||||
|
||||
mpv_destroy(ctx);
|
||||
|
||||
// And this is also the reason why we only allow 1 thread (the owner) to
|
||||
// call this function.
|
||||
pthread_join(playthread, NULL);
|
||||
}
|
||||
|
||||
mpv_handle *mpv_create(void)
|
||||
{
|
||||
struct MPContext *mpctx = mp_create();
|
||||
mpv_handle *ctx = mp_new_client(mpctx->clients, "main");
|
||||
if (ctx) {
|
||||
ctx->owner = true;
|
||||
// Set some defaults.
|
||||
mpv_set_option_string(ctx, "config", "no");
|
||||
mpv_set_option_string(ctx, "idle", "yes");
|
||||
@ -319,8 +350,7 @@ mpv_handle *mpv_create(void)
|
||||
static void *playback_thread(void *p)
|
||||
{
|
||||
struct MPContext *mpctx = p;
|
||||
|
||||
pthread_detach(pthread_self());
|
||||
mpctx->autodetach = true;
|
||||
|
||||
mp_play_files(mpctx);
|
||||
|
||||
|
@ -144,6 +144,7 @@ enum {
|
||||
typedef struct MPContext {
|
||||
bool initialized;
|
||||
bool is_cplayer;
|
||||
bool autodetach;
|
||||
struct mpv_global *global;
|
||||
struct MPOpts *opts;
|
||||
struct mp_log *log;
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "talloc.h"
|
||||
@ -148,6 +149,9 @@ void mp_destroy(struct MPContext *mpctx)
|
||||
}
|
||||
uninit_libav(mpctx->global);
|
||||
|
||||
if (mpctx->autodetach)
|
||||
pthread_detach(pthread_self());
|
||||
|
||||
mp_msg_uninit(mpctx->global);
|
||||
talloc_free(mpctx);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user