diff options
Diffstat (limited to 'sub/osd.c')
-rw-r--r-- | sub/osd.c | 100 |
1 files changed, 38 insertions, 62 deletions
@@ -61,6 +61,7 @@ static const m_option_t style_opts[] = { ({"top", -1}, {"center", 0}, {"bottom", +1})), OPT_FLOATRANGE("blur", blur, 0, 0, 20), OPT_FLAG("bold", bold, 0), + OPT_FLAG("italic", italic, 0), {0} }; @@ -109,6 +110,8 @@ static bool osd_res_equals(struct mp_osd_res a, struct mp_osd_res b) struct osd_state *osd_create(struct mpv_global *global) { + assert(MAX_OSD_PARTS >= OSDTYPE_COUNT); + struct osd_state *osd = talloc_zero(NULL, struct osd_state); *osd = (struct osd_state) { .opts = global->opts, @@ -145,30 +148,31 @@ 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; } -void osd_set_text(struct osd_state *osd, int obj, const char *text) +void osd_set_text(struct osd_state *osd, const char *text) { pthread_mutex_lock(&osd->lock); - struct osd_object *osd_obj = osd->objs[obj]; + struct osd_object *osd_obj = osd->objs[OSDTYPE_OSD]; if (!text) text = ""; if (strcmp(osd_obj->text, text) != 0) { talloc_free(osd_obj->text); osd_obj->text = talloc_strdup(osd_obj, text); - osd_changed_unlocked(osd, obj); + osd_changed_unlocked(osd, osd_obj->type); } pthread_mutex_unlock(&osd->lock); } -void osd_set_sub(struct osd_state *osd, int obj, struct dec_sub *dec_sub) +void osd_set_sub(struct osd_state *osd, int index, struct dec_sub *dec_sub) { pthread_mutex_lock(&osd->lock); - osd->objs[obj]->sub = dec_sub; + if (index >= 0 && index < 2) + osd->objs[OSDTYPE_SUB + index]->sub = dec_sub; pthread_mutex_unlock(&osd->lock); } @@ -201,28 +205,38 @@ 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) +void osd_set_external2(struct osd_state *osd, struct sub_bitmaps *imgs) { 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); - } + osd->objs[OSDTYPE_EXTERNAL2]->external2 = imgs; + osd_changed_unlocked(osd, OSDTYPE_EXTERNAL2); pthread_mutex_unlock(&osd->lock); } -void osd_set_external2(struct osd_state *osd, struct sub_bitmaps *imgs) +static void check_obj_resize(struct osd_state *osd, struct mp_osd_res res, + struct osd_object *obj) +{ + if (!osd_res_equals(res, obj->vo_res)) { + obj->vo_res = res; + obj->force_redraw = true; + mp_client_broadcast_event(mp_client_api_get_core(osd->global->client_api), + MP_EVENT_WIN_RESIZE, NULL); + } +} + +// Optional. Can be called for faster reaction of OSD-generating scripts like +// osc.lua. This can achieve that the resize happens first, so that the OSD is +// generated at the correct resolution the first time the resized frame is +// rendered. Since the OSD doesn't (and can't) wait for the script, this +// increases the time in which the script can react, and also gets rid of the +// unavoidable redraw delay (though it will still be racy). +// Unnecessary for anything else. +void osd_resize(struct osd_state *osd, struct mp_osd_res res) { pthread_mutex_lock(&osd->lock); - osd->objs[OSDTYPE_EXTERNAL2]->external2 = imgs; - osd_changed_unlocked(osd, OSDTYPE_EXTERNAL2); + int types[] = {OSDTYPE_OSD, OSDTYPE_EXTERNAL, OSDTYPE_EXTERNAL2, -1}; + for (int n = 0; types[n] >= 0; n++) + check_obj_resize(osd, res, osd->objs[types[n]]); pthread_mutex_unlock(&osd->lock); } @@ -240,12 +254,7 @@ static void render_object(struct osd_state *osd, struct osd_object *obj, *out_imgs = (struct sub_bitmaps) {0}; - if (!osd_res_equals(res, obj->vo_res)) { - obj->vo_res = res; - obj->force_redraw = true; - mp_client_broadcast_event(mp_client_api_get_core(osd->global->client_api), - MP_EVENT_WIN_RESIZE, NULL); - } + check_obj_resize(osd, res, obj); if (obj->type == OSDTYPE_SUB || obj->type == OSDTYPE_SUB2) { if (obj->sub) { @@ -422,44 +431,11 @@ bool osd_query_and_reset_want_redraw(struct osd_state *osd) return r; } -// Scale factor to translate OSD coordinates to what the obj uses internally. -// osd_coordinates * (sw, sh) = obj_coordinates -void osd_object_get_scale_factor(struct osd_state *osd, int obj, - double *sw, double *sh) -{ - int nw, nh; - osd_object_get_resolution(osd, obj, &nw, &nh); - pthread_mutex_lock(&osd->lock); - int vow = osd->objs[obj]->vo_res.w; - int voh = osd->objs[obj]->vo_res.h; - pthread_mutex_unlock(&osd->lock); - *sw = vow ? nw / (double)vow : 0; - *sh = voh ? nh / (double)voh : 0; -} - -// Turn *x and *y, which are given in OSD coordinates, to video coordinates. -// frame_w and frame_h give the dimensions of the original, unscaled video. -// (This gives correct results only after the OSD has been updated after a -// resize or video reconfig.) -void osd_coords_to_video(struct osd_state *osd, int frame_w, int frame_h, - int *x, int *y) +struct mp_osd_res osd_get_vo_res(struct osd_state *osd) { pthread_mutex_lock(&osd->lock); + // Any OSDTYPE is fine; but it mustn't be a subtitle one (can have lower res.) struct mp_osd_res res = osd->objs[OSDTYPE_OSD]->vo_res; - int vidw = res.w - res.ml - res.mr; - int vidh = res.h - res.mt - res.mb; - double xscale = (double)vidw / frame_w; - double yscale = (double)vidh / frame_h; - // The OSD size + margins make up the scaled rectangle of the video. - *x = (*x - res.ml) / xscale; - *y = (*y - res.mt) / yscale; - pthread_mutex_unlock(&osd->lock); -} - -struct mp_osd_res osd_get_vo_res(struct osd_state *osd, int obj) -{ - pthread_mutex_lock(&osd->lock); - struct mp_osd_res res = osd->objs[obj]->vo_res; pthread_mutex_unlock(&osd->lock); return res; } |