summaryrefslogtreecommitdiffstats
path: root/mpvcore/player/osd.c
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2013-12-17 00:53:22 +0100
committerwm4 <wm4@nowhere>2013-12-17 00:53:22 +0100
commite44911142914783c9ec717f329bd9b6a8bb9b70e (patch)
tree92bb653f7d56553ffd3bb6e5a22ffc0db91142e8 /mpvcore/player/osd.c
parent7dc7b900c622235d595337c988a0c75280084b7c (diff)
downloadmpv-e44911142914783c9ec717f329bd9b6a8bb9b70e.tar.bz2
mpv-e44911142914783c9ec717f329bd9b6a8bb9b70e.tar.xz
Move mpvcore/player/ to player/
Diffstat (limited to 'mpvcore/player/osd.c')
-rw-r--r--mpvcore/player/osd.c518
1 files changed, 0 insertions, 518 deletions
diff --git a/mpvcore/player/osd.c b/mpvcore/player/osd.c
deleted file mode 100644
index 42409b555f..0000000000
--- a/mpvcore/player/osd.c
+++ /dev/null
@@ -1,518 +0,0 @@
-/*
- * This file is part of MPlayer.
- *
- * MPlayer is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * MPlayer is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with MPlayer; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <stddef.h>
-#include <stdbool.h>
-#include <inttypes.h>
-#include <math.h>
-#include <limits.h>
-#include <assert.h>
-
-#include "config.h"
-#include "talloc.h"
-
-#include "mpvcore/mp_msg.h"
-#include "mpvcore/options.h"
-#include "mpvcore/mp_common.h"
-#include "mpvcore/m_property.h"
-#include "mpvcore/encode.h"
-
-#include "osdep/getch2.h"
-#include "osdep/timer.h"
-
-#include "demux/demux.h"
-#include "sub/osd.h"
-
-#include "mp_core.h"
-#include "command.h"
-
-#define saddf(var, ...) (*(var) = talloc_asprintf_append((*var), __VA_ARGS__))
-
-// append time in the hh:mm:ss format (plus fractions if wanted)
-static void sadd_hhmmssff(char **buf, double time, bool fractions)
-{
- char *s = mp_format_time(time, fractions);
- *buf = talloc_strdup_append(*buf, s);
- talloc_free(s);
-}
-
-static void sadd_percentage(char **buf, int percent) {
- if (percent >= 0)
- *buf = talloc_asprintf_append(*buf, " (%d%%)", percent);
-}
-
-static int get_term_width(void)
-{
- get_screen_size();
- int width = screen_width > 0 ? screen_width : 80;
-#if defined(__MINGW32__) || defined(__CYGWIN__)
- /* Windows command line is broken (MinGW's rxvt works, but we
- * should not depend on that). */
- width--;
-#endif
- return width;
-}
-
-void write_status_line(struct MPContext *mpctx, const char *line)
-{
- struct MPOpts *opts = mpctx->opts;
- if (opts->slave_mode) {
- mp_msg(MSGT_STATUSLINE, MSGL_STATUS, "%s\n", line);
- } else if (erase_to_end_of_line) {
- mp_msg(MSGT_STATUSLINE, MSGL_STATUS,
- "%s%s\r", line, erase_to_end_of_line);
- } else {
- int pos = strlen(line);
- int width = get_term_width() - pos;
- mp_msg(MSGT_STATUSLINE, MSGL_STATUS, "%s%*s\r", line, width, "");
- }
-}
-
-void print_status(struct MPContext *mpctx)
-{
- struct MPOpts *opts = mpctx->opts;
-
- update_window_title(mpctx, false);
-
- if (opts->quiet)
- return;
-
- if (opts->status_msg) {
- char *r = mp_property_expand_string(mpctx, opts->status_msg);
- write_status_line(mpctx, r);
- talloc_free(r);
- return;
- }
-
- char *line = NULL;
-
- // Playback status
- if (mpctx->paused_for_cache && !opts->pause) {
- saddf(&line, "(Buffering) ");
- } else if (mpctx->paused) {
- saddf(&line, "(Paused) ");
- }
-
- if (mpctx->d_audio)
- saddf(&line, "A");
- if (mpctx->d_video)
- saddf(&line, "V");
- saddf(&line, ": ");
-
- // Playback position
- double cur = get_current_time(mpctx);
- sadd_hhmmssff(&line, cur, mpctx->opts->osd_fractions);
-
- double len = get_time_length(mpctx);
- if (len >= 0) {
- saddf(&line, " / ");
- sadd_hhmmssff(&line, len, mpctx->opts->osd_fractions);
- }
-
- sadd_percentage(&line, get_percent_pos(mpctx));
-
- // other
- if (opts->playback_speed != 1)
- saddf(&line, " x%4.2f", opts->playback_speed);
-
- // A-V sync
- if (mpctx->d_audio && mpctx->d_video && mpctx->sync_audio_to_video) {
- if (mpctx->last_av_difference != MP_NOPTS_VALUE)
- saddf(&line, " A-V:%7.3f", mpctx->last_av_difference);
- else
- saddf(&line, " A-V: ???");
- if (fabs(mpctx->total_avsync_change) > 0.05)
- saddf(&line, " ct:%7.3f", mpctx->total_avsync_change);
- }
-
-#if HAVE_ENCODING
- double position = get_current_pos_ratio(mpctx, true);
- char lavcbuf[80];
- if (encode_lavc_getstatus(mpctx->encode_lavc_ctx, lavcbuf, sizeof(lavcbuf),
- position) >= 0)
- {
- // encoding stats
- saddf(&line, " %s", lavcbuf);
- } else
-#endif
- {
- // VO stats
- if (mpctx->d_video && mpctx->drop_frame_cnt)
- saddf(&line, " Late: %d", mpctx->drop_frame_cnt);
- }
-
- int cache = mp_get_cache_percent(mpctx);
- if (cache >= 0)
- saddf(&line, " Cache: %d%%", cache);
-
- // end
- write_status_line(mpctx, line);
- talloc_free(line);
-}
-
-typedef struct mp_osd_msg mp_osd_msg_t;
-struct mp_osd_msg {
- /// Previous message on the stack.
- mp_osd_msg_t *prev;
- /// Message text.
- char *msg;
- int id, level, started;
- /// Display duration in seconds.
- double time;
- // Show full OSD for duration of message instead of msg
- // (osd_show_progression command)
- bool show_position;
-};
-
-// time is in ms
-static mp_osd_msg_t *add_osd_msg(struct MPContext *mpctx, int id, int level,
- int time)
-{
- rm_osd_msg(mpctx, id);
- mp_osd_msg_t *msg = talloc_struct(mpctx, mp_osd_msg_t, {
- .prev = mpctx->osd_msg_stack,
- .msg = "",
- .id = id,
- .level = level,
- .time = time / 1000.0,
- });
- mpctx->osd_msg_stack = msg;
- return msg;
-}
-
-static void set_osd_msg_va(struct MPContext *mpctx, int id, int level, int time,
- const char *fmt, va_list ap)
-{
- if (level == OSD_LEVEL_INVISIBLE)
- return;
- mp_osd_msg_t *msg = add_osd_msg(mpctx, id, level, time);
- msg->msg = talloc_vasprintf(msg, fmt, ap);
-}
-
-void set_osd_msg(struct MPContext *mpctx, int id, int level, int time,
- const char *fmt, ...)
-{
- va_list ap;
- va_start(ap, fmt);
- set_osd_msg_va(mpctx, id, level, time, fmt, ap);
- va_end(ap);
-}
-
-/**
- * \brief Remove a message from the OSD stack
- *
- * This function can be used to get rid of a message right away.
- *
- */
-
-void rm_osd_msg(struct MPContext *mpctx, int id)
-{
- mp_osd_msg_t *msg, *last = NULL;
-
- // Search for the msg
- for (msg = mpctx->osd_msg_stack; msg && msg->id != id;
- last = msg, msg = msg->prev) ;
- if (!msg)
- return;
-
- // Detach it from the stack and free it
- if (last)
- last->prev = msg->prev;
- else
- mpctx->osd_msg_stack = msg->prev;
- talloc_free(msg);
-}
-
-/**
- * \brief Get the current message from the OSD stack.
- *
- * This function decrements the message timer and destroys the old ones.
- * The message that should be displayed is returned (if any).
- *
- */
-
-static mp_osd_msg_t *get_osd_msg(struct MPContext *mpctx)
-{
- struct MPOpts *opts = mpctx->opts;
- mp_osd_msg_t *msg, *prev, *last = NULL;
- double now = mp_time_sec();
- double diff;
- char hidden_dec_done = 0;
-
- if (mpctx->osd_visible && now >= mpctx->osd_visible) {
- mpctx->osd_visible = 0;
- mpctx->osd->progbar_type = -1; // disable
- osd_changed(mpctx->osd, OSDTYPE_PROGBAR);
- }
- if (mpctx->osd_function_visible && now >= mpctx->osd_function_visible) {
- mpctx->osd_function_visible = 0;
- mpctx->osd_function = 0;
- }
-
- if (!mpctx->osd_last_update)
- mpctx->osd_last_update = now;
- diff = now >= mpctx->osd_last_update ? now - mpctx->osd_last_update : 0;
-
- mpctx->osd_last_update = now;
-
- // Look for the first message in the stack with high enough level.
- for (msg = mpctx->osd_msg_stack; msg; last = msg, msg = prev) {
- prev = msg->prev;
- if (msg->level > opts->osd_level && hidden_dec_done)
- continue;
- // The message has a high enough level or it is the first hidden one
- // in both cases we decrement the timer or kill it.
- if (!msg->started || msg->time > diff) {
- if (msg->started)
- msg->time -= diff;
- else
- msg->started = 1;
- // display it
- if (msg->level <= opts->osd_level)
- return msg;
- hidden_dec_done = 1;
- continue;
- }
- // kill the message
- talloc_free(msg);
- if (last) {
- last->prev = prev;
- msg = last;
- } else {
- mpctx->osd_msg_stack = prev;
- msg = NULL;
- }
- }
- // Nothing found
- return NULL;
-}
-
-// type: mp_osd_font_codepoints, ASCII, or OSD_BAR_*
-// name: fallback for terminal OSD
-void set_osd_bar(struct MPContext *mpctx, int type, const char *name,
- double min, double max, double val)
-{
- struct MPOpts *opts = mpctx->opts;
- if (opts->osd_level < 1 || !opts->osd_bar_visible)
- return;
-
- if (mpctx->video_out && opts->term_osd != 1) {
- mpctx->osd_visible = mp_time_sec() + opts->osd_duration / 1000.0;
- mpctx->osd->progbar_type = type;
- mpctx->osd->progbar_value = (val - min) / (max - min);
- mpctx->osd->progbar_num_stops = 0;
- osd_changed(mpctx->osd, OSDTYPE_PROGBAR);
- return;
- }
-
- set_osd_msg(mpctx, OSD_MSG_BAR, 1, opts->osd_duration, "%s: %d %%",
- name, ROUND(100 * (val - min) / (max - min)));
-}
-
-// Update a currently displayed bar of the same type, without resetting the
-// timer.
-static void update_osd_bar(struct MPContext *mpctx, int type,
- double min, double max, double val)
-{
- if (mpctx->osd->progbar_type == type) {
- float new_value = (val - min) / (max - min);
- if (new_value != mpctx->osd->progbar_value) {
- mpctx->osd->progbar_value = new_value;
- osd_changed(mpctx->osd, OSDTYPE_PROGBAR);
- }
- }
-}
-
-static void set_osd_bar_chapters(struct MPContext *mpctx, int type)
-{
- struct osd_state *osd = mpctx->osd;
- osd->progbar_num_stops = 0;
- if (osd->progbar_type == type) {
- double len = get_time_length(mpctx);
- if (len > 0) {
- int num = get_chapter_count(mpctx);
- for (int n = 0; n < num; n++) {
- double time = chapter_start_time(mpctx, n);
- if (time >= 0) {
- float pos = time / len;
- MP_TARRAY_APPEND(osd, osd->progbar_stops,
- osd->progbar_num_stops, pos);
- }
- }
- }
- }
-}
-
-// osd_function is the symbol appearing in the video status, such as OSD_PLAY
-void set_osd_function(struct MPContext *mpctx, int osd_function)
-{
- struct MPOpts *opts = mpctx->opts;
-
- mpctx->osd_function = osd_function;
- mpctx->osd_function_visible = mp_time_sec() + opts->osd_duration / 1000.0;
-}
-
-/**
- * \brief Display text subtitles on the OSD
- */
-void set_osd_subtitle(struct MPContext *mpctx, const char *text)
-{
- if (!text)
- text = "";
- if (strcmp(mpctx->osd->sub_text, text) != 0) {
- osd_set_sub(mpctx->osd, text);
- if (!mpctx->video_out) {
- rm_osd_msg(mpctx, OSD_MSG_SUB_BASE);
- if (text && text[0])
- set_osd_msg(mpctx, OSD_MSG_SUB_BASE, 1, INT_MAX, "%s", text);
- }
- }
- if (!text[0])
- rm_osd_msg(mpctx, OSD_MSG_SUB_BASE);
-}
-
-// sym == mpctx->osd_function
-static void saddf_osd_function_sym(char **buffer, int sym)
-{
- char temp[10];
- osd_get_function_sym(temp, sizeof(temp), sym);
- saddf(buffer, "%s ", temp);
-}
-
-static void sadd_osd_status(char **buffer, struct MPContext *mpctx, bool full)
-{
- bool fractions = mpctx->opts->osd_fractions;
- int sym = mpctx->osd_function;
- if (!sym) {
- if (mpctx->paused_for_cache && !mpctx->opts->pause) {
- sym = OSD_CLOCK;
- } else if (mpctx->paused || mpctx->step_frames) {
- sym = OSD_PAUSE;
- } else {
- sym = OSD_PLAY;
- }
- }
- saddf_osd_function_sym(buffer, sym);
- char *custom_msg = mpctx->opts->osd_status_msg;
- if (custom_msg && full) {
- char *text = mp_property_expand_string(mpctx, custom_msg);
- *buffer = talloc_strdup_append(*buffer, text);
- talloc_free(text);
- } else {
- sadd_hhmmssff(buffer, get_current_time(mpctx), fractions);
- if (full) {
- saddf(buffer, " / ");
- sadd_hhmmssff(buffer, get_time_length(mpctx), fractions);
- sadd_percentage(buffer, get_percent_pos(mpctx));
- int cache = mp_get_cache_percent(mpctx);
- if (cache >= 0)
- saddf(buffer, " Cache: %d%%", cache);
- }
- }
-}
-
-// OSD messages initated by seeking commands are added lazily with this
-// function, because multiple successive seek commands can be coalesced.
-static void add_seek_osd_messages(struct MPContext *mpctx)
-{
- if (mpctx->add_osd_seek_info & OSD_SEEK_INFO_BAR) {
- double pos = get_current_pos_ratio(mpctx, false);
- set_osd_bar(mpctx, OSD_BAR_SEEK, "Position", 0, 1, MPCLAMP(pos, 0, 1));
- set_osd_bar_chapters(mpctx, OSD_BAR_SEEK);
- }
- if (mpctx->add_osd_seek_info & OSD_SEEK_INFO_TEXT) {
- mp_osd_msg_t *msg = add_osd_msg(mpctx, OSD_MSG_TEXT, 1,
- mpctx->opts->osd_duration);
- msg->show_position = true;
- }
- if (mpctx->add_osd_seek_info & OSD_SEEK_INFO_CHAPTER_TEXT) {
- char *chapter = chapter_display_name(mpctx, get_current_chapter(mpctx));
- set_osd_msg(mpctx, OSD_MSG_TEXT, 1, mpctx->opts->osd_duration,
- "Chapter: %s", chapter);
- talloc_free(chapter);
- }
- if ((mpctx->add_osd_seek_info & OSD_SEEK_INFO_EDITION)
- && mpctx->master_demuxer)
- {
- set_osd_msg(mpctx, OSD_MSG_TEXT, 1, mpctx->opts->osd_duration,
- "Playing edition %d of %d.",
- mpctx->master_demuxer->edition + 1,
- mpctx->master_demuxer->num_editions);
- }
- mpctx->add_osd_seek_info = 0;
-}
-
-/**
- * \brief Update the OSD message line.
- *
- * This function displays the current message on the vo OSD or on the term.
- * If the stack is empty and the OSD level is high enough the timer
- * is displayed (only on the vo OSD).
- *
- */
-
-void update_osd_msg(struct MPContext *mpctx)
-{
- struct MPOpts *opts = mpctx->opts;
- struct osd_state *osd = mpctx->osd;
-
- add_seek_osd_messages(mpctx);
- double pos = get_current_pos_ratio(mpctx, false);
- update_osd_bar(mpctx, OSD_BAR_SEEK, 0, 1, MPCLAMP(pos, 0, 1));
-
- // Look if we have a msg
- mp_osd_msg_t *msg = get_osd_msg(mpctx);
- if (msg && !msg->show_position) {
- if (mpctx->video_out && opts->term_osd != 1) {
- osd_set_text(osd, msg->msg);
- } else if (opts->term_osd) {
- if (strcmp(mpctx->terminal_osd_text, msg->msg)) {
- talloc_free(mpctx->terminal_osd_text);
- mpctx->terminal_osd_text = talloc_strdup(mpctx, msg->msg);
- // Multi-line message => clear what will be the second line
- write_status_line(mpctx, "");
- mp_msg(MSGT_CPLAYER, MSGL_STATUS, "%s%s\n", opts->term_osd_esc,
- mpctx->terminal_osd_text);
- print_status(mpctx);
- }
- }
- return;
- }
-
- int osd_level = opts->osd_level;
- if (msg && msg->show_position)
- osd_level = 3;
-
- if (mpctx->video_out && opts->term_osd != 1) {
- // fallback on the timer
- char *text = NULL;
-
- if (osd_level >= 2)
- sadd_osd_status(&text, mpctx, osd_level == 3);
-
- osd_set_text(osd, text);
- talloc_free(text);
- return;
- }
-
- // Clear the term osd line
- if (opts->term_osd && mpctx->terminal_osd_text[0]) {
- mpctx->terminal_osd_text[0] = '\0';
- mp_msg(MSGT_CPLAYER, MSGL_STATUS, "%s\n", opts->term_osd_esc);
- }
-}