summaryrefslogtreecommitdiffstats
path: root/sub/osd_libass.c
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2016-03-08 21:42:08 +0100
committerwm4 <wm4@nowhere>2016-03-08 22:00:02 +0100
commit75a36662cb6bb0c8a2aeb3a4034d3f8dc745bbdd (patch)
treeeeb8967caa71b555dcfa43ec932a90fcd9c52ebe /sub/osd_libass.c
parented254f29a93474defd932e52d6995628e01d82aa (diff)
downloadmpv-75a36662cb6bb0c8a2aeb3a4034d3f8dc745bbdd.tar.bz2
mpv-75a36662cb6bb0c8a2aeb3a4034d3f8dc745bbdd.tar.xz
osd, lua: manage multiple ASS overlays set with set_osd_ass() calls
Until now, there was only 1 global ASS overlay that could be set by all scripts. This was often perceived as bug when multiple scripts tried to set their own ASS overlay. This was kind of hard to solve because the script could set its own ASS PlayResX/Y, which makes it impossible to share a single ASS_Renderer for multiple scripts. The OSC unfortunately makes use of this feature (and unfortunately can't be fixed because it's a POS), so we're stuck with this complication. Implement the worst-case solution and fix this by creating separate ASS track and renderer objects for each script that wants to set an ASS overlay. The z-order is decided by the order the scripts set their text first. This is essentially random, unless you do it at script init, and you pass scripts in a specific order. Script initialization is currently serialized (as a feature), so the first loaded script gets lowest Z-order. The Lua script API interestingly remains the same. (And also will remain undocumented, unsupported, and potentially volatile.)
Diffstat (limited to 'sub/osd_libass.c')
-rw-r--r--sub/osd_libass.c81
1 files changed, 62 insertions, 19 deletions
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;