summaryrefslogtreecommitdiffstats
path: root/player
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2014-06-07 15:08:45 +0200
committerwm4 <wm4@nowhere>2014-06-07 15:57:54 +0200
commit500ce69a06be2cb2b79f310e638e4c4ceabe447e (patch)
treea855d9bc2c2be7deaa9db06c787d61ffd1f33136 /player
parentd64bd9efa13c5e1fc71cfc565950b4afe6e53c8a (diff)
downloadmpv-500ce69a06be2cb2b79f310e638e4c4ceabe447e.tar.bz2
mpv-500ce69a06be2cb2b79f310e638e4c4ceabe447e.tar.xz
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.)
Diffstat (limited to 'player')
-rw-r--r--player/client.c34
-rw-r--r--player/core.h1
-rw-r--r--player/main.c4
3 files changed, 37 insertions, 2 deletions
diff --git a/player/client.c b/player/client.c
index be8cbc5d88..9a984052b1 100644
--- a/player/client.c
+++ b/player/client.c
@@ -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);
diff --git a/player/core.h b/player/core.h
index b107edc7e4..ca61ab8f11 100644
--- a/player/core.h
+++ b/player/core.h
@@ -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;
diff --git a/player/main.c b/player/main.c
index 0bfd25bdd5..d7b34e0ef8 100644
--- a/player/main.c
+++ b/player/main.c
@@ -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);
}