diff --git a/player/lua.c b/player/lua.c index 04c7dbb977..680577554c 100644 --- a/player/lua.c +++ b/player/lua.c @@ -391,6 +391,7 @@ static int load_lua(struct mpv_handle *client, const char *fname) r = 0; error_out: + osd_set_external(ctx->mpctx->osd, client, 0, 0, NULL); // remove overlay mp_resume_all(client); if (ctx->state) lua_close(ctx->state); @@ -963,14 +964,14 @@ static int script_command_native(lua_State *L) static int script_set_osd_ass(lua_State *L) { - struct MPContext *mpctx = get_mpctx(L); + struct script_ctx *ctx = get_ctx(L); int res_x = luaL_checkinteger(L, 1); int res_y = luaL_checkinteger(L, 2); const char *text = luaL_checkstring(L, 3); if (!text[0]) text = " "; // force external OSD initialization - osd_set_external(mpctx->osd, res_x, res_y, (char *)text); - mp_input_wakeup(mpctx->input); + osd_set_external(ctx->mpctx->osd, ctx->client, res_x, res_y, (char *)text); + mp_input_wakeup(ctx->mpctx->input); return 0; } diff --git a/sub/osd.c b/sub/osd.c index a9bc035c73..c05fc5a0e3 100644 --- a/sub/osd.c +++ b/sub/osd.c @@ -145,7 +145,7 @@ void osd_free(struct osd_state *osd) talloc_free(osd); } -static void osd_changed_unlocked(struct osd_state *osd, int obj) +void osd_changed_unlocked(struct osd_state *osd, int obj) { osd->objs[obj]->force_redraw = true; osd->want_redraw = true; @@ -201,23 +201,6 @@ void osd_set_progbar(struct osd_state *osd, struct osd_progbar_state *s) pthread_mutex_unlock(&osd->lock); } -void osd_set_external(struct osd_state *osd, int res_x, int res_y, char *text) -{ - pthread_mutex_lock(&osd->lock); - struct osd_object *osd_obj = osd->objs[OSDTYPE_EXTERNAL]; - if (strcmp(osd_obj->text, text) != 0 || - osd_obj->external_res_x != res_x || - osd_obj->external_res_y != res_y) - { - talloc_free(osd_obj->text); - osd_obj->text = talloc_strdup(osd_obj, text); - osd_obj->external_res_x = res_x; - osd_obj->external_res_y = res_y; - osd_changed_unlocked(osd, osd_obj->type); - } - pthread_mutex_unlock(&osd->lock); -} - void osd_set_external2(struct osd_state *osd, struct sub_bitmaps *imgs) { pthread_mutex_lock(&osd->lock); diff --git a/sub/osd.h b/sub/osd.h index c066b09645..654330f152 100644 --- a/sub/osd.h +++ b/sub/osd.h @@ -163,8 +163,6 @@ struct osd_progbar_state { }; void osd_set_progbar(struct osd_state *osd, struct osd_progbar_state *s); -void osd_set_external(struct osd_state *osd, int res_x, int res_y, char *text); - void osd_set_external2(struct osd_state *osd, struct sub_bitmaps *imgs); enum mp_osd_draw_flags { @@ -203,6 +201,9 @@ void osd_object_get_bitmaps(struct osd_state *osd, struct osd_object *obj, void osd_init_backend(struct osd_state *osd); void osd_destroy_backend(struct osd_state *osd); +void osd_set_external(struct osd_state *osd, void *id, int res_x, int res_y, + char *text); + // doesn't need locking void osd_get_function_sym(char *buffer, size_t buffer_size, int osd_function); extern const char *const osd_ass_0; diff --git a/sub/osd_dummy.c b/sub/osd_dummy.c index 1982870248..061f6446c3 100644 --- a/sub/osd_dummy.c +++ b/sub/osd_dummy.c @@ -26,3 +26,8 @@ void osd_object_get_bitmaps(struct osd_state *osd, struct osd_object *obj, { *out_imgs = (struct sub_bitmaps) {0}; } + +void osd_set_external(struct osd_state *osd, char *id, int res_x, int res_y, + char *text) +{ +} diff --git a/sub/osd_libass.c b/sub/osd_libass.c index d58573a910..30d404d8c6 100644 --- a/sub/osd_libass.c +++ b/sub/osd_libass.c @@ -79,12 +79,21 @@ static void destroy_ass_renderer(struct ass_state *ass) ass->log = NULL; } +static void destroy_external(struct osd_external *ext) +{ + talloc_free(ext->text); + destroy_ass_renderer(&ext->ass); +} + void osd_destroy_backend(struct osd_state *osd) { for (int n = 0; n < MAX_OSD_PARTS; n++) { struct osd_object *obj = osd->objs[n]; destroy_ass_renderer(&obj->ass); talloc_free(obj->parts_cache.parts); + for (int i = 0; i < obj->num_externals; i++) + destroy_external(&obj->externals[i]); + obj->num_externals = 0; } } @@ -431,44 +440,76 @@ static void update_osd(struct osd_state *osd, struct osd_object *obj) update_progbar(osd, obj); } -static void update_external(struct osd_state *osd, struct osd_object *obj) +static void update_external(struct osd_state *osd, struct osd_object *obj, + struct osd_external *ext) { - bstr t = bstr0(obj->text); + bstr t = bstr0(ext->text); if (!t.len) return; - create_ass_track(osd, obj, &obj->ass, obj->external_res_x, - obj->external_res_y); + create_ass_track(osd, obj, &ext->ass, ext->res_x, ext->res_y); - clear_ass(&obj->ass); + clear_ass(&ext->ass); - int resy = obj->ass.track->PlayResY; - mp_ass_set_style(get_style(&obj->ass, "OSD"), resy, osd->opts->osd_style); + int resy = ext->ass.track->PlayResY; + mp_ass_set_style(get_style(&ext->ass, "OSD"), resy, osd->opts->osd_style); // Some scripts will reference this style name with \r tags. const struct osd_style_opts *def = osd_style_conf.defaults; - mp_ass_set_style(get_style(&obj->ass, "Default"), resy, def); + mp_ass_set_style(get_style(&ext->ass, "Default"), resy, def); while (t.len) { bstr line; bstr_split_tok(t, "\n", &line, &t); if (line.len) { char *tmp = bstrdup0(NULL, line); - add_osd_ass_event(obj->ass.track, "OSD", tmp); + add_osd_ass_event(ext->ass.track, "OSD", tmp); talloc_free(tmp); } } } -static void update_object(struct osd_state *osd, struct osd_object *obj) +void osd_set_external(struct osd_state *osd, void *id, int res_x, int res_y, + char *text) { - switch (obj->type) { - case OSDTYPE_OSD: - update_osd(osd, obj); - break; - case OSDTYPE_EXTERNAL: - update_external(osd, obj); - break; + pthread_mutex_lock(&osd->lock); + struct osd_object *obj = osd->objs[OSDTYPE_EXTERNAL]; + struct osd_external *entry = 0; + for (int n = 0; n < obj->num_externals; n++) { + if (obj->externals[n].id == id) { + entry = &obj->externals[n]; + break; + } } + if (!entry && !text) + goto done; + + if (!entry) { + struct osd_external new = { .id = id }; + MP_TARRAY_APPEND(obj, obj->externals, obj->num_externals, new); + entry = &obj->externals[obj->num_externals - 1]; + } + + if (!text) { + int index = entry - &obj->externals[0]; + destroy_external(entry); + MP_TARRAY_REMOVE_AT(obj->externals, obj->num_externals, index); + goto done; + } + + if (!entry->text || strcmp(entry->text, text) != 0 || + entry->res_x != res_x || entry->res_y != res_y) + { + talloc_free(entry->text); + entry->text = talloc_strdup(NULL, text); + entry->res_x = res_x; + entry->res_y = res_y; + update_external(osd, obj, entry); + obj->parts_cache.change_id = 1; + osd_changed_unlocked(osd, obj->type); + } + +done: + pthread_mutex_unlock(&osd->lock); } static void append_ass(struct ass_state *ass, struct mp_osd_res *res, @@ -485,10 +526,12 @@ static void append_ass(struct ass_state *ass, struct mp_osd_res *res, void osd_object_get_bitmaps(struct osd_state *osd, struct osd_object *obj, struct sub_bitmaps *out_imgs) { - if (obj->force_redraw) - update_object(osd, obj); + if (obj->force_redraw && obj->type == OSDTYPE_OSD) + update_osd(osd, obj); append_ass(&obj->ass, &obj->vo_res, &obj->parts_cache); + for (int n = 0; n < obj->num_externals; n++) + append_ass(&obj->externals[n].ass, &obj->vo_res, &obj->parts_cache); *out_imgs = obj->parts_cache; diff --git a/sub/osd_state.h b/sub/osd_state.h index 66fee5a387..c52c3354cd 100644 --- a/sub/osd_state.h +++ b/sub/osd_state.h @@ -20,7 +20,7 @@ struct osd_object { bool force_redraw; - // OSDTYPE_SUB/OSDTYPE_SUB2/OSDTYPE_OSD/OSDTYPE_EXTERNAL + // OSDTYPE_OSD char *text; // OSDTYPE_OSD @@ -30,7 +30,8 @@ struct osd_object { struct dec_sub *sub; // OSDTYPE_EXTERNAL - int external_res_x, external_res_y; + struct osd_external *externals; + int num_externals; // OSDTYPE_EXTERNAL2 struct sub_bitmaps *external2; @@ -48,6 +49,13 @@ struct osd_object { struct ass_state ass; }; +struct osd_external { + void *id; + char *text; + int res_x, res_y; + struct ass_state ass; +}; + struct osd_state { pthread_mutex_t lock; @@ -64,4 +72,6 @@ struct osd_state { struct mp_draw_sub_cache *draw_cache; }; +void osd_changed_unlocked(struct osd_state *osd, int obj); + #endif