summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2017-01-26 18:24:53 +0100
committerwm4 <wm4@nowhere>2017-01-26 18:24:53 +0100
commitabc6d130ace804bfa333955ff2cd402d927959c6 (patch)
tree1b7aba8831e99e438855f776bfa412e3b3e5d7bf
parent60452f640fd405133ebf6f7ba773b0e25071fcf1 (diff)
downloadmpv-abc6d130ace804bfa333955ff2cd402d927959c6.tar.bz2
mpv-abc6d130ace804bfa333955ff2cd402d927959c6.tar.xz
command: shorten long playlists on OSD
A hacky, convoluted, half-working mess that attempts to cut off overlong playlists. It does so by relying on the ASS formatting rule that the font size is specified in the virtual PlayResY resolution. This means we can (normally) easily tell how many lines fit on the screen. On the other hand, this does not work if the text is wrapped. This as a kludge until a Betterâ„¢ solution is available.
-rw-r--r--player/command.c81
-rw-r--r--sub/osd.h1
-rw-r--r--sub/osd_dummy.c6
-rw-r--r--sub/osd_libass.c28
4 files changed, 107 insertions, 9 deletions
diff --git a/player/command.c b/player/command.c
index 6e7389d666..da5d985c17 100644
--- a/player/command.c
+++ b/player/command.c
@@ -243,6 +243,78 @@ void mark_seek(struct MPContext *mpctx)
cmd->last_seek_time = now;
}
+static char *skip_n_lines(char *text, int lines)
+{
+ while (text && lines > 0) {
+ char *next = strchr(text, '\n');
+ text = next ? next + 1 : NULL;
+ lines--;
+ }
+ return text;
+}
+
+static int count_lines(char *text)
+{
+ int count = 0;
+ while (text) {
+ char *next = strchr(text, '\n');
+ if (!next || (next[0] == '\n' && !next[1]))
+ break;
+ text = next + 1;
+ count++;
+ }
+ return count;
+}
+
+// Given a huge string separated by new lines, attempts to cut off text above
+// the current line to keep the line visible, and below to keep rendering
+// performance up. pos gives the current line (0 for the first line).
+// "text" might be returned as is, or it can be freed and a new allocation is
+// returned.
+// This is only a heuristic - we can't deal with line breaking.
+static char *cut_osd_list(struct MPContext *mpctx, char *text, int pos)
+{
+ int screen_h, font_h;
+ osd_get_text_size(mpctx->osd, &screen_h, &font_h);
+ int max_lines = screen_h / MPMAX(font_h, 1) - 1;
+
+ if (!text || max_lines < 5)
+ return text;
+
+ int count = count_lines(text);
+ if (count <= max_lines)
+ return text;
+
+ char *new = talloc_strdup(NULL, "");
+
+ int start = pos - max_lines / 2;
+ if (start == 1)
+ start = 0; // avoid weird transition when pad_h becomes visible
+ int pad_h = start > 0;
+ if (pad_h)
+ new = talloc_strdup_append_buffer(new, "\342\206\221 (hidden items)\n");
+
+ int space = max_lines - pad_h - 1;
+ int pad_t = count - start > space;
+ if (!pad_t)
+ start = count - space;
+
+ char *head = skip_n_lines(text, start);
+ if (!head) {
+ talloc_free(new);
+ return text;
+ }
+
+ char *tail = skip_n_lines(head, max_lines - pad_h - pad_t);
+ new = talloc_asprintf_append_buffer(new, "%.*s",
+ (int)(tail ? tail - head : strlen(head)), head);
+ if (pad_t)
+ new = talloc_strdup_append_buffer(new, "\342\206\223 (hidden items)\n");
+
+ talloc_free(text);
+ return new;
+}
+
static char *format_file_size(int64_t size)
{
double s = size;
@@ -3321,9 +3393,10 @@ static int mp_property_playlist(void *ctx, struct m_property *prop,
{
MPContext *mpctx = ctx;
if (action == M_PROPERTY_PRINT) {
+ struct playlist *pl = mpctx->playlist;
char *res = talloc_strdup(NULL, "");
- for (struct playlist_entry *e = mpctx->playlist->first; e; e = e->next)
+ for (struct playlist_entry *e = pl->first; e; e = e->next)
{
char *p = e->filename;
if (!mp_is_url(bstr0(p))) {
@@ -3331,12 +3404,12 @@ static int mp_property_playlist(void *ctx, struct m_property *prop,
if (s[0])
p = s;
}
- const char *m = mpctx->playlist->current == e ?
- list_current : list_normal;
+ const char *m = pl->current == e ? list_current : list_normal;
res = talloc_asprintf_append(res, "%s%s\n", m, p);
}
- *(char **)arg = res;
+ *(char **)arg =
+ cut_osd_list(mpctx, res, playlist_entry_to_index(pl, pl->current));
return M_PROPERTY_OK;
}
diff --git a/sub/osd.h b/sub/osd.h
index f0ebc3b827..aef1c60b33 100644
--- a/sub/osd.h
+++ b/sub/osd.h
@@ -201,6 +201,7 @@ void osd_rescale_bitmaps(struct sub_bitmaps *imgs, int frame_w, int frame_h,
// defined in osd_libass.c and osd_dummy.c
void osd_set_external(struct osd_state *osd, void *id, int res_x, int res_y,
char *text);
+void osd_get_text_size(struct osd_state *osd, int *out_screen_h, int *out_font_h);
void osd_get_function_sym(char *buffer, size_t buffer_size, int osd_function);
#endif /* MPLAYER_SUB_H */
diff --git a/sub/osd_dummy.c b/sub/osd_dummy.c
index f7710ae2df..0e6b802cef 100644
--- a/sub/osd_dummy.c
+++ b/sub/osd_dummy.c
@@ -28,3 +28,9 @@ void osd_set_external(struct osd_state *osd, void *id, int res_x, int res_y,
char *text)
{
}
+
+void osd_get_text_size(struct osd_state *osd, int *out_screen_h, int *out_font_h)
+{
+ *out_screen_h = 0;
+ *out_font_h = 0;
+}
diff --git a/sub/osd_libass.c b/sub/osd_libass.c
index 454d0387a4..44fcf6d269 100644
--- a/sub/osd_libass.c
+++ b/sub/osd_libass.c
@@ -219,13 +219,10 @@ static ASS_Event *add_osd_ass_event_escaped(ASS_Track *track, const char *style,
return e;
}
-static void update_osd_text(struct osd_state *osd, struct osd_object *obj)
+static ASS_Style *prepare_osd_ass(struct osd_state *osd, struct osd_object *obj)
{
struct MPOpts *opts = osd->opts;
- if (!obj->text[0])
- return;
-
create_ass_track(osd, obj, &obj->ass, 0, 0);
struct osd_style_opts font = *opts->osd_style;
@@ -236,10 +233,31 @@ static void update_osd_text(struct osd_state *osd, struct osd_object *obj)
if (!opts->osd_scale_by_window)
playresy *= 720.0 / obj->vo_res.h;
- mp_ass_set_style(get_style(&obj->ass, "OSD"), playresy, &font);
+ ASS_Style *style = get_style(&obj->ass, "OSD");
+ mp_ass_set_style(style, playresy, &font);
+ return style;
+}
+
+static void update_osd_text(struct osd_state *osd, struct osd_object *obj)
+{
+
+ if (!obj->text[0])
+ return;
+
+ prepare_osd_ass(osd, obj);
add_osd_ass_event_escaped(obj->ass.track, "OSD", obj->text);
}
+void osd_get_text_size(struct osd_state *osd, int *out_screen_h, int *out_font_h)
+{
+ pthread_mutex_lock(&osd->lock);
+ struct osd_object *obj = osd->objs[OSDTYPE_OSD];
+ ASS_Style *style = prepare_osd_ass(osd, obj);
+ *out_screen_h = obj->ass.track->PlayResY - style->MarginV;
+ *out_font_h = style->FontSize;
+ pthread_mutex_unlock(&osd->lock);
+}
+
// align: -1 .. +1
// frame: size of the containing area
// obj: size of the object that should be positioned inside the area