diff options
author | wm4 <wm4@nowhere> | 2013-12-17 00:53:22 +0100 |
---|---|---|
committer | wm4 <wm4@nowhere> | 2013-12-17 00:53:22 +0100 |
commit | e44911142914783c9ec717f329bd9b6a8bb9b70e (patch) | |
tree | 92bb653f7d56553ffd3bb6e5a22ffc0db91142e8 /mpvcore/player/osd.c | |
parent | 7dc7b900c622235d595337c988a0c75280084b7c (diff) | |
download | mpv-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.c | 518 |
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); - } -} |