diff options
Diffstat (limited to 'common')
-rw-r--r-- | common/av_common.c | 9 | ||||
-rw-r--r-- | common/av_common.h | 1 | ||||
-rw-r--r-- | common/av_log.c | 33 | ||||
-rw-r--r-- | common/common.c | 19 | ||||
-rw-r--r-- | common/common.h | 6 | ||||
-rw-r--r-- | common/encode_lavc.c | 6 | ||||
-rw-r--r-- | common/meson.build | 5 | ||||
-rw-r--r-- | common/msg.c | 168 | ||||
-rw-r--r-- | common/msg_control.h | 3 | ||||
-rw-r--r-- | common/playlist.c | 25 | ||||
-rw-r--r-- | common/playlist.h | 8 | ||||
-rw-r--r-- | common/version.h.in | 2 |
12 files changed, 198 insertions, 87 deletions
diff --git a/common/av_common.c b/common/av_common.c index 5d07349..e5733c3 100644 --- a/common/av_common.c +++ b/common/av_common.c @@ -402,3 +402,12 @@ void mp_free_av_packet(AVPacket **pkt) } av_packet_free(pkt); } + +void mp_codec_info_from_av(const AVCodecContext *avctx, struct mp_codec_params *c) +{ + c->codec_profile = av_get_profile_name(avctx->codec, avctx->profile); + if (!c->codec_profile) + c->codec_profile = avcodec_profile_name(avctx->codec_id, avctx->profile); + c->codec = avctx->codec_descriptor->name; + c->codec_desc = avctx->codec_descriptor->long_name; +} diff --git a/common/av_common.h b/common/av_common.h index 1f05e14..c584085 100644 --- a/common/av_common.h +++ b/common/av_common.h @@ -50,5 +50,6 @@ void mp_avdict_print_unset(struct mp_log *log, int msgl, struct AVDictionary *d) int mp_set_avopts(struct mp_log *log, void *avobj, char **kv); int mp_set_avopts_pos(struct mp_log *log, void *avobj, void *posargs, char **kv); void mp_free_av_packet(AVPacket **pkt); +void mp_codec_info_from_av(const AVCodecContext *avctx, struct mp_codec_params *c); #endif diff --git a/common/av_log.c b/common/av_log.c index b6bad04..54b78a6 100644 --- a/common/av_log.c +++ b/common/av_log.c @@ -28,6 +28,7 @@ #include "common/global.h" #include "common/msg.h" #include "config.h" +#include "misc/bstr.h" #include "osdep/threads.h" #include <libavutil/avutil.h> @@ -55,6 +56,7 @@ static mp_static_mutex log_lock = MP_STATIC_MUTEX_INITIALIZER; static struct mpv_global *log_mpv_instance; static struct mp_log *log_root, *log_decaudio, *log_decvideo, *log_demuxer; static bool log_print_prefix = true; +static bstr log_buffer; static int av_log_level_to_mp_level(int av_level) { @@ -80,7 +82,7 @@ static struct mp_log *get_av_log(void *ptr) if (!avc) { mp_warn(log_root, "av_log callback called with bad parameters (NULL AVClass).\n" - "This is a bug in one of Libav/FFmpeg libraries used.\n"); + "This is a bug in one of FFmpeg libraries used.\n"); return log_root; } @@ -106,6 +108,11 @@ static struct mp_log *get_av_log(void *ptr) return log_root; } +static const char *avclass_item_name(void *obj, const AVClass *avc) +{ + return (avc->item_name ? avc->item_name : av_default_item_name)(obj); +} + static void mp_msg_av_log_callback(void *ptr, int level, const char *fmt, va_list vl) { @@ -125,19 +132,20 @@ static void mp_msg_av_log_callback(void *ptr, int level, const char *fmt, struct mp_log *log = get_av_log(ptr); if (mp_msg_test(log, mp_level)) { - char buffer[4096] = ""; - int pos = 0; - const char *prefix = avc ? avc->item_name(ptr) : NULL; - if (log_print_prefix && prefix) - pos = snprintf(buffer, sizeof(buffer), "%s: ", prefix); - log_print_prefix = fmt[strlen(fmt) - 1] == '\n'; - - pos = MPMIN(MPMAX(pos, 0), sizeof(buffer)); - vsnprintf(buffer + pos, sizeof(buffer) - pos, fmt, vl); - - mp_msg(log, mp_level, "%s", buffer); + log_buffer.len = 0; + bstr_xappend_vasprintf(log_root, &log_buffer, fmt, vl); + if (!log_buffer.len) + goto done; + const char *prefix = avc ? avclass_item_name(ptr, avc) : NULL; + if (log_print_prefix && prefix) { + mp_msg(log, mp_level, "%s: %.*s", prefix, BSTR_P(log_buffer)); + } else { + mp_msg(log, mp_level, "%.*s", BSTR_P(log_buffer)); + } + log_print_prefix = log_buffer.start[log_buffer.len - 1] == '\n'; } +done: mp_mutex_unlock(&log_lock); } @@ -150,6 +158,7 @@ void init_libav(struct mpv_global *global) log_decaudio = mp_log_new(log_root, log_root, "audio"); log_decvideo = mp_log_new(log_root, log_root, "video"); log_demuxer = mp_log_new(log_root, log_root, "demuxer"); + log_buffer = (bstr){0}; av_log_set_callback(mp_msg_av_log_callback); } mp_mutex_unlock(&log_lock); diff --git a/common/common.c b/common/common.c index 9f8230f..7089a66 100644 --- a/common/common.c +++ b/common/common.c @@ -94,6 +94,25 @@ char *mp_format_time(double time, bool fractions) return mp_format_time_fmt(fractions ? "%H:%M:%S.%T" : "%H:%M:%S", time); } +char *mp_format_double(void *talloc_ctx, double val, int precision, + bool plus_sign, bool percent_sign, bool trim) +{ + bstr str = {0}; + const char *fmt = plus_sign ? "%+.*f" : "%.*f"; + bstr_xappend_asprintf(talloc_ctx, &str, fmt, precision, val); + size_t pos = str.len; + if (trim) { + while (--pos && str.start[pos] == '0') + str.len--; + if (str.start[pos] == '.') + str.len--; + } + if (percent_sign) + bstr_xappend(talloc_ctx, &str, bstr0("%")); + str.start[str.len] = '\0'; + return str.start; +} + // Set rc to the union of rc and rc2 void mp_rect_union(struct mp_rect *rc, const struct mp_rect *rc2) { diff --git a/common/common.h b/common/common.h index ccdd94b..cd9bea9 100644 --- a/common/common.h +++ b/common/common.h @@ -99,6 +99,12 @@ extern const char mpv_copyright[]; char *mp_format_time(double time, bool fractions); char *mp_format_time_fmt(const char *fmt, double time); +// Formats a double value to a string with the specified precision. +// Trailing zeros (and the dot) can be trimmed. +// Optionally, a plus sign and a percent sign can be added. +char *mp_format_double(void *talloc_ctx, double val, int precision, + bool plus_sign, bool percent_sign, bool trim); + struct mp_rect { int x0, y0; int x1, y1; diff --git a/common/encode_lavc.c b/common/encode_lavc.c index 898545d..a250f9c 100644 --- a/common/encode_lavc.c +++ b/common/encode_lavc.c @@ -870,8 +870,8 @@ bool encoder_init_codec_and_muxer(struct encoder_context *p, " ********************************************\n\n" "This means the output file may be broken or bad.\n" "Possible reasons, problems, workarounds:\n" - "- Codec implementation in ffmpeg/libav is not finished yet.\n" - " Try updating ffmpeg or libav.\n" + "- Codec implementation in ffmpeg is not finished yet.\n" + " Try updating ffmpeg.\n" "- Bad picture quality, blocks, blurriness.\n" " Experiment with codec settings to maybe still get the\n" " desired quality output at the expense of bitrate.\n" @@ -906,7 +906,7 @@ bool encoder_init_codec_and_muxer(struct encoder_context *p, return true; fail: - avcodec_close(p->encoder); + avcodec_free_context(&p->encoder); return false; } diff --git a/common/meson.build b/common/meson.build index 4bca5ea..202880f 100644 --- a/common/meson.build +++ b/common/meson.build @@ -1,5 +1,8 @@ version_h = vcs_tag( - command: ['git', 'describe', '--always', '--tags', '--dirty'], + command: ['git', + '--git-dir=' + join_paths(source_root, '.git'), + '--work-tree=' + source_root, + 'describe', '--always', '--tags', '--dirty'], input: 'version.h.in', output: 'version.h', replace_string: '@VERSION@', diff --git a/common/msg.c b/common/msg.c index b14bd5a..840f2ab 100644 --- a/common/msg.c +++ b/common/msg.c @@ -42,10 +42,12 @@ #include "msg.h" #include "msg_control.h" -// log buffer size (lines) for terminal level and logfile level -#define TERM_BUF 100 +// log buffer size (lines) logfile level #define FILE_BUF 100 +// lines to accumulate before any client requests the terminal loglevel +#define EARLY_TERM_BUF 100 + // logfile lines to accumulate during init before we know the log file name. // thousands of logfile lines during init can happen (especially with many // scripts, big config, etc), so we set 5000. If it cycles and messages are @@ -214,9 +216,9 @@ static void prepare_prefix(struct mp_log_root *root, bstr *out, int lev, int ter // Set cursor state if (new_lines && !root->status_lines) { - bstr_xappend(root, out, bstr0("\033[?25l")); + bstr_xappend(root, out, bstr0(TERM_ESC_HIDE_CURSOR)); } else if (!new_lines && root->status_lines) { - bstr_xappend(root, out, bstr0("\033[?25h")); + bstr_xappend(root, out, bstr0(TERM_ESC_RESTORE_CURSOR)); } int line_skip = 0; @@ -226,41 +228,49 @@ static void prepare_prefix(struct mp_log_root *root, bstr *out, int lev, int ter bstr up_clear = bstr0("\033[A\033[K"); for (int i = 1; i < root->status_lines; ++i) bstr_xappend(root, out, up_clear); - // Reposition cursor after last message - line_skip = (new_lines ? new_lines : root->blank_lines) - root->status_lines; - line_skip = MPMIN(root->blank_lines - root->status_lines, line_skip); - if (line_skip) - bstr_xappend_asprintf(root, out, "\033[%dA", line_skip); - } else if (new_lines) { - line_skip = new_lines - root->blank_lines; + assert(root->status_lines > 0 && root->blank_lines >= root->status_lines); + line_skip = root->blank_lines - root->status_lines; } - if (line_skip < 0) { - // Reposition cursor to keep status line at the same line - line_skip = MPMIN(root->blank_lines, -line_skip); - if (line_skip) - bstr_xappend_asprintf(root, out, "\033[%dB", line_skip); - } + if (new_lines) + line_skip -= MPMAX(0, root->blank_lines - new_lines); + + if (line_skip) + bstr_xappend_asprintf(root, out, line_skip > 0 ? "\033[%dA" : "\033[%dB", abs(line_skip)); root->blank_lines = MPMAX(0, root->blank_lines - term_lines); root->status_lines = new_lines; root->blank_lines += root->status_lines; } -void mp_msg_flush_status_line(struct mp_log *log) +void mp_msg_flush_status_line(struct mp_log *log, bool clear) { - if (log->root) { - mp_mutex_lock(&log->root->lock); - if (log->root->status_lines) { - bstr term_msg = (bstr){0}; - prepare_prefix(log->root, &term_msg, MSGL_STATUS, 0); - if (term_msg.len) { - fprintf(stderr, "%.*s", BSTR_P(term_msg)); - talloc_free(term_msg.start); - } - } - mp_mutex_unlock(&log->root->lock); + if (!log->root) + return; + + mp_mutex_lock(&log->root->lock); + if (!log->root->status_lines) + goto done; + + if (!clear) { + if (log->root->isatty[STDERR_FILENO]) + fprintf(stderr, TERM_ESC_RESTORE_CURSOR); + fprintf(stderr, "\n"); + log->root->blank_lines = 0; + log->root->status_lines = 0; + goto done; } + + bstr term_msg = {0}; + prepare_prefix(log->root, &term_msg, MSGL_STATUS, 0); + if (term_msg.len) { + fprintf(stderr, "%.*s", BSTR_P(term_msg)); + talloc_free(term_msg.start); + } + +done: + log->root->status_line.len = 0; + mp_mutex_unlock(&log->root->lock); } void mp_msg_set_term_title(struct mp_log *log, const char *title) @@ -268,7 +278,7 @@ void mp_msg_set_term_title(struct mp_log *log, const char *title) if (log->root && title) { // Lock because printf to terminal is not necessarily atomic. mp_mutex_lock(&log->root->lock); - fprintf(stderr, "\e]0;%s\007", title); + fprintf(stderr, "\033]0;%s\007", title); mp_mutex_unlock(&log->root->lock); } } @@ -284,15 +294,18 @@ bool mp_msg_has_status_line(struct mpv_global *global) static void set_term_color(void *talloc_ctx, bstr *text, int c) { - return c == -1 ? bstr_xappend(talloc_ctx, text, bstr0("\033[0m")) - : bstr_xappend_asprintf(talloc_ctx, text, - "\033[%d;3%dm", c >> 3, c & 7); + if (c == -1) { + bstr_xappend(talloc_ctx, text, bstr0("\033[0m")); + return; + } + + bstr_xappend_asprintf(talloc_ctx, text, "\033[%d;3%dm", c >> 3, c & 7); } static void set_msg_color(void *talloc_ctx, bstr *text, int lev) { static const int v_colors[] = {9, 1, 3, -1, -1, 2, 8, 8, 8, -1}; - return set_term_color(talloc_ctx, text, v_colors[lev]); + set_term_color(talloc_ctx, text, v_colors[lev]); } static void pretty_print_module(struct mp_log_root *root, bstr *text, @@ -325,31 +338,30 @@ static bool test_terminal_level(struct mp_log *log, int lev) } // This is very basic way to infer needed width for a string. -static int term_disp_width(bstr str, size_t start, size_t end) +static int term_disp_width(bstr str) { int width = 0; - bool escape = false; - const char *line = str.start; - for (size_t i = start; i < end && i < str.len; ++i) { - if (escape) { - escape = !(line[i] >= '@' && line[i] <= '~'); + while (str.len) { + if (bstr_eatstart0(&str, "\033[")) { + while (str.len && !((*str.start >= '@' && *str.start <= '~') || *str.start == 'm')) + str = bstr_cut(str, 1); + str = bstr_cut(str, 1); continue; } - if (line[i] == '\033' && line[i + 1] == '[') { - escape = true; - ++i; - continue; - } + bstr code = bstr_split_utf8(str, &str); + if (code.len == 0) + return 0; - if (line[i] == '\n') + if (code.len == 1 && *code.start == '\n') continue; + // Only single-width characters are supported width++; // Assume that everything before \r should be discarded for simplicity - if (line[i] == '\r') + if (code.len == 1 && *code.start == '\r') width = 0; } @@ -378,7 +390,7 @@ static void append_terminal_line(struct mp_log *log, int lev, bstr_xappend(root, term_msg, text); *line_w = root->isatty[term_msg_fileno(root, lev)] - ? term_disp_width(*term_msg, start, term_msg->len) : 0; + ? term_disp_width(bstr_splice(*term_msg, start, term_msg->len)) : 0; } static struct mp_log_buffer_entry *log_buffer_read(struct mp_log_buffer *buffer) @@ -486,9 +498,9 @@ static void write_term_msg(struct mp_log *log, int lev, bstr text, bstr *out) write_msg_to_buffers(log, lev, line); } - if (lev == MSGL_STATUS && print_term) { + if (lev == MSGL_STATUS) { int line_w = 0; - if (str.len) + if (str.len && print_term) append_terminal_line(log, lev, str, &root->term_msg_tmp, &line_w); term_msg_lines += !term_w ? (str.len ? 1 : 0) : (line_w + term_w - 1) / term_w; @@ -551,12 +563,9 @@ void mp_msg_va(struct mp_log *log, int lev, const char *format, va_list va) int fileno = term_msg_fileno(root, lev); FILE *stream = fileno == STDERR_FILENO ? stderr : stdout; if (root->term_msg.len) { - if (root->term_status_msg.len) { - fprintf(stream, "%.*s%.*s", BSTR_P(root->term_msg), - BSTR_P(root->term_status_msg)); - } else { - fprintf(stream, "%.*s", BSTR_P(root->term_msg)); - } + fwrite(root->term_msg.start, root->term_msg.len, 1, stream); + if (root->term_status_msg.len) + fwrite(root->term_status_msg.start, root->term_status_msg.len, 1, stream); fflush(stream); } } @@ -738,6 +747,10 @@ void mp_msg_update_msglevels(struct mpv_global *global, struct MPOpts *opts) root->module = opts->msg_module; root->use_terminal = opts->use_terminal; root->show_time = opts->msg_time; + + if (root->really_quiet) + root->status_lines = 0; + for (int i = STDOUT_FILENO; i <= STDERR_FILENO && root->use_terminal; ++i) { root->isatty[i] = isatty(i); root->color[i] = opts->msg_color && root->isatty[i]; @@ -836,7 +849,9 @@ bool mp_msg_has_log_file(struct mpv_global *global) void mp_msg_uninit(struct mpv_global *global) { struct mp_log_root *root = global->log->root; - mp_msg_flush_status_line(global->log); + mp_msg_flush_status_line(global->log, true); + if (root->really_quiet && root->isatty[STDERR_FILENO]) + fprintf(stderr, TERM_ESC_RESTORE_CURSOR); terminate_log_file_thread(root); mp_msg_log_buffer_destroy(root->early_buffer); mp_msg_log_buffer_destroy(root->early_filebuffer); @@ -903,7 +918,7 @@ void mp_msg_set_early_logging(struct mpv_global *global, bool enable) struct mp_log_root *root = global->log->root; mp_msg_set_early_logging_raw(global, enable, &root->early_buffer, - TERM_BUF, MP_LOG_BUFFER_MSGL_TERM); + EARLY_TERM_BUF, MP_LOG_BUFFER_MSGL_TERM); // normally MSGL_LOGFILE buffer gets a write thread, but not the early buf mp_msg_set_early_logging_raw(global, enable, &root->early_filebuffer, @@ -920,8 +935,6 @@ struct mp_log_buffer *mp_msg_log_buffer_new(struct mpv_global *global, mp_mutex_lock(&root->lock); if (level == MP_LOG_BUFFER_MSGL_TERM) { - size = TERM_BUF; - // The first thing which creates a terminal-level log buffer gets the // early log buffer, if it exists. This is supposed to enable a script // to grab log messages from before it was initialized. It's OK that @@ -929,6 +942,7 @@ struct mp_log_buffer *mp_msg_log_buffer_new(struct mpv_global *global, if (root->early_buffer) { struct mp_log_buffer *buffer = root->early_buffer; root->early_buffer = NULL; + mp_msg_log_buffer_resize(buffer, size); buffer->wakeup_cb = wakeup_cb; buffer->wakeup_cb_ctx = wakeup_cb_ctx; mp_mutex_unlock(&root->lock); @@ -958,6 +972,40 @@ struct mp_log_buffer *mp_msg_log_buffer_new(struct mpv_global *global, return buffer; } +void mp_msg_log_buffer_resize(struct mp_log_buffer *buffer, int size) +{ + mp_mutex_lock(&buffer->lock); + + assert(size > 0); + if (buffer->capacity < size && + buffer->entry0 + buffer->num_entries <= buffer->capacity) { + // shortcut if buffer doesn't wrap + buffer->entries = talloc_realloc(buffer, buffer->entries, + struct mp_log_buffer_entry *, size); + } else if (buffer->capacity != size) { + struct mp_log_buffer_entry **entries = + talloc_array(buffer, struct mp_log_buffer_entry *, size); + int num_entries = 0; + for (int i = buffer->num_entries - 1; i >= 0; i--) { + int entry = (buffer->entry0 + i) % buffer->num_entries; + struct mp_log_buffer_entry *res = buffer->entries[entry]; + if (num_entries < size) { + entries[num_entries++] = res; + } else { + talloc_free(res); + buffer->dropped += 1; + } + } + talloc_free(buffer->entries); + buffer->entries = entries; + buffer->entry0 = 0; + buffer->num_entries = num_entries; + } + buffer->capacity = size; + + mp_mutex_unlock(&buffer->lock); +} + void mp_msg_log_buffer_set_silent(struct mp_log_buffer *buffer, bool silent) { mp_mutex_lock(&buffer->lock); diff --git a/common/msg_control.h b/common/msg_control.h index e4da59e..ee02eb2 100644 --- a/common/msg_control.h +++ b/common/msg_control.h @@ -14,7 +14,7 @@ bool mp_msg_has_status_line(struct mpv_global *global); bool mp_msg_has_log_file(struct mpv_global *global); void mp_msg_set_early_logging(struct mpv_global *global, bool enable); -void mp_msg_flush_status_line(struct mp_log *log); +void mp_msg_flush_status_line(struct mp_log *log, bool clear); void mp_msg_set_term_title(struct mp_log *log, const char *title); struct mp_log_buffer_entry { @@ -35,6 +35,7 @@ struct mp_log_buffer *mp_msg_log_buffer_new(struct mpv_global *global, void *wakeup_cb_ctx); void mp_msg_log_buffer_destroy(struct mp_log_buffer *buffer); struct mp_log_buffer_entry *mp_msg_log_buffer_read(struct mp_log_buffer *buffer); +void mp_msg_log_buffer_resize(struct mp_log_buffer *buffer, int size); void mp_msg_log_buffer_set_silent(struct mp_log_buffer *buffer, bool silent); int mp_msg_find_level(const char *s); diff --git a/common/playlist.c b/common/playlist.c index c1636bc..39c49a5 100644 --- a/common/playlist.c +++ b/common/playlist.c @@ -60,13 +60,23 @@ static void playlist_update_indexes(struct playlist *pl, int start, int end) pl->entries[n]->pl_index = n; } -void playlist_add(struct playlist *pl, struct playlist_entry *add) +// Inserts the entry so that it takes "at"'s place, shifting "at" and all +// further entires to the right (or append to end, if at==NULL). +void playlist_insert_at(struct playlist *pl, struct playlist_entry *add, + struct playlist_entry *at) { assert(add->filename); - MP_TARRAY_APPEND(pl, pl->entries, pl->num_entries, add); + assert(!at || at->pl == pl); + + int index = at ? at->pl_index : pl->num_entries; + MP_TARRAY_INSERT_AT(pl, pl->entries, pl->num_entries, index, add); + add->pl = pl; - add->pl_index = pl->num_entries - 1; + add->pl_index = index; add->id = ++pl->id_alloc; + + playlist_update_indexes(pl, index, pl->num_entries); + talloc_steal(pl, add); } @@ -137,9 +147,9 @@ void playlist_move(struct playlist *pl, struct playlist_entry *entry, MPMAX(index + 1, old_index + 1)); } -void playlist_add_file(struct playlist *pl, const char *filename) +void playlist_append_file(struct playlist *pl, const char *filename) { - playlist_add(pl, playlist_entry_new(filename)); + playlist_insert_at(pl, playlist_entry_new(filename), NULL); } void playlist_populate_playlist_path(struct playlist *pl, const char *path) @@ -302,8 +312,8 @@ void playlist_set_stream_flags(struct playlist *pl, int flags) pl->entries[n]->stream_flags = flags; } -static int64_t playlist_transfer_entries_to(struct playlist *pl, int dst_index, - struct playlist *source_pl) +int64_t playlist_transfer_entries_to(struct playlist *pl, int dst_index, + struct playlist *source_pl) { assert(pl != source_pl); struct playlist_entry *first = playlist_get_first(source_pl); @@ -391,6 +401,7 @@ struct playlist *playlist_parse_file(const char *file, struct mp_cancel *cancel, struct playlist *ret = NULL; if (d && d->playlist) { ret = talloc_zero(NULL, struct playlist); + playlist_populate_playlist_path(d->playlist, file); playlist_transfer_entries(ret, d->playlist); if (d->filetype && strcmp(d->filetype, "hls") == 0) { mp_warn(log, "This might be a HLS stream. For correct operation, " diff --git a/common/playlist.h b/common/playlist.h index aecd539..853cd31 100644 --- a/common/playlist.h +++ b/common/playlist.h @@ -81,7 +81,9 @@ void playlist_entry_add_params(struct playlist_entry *e, struct playlist_entry *playlist_entry_new(const char *filename); -void playlist_add(struct playlist *pl, struct playlist_entry *add); +void playlist_insert_at(struct playlist *pl, struct playlist_entry *entry, + struct playlist_entry *at); + void playlist_remove(struct playlist *pl, struct playlist_entry *entry); void playlist_clear(struct playlist *pl); void playlist_clear_except_current(struct playlist *pl); @@ -89,7 +91,7 @@ void playlist_clear_except_current(struct playlist *pl); void playlist_move(struct playlist *pl, struct playlist_entry *entry, struct playlist_entry *at); -void playlist_add_file(struct playlist *pl, const char *filename); +void playlist_append_file(struct playlist *pl, const char *filename); void playlist_populate_playlist_path(struct playlist *pl, const char *path); void playlist_shuffle(struct playlist *pl); void playlist_unshuffle(struct playlist *pl); @@ -104,6 +106,8 @@ struct playlist_entry *playlist_get_first_in_same_playlist(struct playlist_entry char *current_playlist_path); void playlist_add_base_path(struct playlist *pl, bstr base_path); void playlist_set_stream_flags(struct playlist *pl, int flags); +int64_t playlist_transfer_entries_to(struct playlist *pl, int dst_index, + struct playlist *source_pl); int64_t playlist_transfer_entries(struct playlist *pl, struct playlist *source_pl); int64_t playlist_append_entries(struct playlist *pl, struct playlist *source_pl); diff --git a/common/version.h.in b/common/version.h.in index b09718f..25d6441 100644 --- a/common/version.h.in +++ b/common/version.h.in @@ -1,5 +1,5 @@ #define VERSION "@VERSION@" -#define MPVCOPYRIGHT "Copyright © 2000-2023 mpv/MPlayer/mplayer2 projects" +#define MPVCOPYRIGHT "Copyright © 2000-2024 mpv/MPlayer/mplayer2 projects" #ifndef NO_BUILD_TIMESTAMPS #define BUILDDATE __DATE__ " " __TIME__ #else |