From 822daeb89fe9ce849bcc48265df1ceaca81056c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kacper=20Michaj=C5=82ow?= Date: Wed, 2 Oct 2024 17:54:52 +0200 Subject: [PATCH 01/38] f_hwtransfer: ensure that we convert to full range rgb with scale_vaapi Limited range rgb is evil and not supported by FFmpeg, this ensures parity of hardware conversion with software conversion. --- filters/f_hwtransfer.c | 25 ++++++++++++++----------- video/hwdec.h | 15 ++++++++++++--- video/out/hwdec/hwdec_vaapi.c | 27 ++++++++++++++++++++++++++- 3 files changed, 52 insertions(+), 15 deletions(-) diff --git a/filters/f_hwtransfer.c b/filters/f_hwtransfer.c index f52bdff61efe5..eb378fc04e191 100644 --- a/filters/f_hwtransfer.c +++ b/filters/f_hwtransfer.c @@ -44,8 +44,8 @@ struct priv { int num_map_fmts; // If the selected hwdec has a conversion filter available for converting - // between sw formats in hardware, the name will be set. NULL otherwise. - const char *conversion_filter_name; + // between sw formats in hardware, the getter will be set. NULL otherwise. + struct mp_conversion_filter *(*get_conversion_filter)(int imgfmt); }; struct hwmap_pairs { @@ -544,7 +544,7 @@ static bool probe_formats(struct mp_filter *f, int hw_imgfmt, bool use_conversio p->av_device_ctx = av_buffer_ref(ctx->av_device_ref); if (!p->av_device_ctx) return false; - p->conversion_filter_name = ctx->conversion_filter_name; + p->get_conversion_filter = ctx->get_conversion_filter; /* * In the case of needing to do hardware conversion vs uploading, we will @@ -554,7 +554,7 @@ static bool probe_formats(struct mp_filter *f, int hw_imgfmt, bool use_conversio * through whatever format we are given. */ return p->num_upload_fmts > 0 || - (use_conversion_filter && !p->conversion_filter_name); + (use_conversion_filter && !p->get_conversion_filter); } struct mp_hwupload mp_hwupload_create(struct mp_filter *parent, int hw_imgfmt, @@ -582,7 +582,7 @@ struct mp_hwupload mp_hwupload_create(struct mp_filter *parent, int hw_imgfmt, } if (src_is_same_hw) { - if (p->conversion_filter_name) { + if (p->get_conversion_filter) { /* * If we are converting from one sw format to another within the same * hw format, we will use that hw format's conversion filter rather @@ -590,14 +590,17 @@ struct mp_hwupload mp_hwupload_create(struct mp_filter *parent, int hw_imgfmt, */ u.selected_sw_imgfmt = hw_output_fmt; if (sw_imgfmt != u.selected_sw_imgfmt) { - enum AVPixelFormat pixfmt = imgfmt2pixfmt(u.selected_sw_imgfmt); - const char *avfmt_name = av_get_pix_fmt_name(pixfmt); - char *args[] = {"format", (char *)avfmt_name, NULL}; - MP_VERBOSE(f, "Hardware conversion: %s -> %s\n", - p->conversion_filter_name, avfmt_name); + struct mp_conversion_filter *desc = p->get_conversion_filter(u.selected_sw_imgfmt); + if (!desc) + goto fail; + MP_VERBOSE(f, "Hardware conversion: %s (%s -> %s)\n", + desc->name, + mp_imgfmt_to_name(sw_imgfmt), + mp_imgfmt_to_name(u.selected_sw_imgfmt)); struct mp_filter *sv = mp_create_user_filter(parent, MP_OUTPUT_CHAIN_VIDEO, - p->conversion_filter_name, args); + desc->name, desc->args); + talloc_free(desc); u.f = sv; talloc_free(f); } diff --git a/video/hwdec.h b/video/hwdec.h index 8027b72e8edce..3f997eacc7fe5 100644 --- a/video/hwdec.h +++ b/video/hwdec.h @@ -8,6 +8,14 @@ struct mp_image_pool; +struct mp_conversion_filter { + // Name of the conversion filter. + const char *name; + + // Arguments for the conversion filter. + char **args; +}; + struct mp_hwdec_ctx { const char *driver_name; // NULL if unknown/not loaded @@ -24,10 +32,11 @@ struct mp_hwdec_ctx { // If NULL, all possible hwuploads are assumed to be supported. const int *supported_hwupload_formats; - // The name of this hwdec's matching conversion filter if available. + // Getter for conversion filter description, or NULL. // This will be used for hardware conversion of frame formats. - // NULL otherwise. - const char *conversion_filter_name; + // If available the talloc allocated mp_conversion_filter is returned, + // Caller is responsible to free the allocation. + struct mp_conversion_filter *(*get_conversion_filter)(int imgfmt); // The libavutil hwconfig to be used when querying constraints for the // conversion filter. Can be NULL if no special config is required. diff --git a/video/out/hwdec/hwdec_vaapi.c b/video/out/hwdec/hwdec_vaapi.c index 63c441464c82e..e8d4f159db28c 100644 --- a/video/out/hwdec/hwdec_vaapi.c +++ b/video/out/hwdec/hwdec_vaapi.c @@ -21,6 +21,7 @@ #include #include +#include #include #include "config.h" @@ -138,6 +139,30 @@ static const dmabuf_interop_init interop_inits[] = { NULL }; +static struct mp_conversion_filter *get_conversion_filter_desc(int target_imgfmt) +{ + const AVPixFmtDescriptor *pixfmt_desc = av_pix_fmt_desc_get(imgfmt2pixfmt(target_imgfmt)); + if (!pixfmt_desc) + return NULL; + + bool rgb = pixfmt_desc->flags & AV_PIX_FMT_FLAG_RGB; + + struct mp_conversion_filter *desc = talloc_ptrtype(NULL, desc); + desc->name = "scale_vaapi"; + desc->args = talloc_array_ptrtype(desc, desc->args, rgb ? 5 : 3); + + int i = 0; + desc->args[i++] = "format"; + desc->args[i++] = (char *)pixfmt_desc->name; + if (rgb) { + desc->args[i++] = "out_range"; + desc->args[i++] = "full"; + } + desc->args[i++] = NULL; + + return desc; +} + static int init(struct ra_hwdec *hw) { struct priv_owner *p = hw->priv; @@ -195,7 +220,7 @@ static int init(struct ra_hwdec *hw) p->ctx->hwctx.supported_formats = p->formats; p->ctx->hwctx.supported_hwupload_formats = p->hwupload_formats; p->ctx->hwctx.driver_name = hw->driver->name; - p->ctx->hwctx.conversion_filter_name = "scale_vaapi"; + p->ctx->hwctx.get_conversion_filter = get_conversion_filter_desc; p->ctx->hwctx.conversion_config = hwconfig; hwdec_devices_add(hw->devs, &p->ctx->hwctx); return 0; From 3fd6c31e1f8c52742b5f1fd54c18227a87fbbfaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kacper=20Michaj=C5=82ow?= Date: Wed, 2 Oct 2024 15:57:31 +0200 Subject: [PATCH 02/38] f_hwtransfer: fix upload formats selection There was mixup between upload formats and device formats. Instead of filtering the device formats with VO constraints, upload formats were affected. It was working, because most of the time the upload is using the same formats. But if there is conversion on the fly needed we were filtering wrong list of formats. Upload formats are those that can be used to upload to the given hardware frame, conversion during upload are allowed if possible. The main fix is in select_format() which were using device formats as input, instead of ouptut formats and upload formats as output, instead of input. --- filters/f_hwtransfer.c | 112 +++++++++++++++++++---------------------- 1 file changed, 51 insertions(+), 61 deletions(-) diff --git a/filters/f_hwtransfer.c b/filters/f_hwtransfer.c index eb378fc04e191..ca530944466ef 100644 --- a/filters/f_hwtransfer.c +++ b/filters/f_hwtransfer.c @@ -110,32 +110,38 @@ static bool select_format(struct priv *p, int input_fmt, return true; } - // First find the closest hw input fmt. Some hwdec APIs return crazy lists of - // "supported" formats, which then are not supported or crash (???), so - // the this is a good way to avoid problems. - // (Actually we should just have hardcoded everything instead of relying on - // this fragile bullshit FFmpeg API and the fragile bullshit hwdec drivers.) - int hw_input_fmt = mp_imgfmt_select_best_list(p->fmts, p->num_fmts, input_fmt); - if (!hw_input_fmt) + // Select best output format from the available hw formats + int hw_output_fmt = mp_imgfmt_select_best_list(p->fmts, p->num_fmts, input_fmt); + if (!hw_output_fmt) return false; // Dumb, but find index for p->fmts[index]==hw_input_fmt. int index = -1; for (int n = 0; n < p->num_fmts; n++) { - if (p->fmts[n] == hw_input_fmt) + if (p->fmts[n] == hw_output_fmt) index = n; } if (index < 0) return false; - // Now check the available output formats. This is the format our sw frame - // will be in after the upload (probably). + // Now check the available upload formats. This is the sw format which will + // be uploaded to given output format. int *upload_fmts = &p->upload_fmts[p->fmt_upload_index[index]]; int num_upload_fmts = p->fmt_upload_num[index]; - int hw_output_fmt = mp_imgfmt_select_best_list(upload_fmts, num_upload_fmts, - input_fmt); - if (!hw_output_fmt) + // Select the output format as the upload format if available to avoid double + // conversion. Note that this will prevent double conversion but does not + // guarantee that the conversion chain is optimal. Conversion during upload + // might already be done on hardware, in which case it may be better to + // prefer a lighter conversion before upload, instead of going directly to + // the output format. However, such cases are uncommon, and in practice, + // there is no good way to predict this without hardcoding specific rules. + int hw_input_fmt = mp_imgfmt_select_best_list(upload_fmts, num_upload_fmts, hw_output_fmt); + + // Select best input format for the available upload formats otherwise. + if (hw_input_fmt != hw_output_fmt) + hw_input_fmt = mp_imgfmt_select_best_list(upload_fmts, num_upload_fmts, input_fmt); + if (!hw_input_fmt) return false; *out_hw_input_fmt = hw_input_fmt; @@ -270,6 +276,19 @@ static bool vo_supports(struct mp_hwdec_ctx *ctx, int hw_fmt, int sw_fmt) return false; } +static bool upload_supports(struct mp_hwdec_ctx *ctx, int fmt) +{ + if (!ctx->supported_hwupload_formats) + return true; // if unset, all formats are allowed + + for (int i = 0; ctx->supported_hwupload_formats[i]; i++) { + if (ctx->supported_hwupload_formats[i] == fmt) + return true; + } + + return false; +} + /** * Some hwcontexts do not implement constraints, and so cannot * report supported formats, so cobble something together from our @@ -392,12 +411,9 @@ static bool probe_formats(struct mp_filter *f, int hw_imgfmt, bool use_conversio ctx->conversion_config); } - int hw_transfer_index = 0; for (int n = 0; cstr->valid_sw_formats && cstr->valid_sw_formats[n] != AV_PIX_FMT_NONE; n++) { - int *not_supported_by_vo = NULL; - int num_not_supported = 0; int imgfmt = pixfmt2imgfmt(cstr->valid_sw_formats[n]); if (!imgfmt) continue; @@ -414,6 +430,11 @@ static bool probe_formats(struct mp_filter *f, int hw_imgfmt, bool use_conversio continue; } + if (!vo_supports(ctx, hw_imgfmt, imgfmt)) { + MP_DBG(f, " not supported by VO\n"); + continue; + } + if (use_conversion_filter) { // The conversion constraints are universal, and do not vary with // source format, so we will associate the same set of target formats @@ -445,7 +466,6 @@ static bool probe_formats(struct mp_filter *f, int hw_imgfmt, bool use_conversio for (int i = 0; ctx->supported_formats[i]; i++) { int fmt = ctx->supported_formats[i]; if (fmt == imgfmt) { - MP_DBG(f, " vo accepts %s\n", mp_imgfmt_to_name(fmt)); MP_TARRAY_APPEND(p, p->upload_fmts, p->num_upload_fmts, fmt); } } @@ -458,19 +478,9 @@ static bool probe_formats(struct mp_filter *f, int hw_imgfmt, bool use_conversio int fmt = pixfmt2imgfmt(fmts[i]); if (!fmt) continue; - if (!vo_supports(ctx, hw_imgfmt, fmt)) { - MP_TARRAY_APPEND(p, not_supported_by_vo, num_not_supported, fmt); - continue; - } MP_DBG(f, " %s", mp_imgfmt_to_name(fmt)); MP_TARRAY_APPEND(p, p->upload_fmts, p->num_upload_fmts, fmt); } - if (num_not_supported) { - MP_DBG(f, "\n not supported by VO:"); - for (int i = 0; i < num_not_supported; i++) { - MP_DBG(f, " %s", mp_imgfmt_to_name(not_supported_by_vo[i])); - } - } MP_DBG(f, "\n"); p->fmt_upload_num[index] = @@ -490,44 +500,37 @@ static bool probe_formats(struct mp_filter *f, int hw_imgfmt, bool use_conversio AV_HWFRAME_TRANSFER_DIRECTION_TO, &fmts, 0) >= 0 && fmts[0] != AV_PIX_FMT_NONE) { - // Don't add the format to p->fmts if we know it cannot be used. - if (ctx->supported_hwupload_formats) { - for (int i = 0; ctx->supported_hwupload_formats[i]; i++) { - if (ctx->supported_hwupload_formats[i] == imgfmt) - MP_TARRAY_APPEND(p, p->fmts, p->num_fmts, imgfmt); - } - } else { - MP_TARRAY_APPEND(p, p->fmts, p->num_fmts, imgfmt); - } - - int index = hw_transfer_index; - hw_transfer_index++; - + int index = p->num_fmts; + MP_TARRAY_APPEND(p, p->fmts, p->num_fmts, imgfmt); MP_TARRAY_GROW(p, p->fmt_upload_index, index); MP_TARRAY_GROW(p, p->fmt_upload_num, index); p->fmt_upload_index[index] = p->num_upload_fmts; + int *upload_not_supported = NULL; + int num_upload_not_supported = 0; + MP_DBG(f, " supports:"); for (int i = 0; fmts[i] != AV_PIX_FMT_NONE; i++) { int fmt = pixfmt2imgfmt(fmts[i]); if (!fmt) continue; - if (!vo_supports(ctx, hw_imgfmt, fmt)) { - MP_TARRAY_APPEND(p, not_supported_by_vo, num_not_supported, fmt); + if (!upload_supports(ctx, fmt)) { + MP_TARRAY_APPEND(NULL, upload_not_supported, num_upload_not_supported, fmt); continue; } MP_DBG(f, " %s", mp_imgfmt_to_name(fmt)); MP_TARRAY_APPEND(p, p->upload_fmts, p->num_upload_fmts, fmt); } - if (num_not_supported) { - MP_DBG(f, "\n not supported by VO:"); - for (int i = 0; i < num_not_supported; i++) { - MP_DBG(f, " %s", mp_imgfmt_to_name(not_supported_by_vo[i])); - } + if (num_upload_not_supported) { + MP_DBG(f, "\n upload not supported:"); + for (int i = 0; i < num_upload_not_supported; ++i) + MP_DBG(f, " %s", mp_imgfmt_to_name(upload_not_supported[i])); } MP_DBG(f, "\n"); + talloc_free(upload_not_supported); + p->fmt_upload_num[index] = p->num_upload_fmts - p->fmt_upload_index[index]; @@ -536,7 +539,6 @@ static bool probe_formats(struct mp_filter *f, int hw_imgfmt, bool use_conversio av_buffer_unref(&frames); } - talloc_free(not_supported_by_vo); } av_hwframe_constraints_free(&cstr); @@ -607,19 +609,7 @@ struct mp_hwupload mp_hwupload_create(struct mp_filter *parent, int hw_imgfmt, } } else { u.f = f; - /* - * In the case where the imgfmt is not natively supported, it must be - * converted, either before or during upload. If the imgfmt is supported - * as a hw input format, then prefer that, and if the upload has to do - * implicit conversion, that's fine. On the other hand, if the imgfmt is - * not a supported input format, then pick the output format as the - * conversion target to avoid doing two conversions (one before upload, - * and one during upload). Note that for most hardware types, there is - * no ability to convert during upload, and the two formats will always - * be the same. - */ - u.selected_sw_imgfmt = - sw_imgfmt == hw_input_fmt ? hw_input_fmt : hw_output_fmt; + u.selected_sw_imgfmt = hw_input_fmt; } u.successful_init = true; From 216abbc12149668c71e400c19d1f60a507fb68c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kacper=20Michaj=C5=82ow?= Date: Sun, 29 Sep 2024 16:26:44 +0200 Subject: [PATCH 03/38] bstr: add missing function docs --- misc/bstr.c | 6 ------ misc/bstr.h | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 6 deletions(-) diff --git a/misc/bstr.c b/misc/bstr.c index 120abef8fe16b..0b82244bcaf5f 100644 --- a/misc/bstr.c +++ b/misc/bstr.c @@ -361,11 +361,6 @@ static void resize_append(void *talloc_ctx, bstr *s, size_t append_min) } } -// Append the string, so that *s = *s + append. s->start is expected to be -// a talloc allocation (which can be realloced) or NULL. -// This function will always implicitly append a \0 after the new string for -// convenience. -// talloc_ctx will be used as parent context, if s->start is NULL. void bstr_xappend(void *talloc_ctx, bstr *s, bstr append) { if (!append.len) @@ -385,7 +380,6 @@ int bstr_xappend_asprintf(void *talloc_ctx, bstr *s, const char *fmt, ...) return ret; } -// Exactly as bstr_xappend(), but with a formatted string. int bstr_xappend_vasprintf(void *talloc_ctx, bstr *s, const char *fmt, va_list ap) { diff --git a/misc/bstr.h b/misc/bstr.h index d279a3a088526..a586ef3442c5d 100644 --- a/misc/bstr.h +++ b/misc/bstr.h @@ -135,9 +135,52 @@ static inline struct bstr bstr_getline(struct bstr str, struct bstr *rest) // and will remove the trailing \n or \r\n sequence. struct bstr bstr_strip_linebreaks(struct bstr str); +/** + * @brief Append a string to the existing bstr. + * + * This function appends the content of the `append` bstr to the `s` bstr. + * `s->start` is expected to be a talloc allocation (which can be resized) or NULL. + * A null terminator ('\0') is always appended for convenience. If `s->start` + * is NULL, the `talloc_ctx` will be used as the parent context to allocate + * memory. + * + * @param talloc_ctx The parent talloc context. + * @param s The destination bstr to which the `append` string is appended. + * @param append The string to append to `s`. + */ void bstr_xappend(void *talloc_ctx, bstr *s, bstr append); + +/** + * @brief Append a formatted string to the existing bstr. + * + * This function works like bstr_xappend() but appends a formatted string using + * a format string and additional arguments. The formatted string is created + * using vsnprintf. The function takes care of resizing the destination + * buffer if necessary. + * + * @param talloc_ctx The parent talloc context. + * @param s The destination bstr to which the formatted string is appended. + * @param fmt The format string (same as in vsnprintf). + * @param ... Additional arguments for the format string. + * @return The number of characters added (excluding the null terminator) + * or a negative value on error. + */ int bstr_xappend_asprintf(void *talloc_ctx, bstr *s, const char *fmt, ...) PRINTF_ATTRIBUTE(3, 4); + +/** + * @brief Append a formatted string to the existing bstr using a va_list. + * + * This function is identical to bstr_xappend_asprintf() but takes a `va_list` + * instead of a variable number of arguments. + * + * @param talloc_ctx The parent talloc context. + * @param s The destination bstr to which the formatted string is appended. + * @param fmt The format string (same as in printf). + * @param ap The `va_list` containing the arguments for the format string. + * @return The number of characters added (excluding the null terminator) + * or a negative value on error. + */ int bstr_xappend_vasprintf(void *talloc_ctx, bstr *s, const char *fmt, va_list va) PRINTF_ATTRIBUTE(3, 0); From a6c363e8dac1e0fd932b1a17838e0da3b13f3b4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kacper=20Michaj=C5=82ow?= Date: Fri, 4 Oct 2024 04:17:15 +0200 Subject: [PATCH 04/38] f_hwtransfer: fix too aggressive preference to use direct upload format Well, this was thinko on last minute code simplification I made. We need to check both input and output formats. --- filters/f_hwtransfer.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/filters/f_hwtransfer.c b/filters/f_hwtransfer.c index ca530944466ef..f39a28f749a66 100644 --- a/filters/f_hwtransfer.c +++ b/filters/f_hwtransfer.c @@ -129,18 +129,23 @@ static bool select_format(struct priv *p, int input_fmt, int *upload_fmts = &p->upload_fmts[p->fmt_upload_index[index]]; int num_upload_fmts = p->fmt_upload_num[index]; - // Select the output format as the upload format if available to avoid double - // conversion. Note that this will prevent double conversion but does not - // guarantee that the conversion chain is optimal. Conversion during upload - // might already be done on hardware, in which case it may be better to - // prefer a lighter conversion before upload, instead of going directly to - // the output format. However, such cases are uncommon, and in practice, - // there is no good way to predict this without hardcoding specific rules. - int hw_input_fmt = mp_imgfmt_select_best_list(upload_fmts, num_upload_fmts, hw_output_fmt); - - // Select best input format for the available upload formats otherwise. - if (hw_input_fmt != hw_output_fmt) - hw_input_fmt = mp_imgfmt_select_best_list(upload_fmts, num_upload_fmts, input_fmt); + // Select the best input format from the available upload formats. + int hw_input_fmt = mp_imgfmt_select_best_list(upload_fmts, num_upload_fmts, input_fmt); + + // If the input format is not directly uploadable, conversion will be needed. + // Attempt to convert directly to the output format to avoid double conversion. + if (input_fmt != hw_input_fmt) { + int upload_output_fmt = mp_imgfmt_select_best_list(upload_fmts, num_upload_fmts, hw_output_fmt); + // Use this format only if it avoids double conversion, i.e., if we can + // upload the output format directly. If that's not the case, just use + // the best format for the input format selected earlier, as double + // conversion is unavoidable anyway. This approach prefers a closer + // conversion before upload and do remaining conversion during upload, + // which may be hardware-accelerated. + if (upload_output_fmt == hw_output_fmt) + hw_input_fmt = upload_output_fmt; + } + if (!hw_input_fmt) return false; From dcd681ecdd69af91be21d98af89a39d24fe16479 Mon Sep 17 00:00:00 2001 From: Guido Cella Date: Tue, 1 Oct 2024 14:26:54 +0200 Subject: [PATCH 05/38] stats.lua: filter keybindings by comment Requested in #14966. --- player/lua/stats.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/player/lua/stats.lua b/player/lua/stats.lua index e8ba263b55406..a46ee331909ec 100644 --- a/player/lua/stats.lua +++ b/player/lua/stats.lua @@ -474,7 +474,7 @@ local function get_kbinfo_lines() and bind.section ~= "input_forced_console" and ( searched_text == nil or - (bind.key .. bind.cmd):lower():find(searched_text, 1, true) + (bind.key .. bind.cmd .. (bind.comment or "")):lower():find(searched_text, 1, true) ) then active[bind.key] = bind From b3f8464fa9a01f0128cfa58c55ceca6c3ac6b398 Mon Sep 17 00:00:00 2001 From: Guido Cella Date: Tue, 1 Oct 2024 20:25:36 +0200 Subject: [PATCH 06/38] input.lua,defaults.js: don't hardcode mp.input arguments Pass everything in the tables passed by mp.input callers to console.lua so new flags can be added without modifying these clients. In Lua, callbacks have to be excluded from the argument tables to not make utils.format_json() error, while with JSON.stringify they are automatically omitted. --- player/javascript/defaults.js | 18 ++---------------- player/lua/input.lua | 30 ++++++++++++++---------------- 2 files changed, 16 insertions(+), 32 deletions(-) diff --git a/player/javascript/defaults.js b/player/javascript/defaults.js index e49bc80614d22..247c88ad993db 100644 --- a/player/javascript/defaults.js +++ b/player/javascript/defaults.js @@ -670,25 +670,10 @@ function register_event_handler(t) { mp.input = { get: function(t) { mp.commandv("script-message-to", "console", "get-input", mp.script_name, - JSON.stringify({ - prompt: t.prompt, - default_text: t.default_text, - cursor_position: t.cursor_position, - id: t.id, - })); + JSON.stringify(t)); register_event_handler(t) }, - select: function (t) { - mp.commandv("script-message-to", "console", "get-input", mp.script_name, - JSON.stringify({ - prompt: t.prompt, - items: t.items, - default_item: t.default_item, - })); - - register_event_handler(t); - }, terminate: function () { mp.commandv("script-message-to", "console", "disable"); }, @@ -708,6 +693,7 @@ mp.input = { JSON.stringify(log)); } } +mp.input.select = mp.input.get /********************************************************************** * various diff --git a/player/lua/input.lua b/player/lua/input.lua index 3c1584b2efb52..aadab383ccab0 100644 --- a/player/lua/input.lua +++ b/player/lua/input.lua @@ -18,6 +18,18 @@ License along with mpv. If not, see . local utils = require "mp.utils" local input = {} +local function get_non_callbacks(t) + local non_callbacks = {} + + for key, value in pairs(t) do + if type(value) ~= "function" then + non_callbacks[key] = value + end + end + + return non_callbacks +end + local function register_event_handler(t) mp.register_script_message("input-event", function (type, args) if t[type] then @@ -38,26 +50,12 @@ end function input.get(t) mp.commandv("script-message-to", "console", "get-input", - mp.get_script_name(), utils.format_json({ - prompt = t.prompt, - default_text = t.default_text, - cursor_position = t.cursor_position, - id = t.id, - })) + mp.get_script_name(), utils.format_json(get_non_callbacks(t))) register_event_handler(t) end -function input.select(t) - mp.commandv("script-message-to", "console", "get-input", - mp.get_script_name(), utils.format_json({ - prompt = t.prompt, - items = t.items, - default_item = t.default_item, - })) - - register_event_handler(t) -end +input.select = input.get function input.terminate() mp.commandv("script-message-to", "console", "disable") From be814e3753e27e35359ea38e09518248d59d8975 Mon Sep 17 00:00:00 2001 From: Guido Cella Date: Tue, 1 Oct 2024 20:53:47 +0200 Subject: [PATCH 07/38] stats.lua: scroll keybindings while filtering them console.lua binds up and down to navigate its history. Add a private flag to mp.input.get to instruct console.lua not to bind up and down, so you can use them to scroll the keybindings page while filtering keybindings. If it is requested, this can be replaced with an argument to input.get to not bind arbitrary keys. Fixes #14966. --- player/lua/console.lua | 13 +++++++++---- player/lua/stats.lua | 1 + 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/player/lua/console.lua b/player/lua/console.lua index b232b878c41d4..bfd19da0e5583 100644 --- a/player/lua/console.lua +++ b/player/lua/console.lua @@ -93,6 +93,7 @@ local history_pos = 1 local searching_history = false local log_buffers = {[id] = {}} local key_bindings = {} +local dont_bind_up_down = false local global_margins = { t = 0, b = 0 } local input_caller @@ -1624,10 +1625,12 @@ local function define_key_bindings() return end for _, bind in ipairs(get_bindings()) do - -- Generate arbitrary name for removing the bindings later. - local name = "_console_" .. (#key_bindings + 1) - key_bindings[#key_bindings + 1] = name - mp.add_forced_key_binding(bind[1], name, bind[2], {repeatable = true}) + if not (dont_bind_up_down and (bind[1] == 'up' or bind[1] == 'down')) then + -- Generate arbitrary name for removing the bindings later. + local name = "_console_" .. (#key_bindings + 1) + key_bindings[#key_bindings + 1] = name + mp.add_forced_key_binding(bind[1], name, bind[2], {repeatable = true}) + end end mp.add_forced_key_binding("any_unicode", "_console_text", text_input, {repeatable = true, complex = true}) @@ -1675,6 +1678,7 @@ set_active = function (active) line = '' cursor = 1 selectable_items = nil + dont_bind_up_down = false end collectgarbage() end @@ -1734,6 +1738,7 @@ mp.register_script_message('get-input', function (script_name, args) line = args.default_text or '' cursor = args.cursor_position or line:len() + 1 id = args.id or script_name .. prompt + dont_bind_up_down = args.dont_bind_up_down if histories[id] == nil then histories[id] = {} log_buffers[id] = {} diff --git a/player/lua/stats.lua b/player/lua/stats.lua index a46ee331909ec..2d529e8858720 100644 --- a/player/lua/stats.lua +++ b/player/lua/stats.lua @@ -1619,6 +1619,7 @@ local function filter_bindings() end end end, + dont_bind_up_down = true, }) end From 493cab7efc1d80bb780d6eacffb316e7f5313154 Mon Sep 17 00:00:00 2001 From: Guido Cella Date: Tue, 1 Oct 2024 21:47:48 +0200 Subject: [PATCH 08/38] stats.lua: allow keybindings to toggle the display of a specific page This lets you define bindings like h script-binding stats/display-page-4-toggle. Requested in #14966. --- .../interface-changes/display-page-toggle.txt | 1 + DOCS/man/stats.rst | 2 +- player/lua/stats.lua | 20 ++++++++++++------- 3 files changed, 15 insertions(+), 8 deletions(-) create mode 100644 DOCS/interface-changes/display-page-toggle.txt diff --git a/DOCS/interface-changes/display-page-toggle.txt b/DOCS/interface-changes/display-page-toggle.txt new file mode 100644 index 0000000000000..0352821074062 --- /dev/null +++ b/DOCS/interface-changes/display-page-toggle.txt @@ -0,0 +1 @@ +add `display-page-n-toggle` script bindings to stats.lua, where n is a page number diff --git a/DOCS/man/stats.rst b/DOCS/man/stats.rst index 0e42f44496d90..4d22f36ff34f9 100644 --- a/DOCS/man/stats.rst +++ b/DOCS/man/stats.rst @@ -233,7 +233,7 @@ Additional keys can be configured in ``input.conf`` to display the stats:: And to display a certain page directly:: i script-binding stats/display-page-1 - e script-binding stats/display-page-2 + h script-binding stats/display-page-4-toggle Active key bindings page ~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/player/lua/stats.lua b/player/lua/stats.lua index 2d529e8858720..bee666467a492 100644 --- a/player/lua/stats.lua +++ b/player/lua/stats.lua @@ -1750,14 +1750,20 @@ mp.add_key_binding(nil, "display-stats", function() process_key_binding(true) en mp.add_key_binding(nil, "display-stats-toggle", function() process_key_binding(false) end, {repeatable=false}) --- Single invocation bindings without key, can be used in input.conf to create --- bindings for a specific page: "e script-binding stats/display-page-2" for k, _ in pairs(pages) do - mp.add_key_binding(nil, "display-page-" .. k, - function() - curr_page = k - process_key_binding(true) - end, {repeatable=true}) + -- Single invocation key bindings for specific pages, e.g.: + -- "e script-binding stats/display-page-2" + mp.add_key_binding(nil, "display-page-" .. k, function() + curr_page = k + process_key_binding(true) + end, {repeatable=true}) + + -- Key bindings to toggle a specific page, e.g.: + -- "h script-binding stats/display-page-4-toggle". + mp.add_key_binding(nil, "display-page-" .. k .. "-toggle", function() + curr_page = k + process_key_binding(false) + end, {repeatable=true}) end -- Reprint stats immediately when VO was reconfigured, only when toggled From 8b30a2386f1e6a0e89c3eb0cbd3088ea63e76079 Mon Sep 17 00:00:00 2001 From: Dudemanguy Date: Fri, 27 Sep 2024 21:32:33 -0500 Subject: [PATCH 09/38] win_state: remove redundant vo_calc_window_geometry functions There's really no reason to have all these extra variants. It's not like this is public API. Collapse it all into one vo_calc_window_geometry function and callers can simply just pass the appropriate parameters to get the same behavior as before. I'm about to edit this function again in a future commit and I really don't want to make a vo_calc_window_geometry4 for this so let's clean it up. --- video/out/mac/common.swift | 2 +- video/out/vo_sdl.c | 2 +- video/out/w32_common.c | 2 +- video/out/wayland_common.c | 2 +- video/out/win_state.c | 21 +++++---------------- video/out/win_state.h | 8 ++------ video/out/x11_common.c | 2 +- 7 files changed, 12 insertions(+), 27 deletions(-) diff --git a/video/out/mac/common.swift b/video/out/mac/common.swift index 9fd7dbc9ea5f9..664665166df26 100644 --- a/video/out/mac/common.swift +++ b/video/out/mac/common.swift @@ -426,7 +426,7 @@ class Common: NSObject { y1: Int32(originY + rv.size.height)) var geo: vo_win_geometry = vo_win_geometry() - vo_calc_window_geometry2(vo, &screenRC, Double(screen.backingScaleFactor), &geo) + vo_calc_window_geometry(vo, &screenRC, &screenRC, Double(screen.backingScaleFactor), &geo) vo_apply_window_geometry(vo, &geo) let height = CGFloat(geo.win.y1 - geo.win.y0) diff --git a/video/out/vo_sdl.c b/video/out/vo_sdl.c index fb8cc331b66a0..6680a7cef8072 100644 --- a/video/out/vo_sdl.c +++ b/video/out/vo_sdl.c @@ -453,7 +453,7 @@ static int reconfig(struct vo *vo, struct mp_image_params *params) struct mp_rect screenrc; update_screeninfo(vo, &screenrc); - vo_calc_window_geometry(vo, &screenrc, &geo); + vo_calc_window_geometry(vo, &screenrc, &screenrc, 1.0, &geo); vo_apply_window_geometry(vo, &geo); int win_w = vo->dwidth; diff --git a/video/out/w32_common.c b/video/out/w32_common.c index 6ebd6076e86b5..027c542f54793 100644 --- a/video/out/w32_common.c +++ b/video/out/w32_common.c @@ -1920,7 +1920,7 @@ static void window_reconfig(struct vo_w32_state *w32, bool force) if (w32->dpi_scale == 0) force_update_display_info(w32); - vo_calc_window_geometry3(vo, &screen, &mon, w32->dpi_scale, &geo); + vo_calc_window_geometry(vo, &screen, &mon, w32->dpi_scale, &geo); vo_apply_window_geometry(vo, &geo); bool reset_size = ((w32->o_dwidth != vo->dwidth || diff --git a/video/out/wayland_common.c b/video/out/wayland_common.c index 4406d53d38ae3..e691c957a8ab0 100644 --- a/video/out/wayland_common.c +++ b/video/out/wayland_common.c @@ -2320,7 +2320,7 @@ static void set_geometry(struct vo_wayland_state *wl, bool resize) struct vo_win_geometry geo; struct mp_rect screenrc = wl->current_output->geometry; - vo_calc_window_geometry2(vo, &screenrc, wl->scaling_factor, &geo); + vo_calc_window_geometry(vo, &screenrc, &screenrc, wl->scaling_factor, &geo); vo_apply_window_geometry(vo, &geo); int gcd = greatest_common_divisor(vo->dwidth, vo->dheight); diff --git a/video/out/win_state.c b/video/out/win_state.c index b4bc9fdb7b33d..c30c257b245d1 100644 --- a/video/out/win_state.c +++ b/video/out/win_state.c @@ -69,6 +69,8 @@ static void apply_autofit(int *w, int *h, int scr_w, int scr_h, // Does not change *vo. // screen: position of the area on virtual desktop on which the video-content // should be placed (maybe after excluding decorations, taskbars, etc) +// can be the same as monitor for platforms that don't try to take into +// account decorations, taskbars, etc. // monitor: position of the monitor on virtual desktop (used for pixelaspect). // dpi_scale: the DPI multiplier to get from virtual to real coordinates // (>1 for "hidpi") @@ -77,9 +79,9 @@ static void apply_autofit(int *w, int *h, int scr_w, int scr_h, // geometry additional to this code. This is to deal with initial window // placement, fullscreen handling, avoiding resize on reconfig() with no // size change, multi-monitor stuff, and possibly more. -void vo_calc_window_geometry3(struct vo *vo, const struct mp_rect *screen, - const struct mp_rect *monitor, - double dpi_scale, struct vo_win_geometry *out_geo) +void vo_calc_window_geometry(struct vo *vo, const struct mp_rect *screen, + const struct mp_rect *monitor, + double dpi_scale, struct vo_win_geometry *out_geo) { struct mp_vo_opts *opts = vo->opts; @@ -131,19 +133,6 @@ void vo_calc_window_geometry3(struct vo *vo, const struct mp_rect *screen, out_geo->flags |= VO_WIN_FORCE_POS; } -// same as vo_calc_window_geometry3 with monitor assumed same as screen -void vo_calc_window_geometry2(struct vo *vo, const struct mp_rect *screen, - double dpi_scale, struct vo_win_geometry *out_geo) -{ - vo_calc_window_geometry3(vo, screen, screen, dpi_scale, out_geo); -} - -void vo_calc_window_geometry(struct vo *vo, const struct mp_rect *screen, - struct vo_win_geometry *out_geo) -{ - vo_calc_window_geometry2(vo, screen, 1.0, out_geo); -} - // Copy the parameters in *geo to the vo fields. // (Doesn't do anything else - windowing backends should trigger VO_EVENT_RESIZE // to ensure that the VO reinitializes rendering properly.) diff --git a/video/out/win_state.h b/video/out/win_state.h index a253efa7584d4..b91e174b18441 100644 --- a/video/out/win_state.h +++ b/video/out/win_state.h @@ -24,12 +24,8 @@ struct vo_win_geometry { }; void vo_calc_window_geometry(struct vo *vo, const struct mp_rect *screen, - struct vo_win_geometry *out_geo); -void vo_calc_window_geometry2(struct vo *vo, const struct mp_rect *screen, - double dpi_scale, struct vo_win_geometry *out_geo); -void vo_calc_window_geometry3(struct vo *vo, const struct mp_rect *screen, - const struct mp_rect *monitor, - double dpi_scale, struct vo_win_geometry *out_geo); + const struct mp_rect *monitor, + double dpi_scale, struct vo_win_geometry *out_geo); void vo_apply_window_geometry(struct vo *vo, const struct vo_win_geometry *geo); #endif diff --git a/video/out/x11_common.c b/video/out/x11_common.c index ae1ea5bf465d5..373c5bd6cb362 100644 --- a/video/out/x11_common.c +++ b/video/out/x11_common.c @@ -1809,7 +1809,7 @@ void vo_x11_config_vo_window(struct vo *vo) vo_x11_update_screeninfo(vo); struct vo_win_geometry geo; - vo_calc_window_geometry2(vo, &x11->screenrc, x11->dpi_scale, &geo); + vo_calc_window_geometry(vo, &x11->screenrc, &x11->screenrc, x11->dpi_scale, &geo); vo_apply_window_geometry(vo, &geo); struct mp_rect rc = geo.win; From e01eab4385d8fe6a542dd9526f912e37b691f58e Mon Sep 17 00:00:00 2001 From: Dudemanguy Date: Fri, 27 Sep 2024 10:54:01 -0500 Subject: [PATCH 10/38] win_state: move window centering to vo_calc_window_geometry c4e8c360719f6e716d1f437c08082022a3b6662f made any usage of --geometry implicitly center the window on the screen after a resize even if the user did not pass any x/y arguments to the option. At the time, this was probably wanted since --geometry was primarily a startup option and likely the window wouldn't be centered on x11 without moving coordinates. Times have changed since then and we support full runtime --geometry changes on all the relevant platforms but it comes with this automatic window centering behavior (except on wayland of course hah). It's better to make such window centering optional and user controllable since it is entirely reasonable that someone wants --geometry=50% to just resize and not move anything. It's already trivial for a person that does want to move the window to just add their coordinates to the --geometry command so there's no reason to continue to force this behavior since it is less flexible. Instead, move the window centering stuff out of m_geometry_apply into vo_calc_window_geometry. We give the power to the caller to whether or not to force centering the window here and all usage of the function is updated to simply call it with false for now. Additionally, --force-window-position being set will also center the window like before. All that is left is for the windowing code to take advantage of this. See subsequent commits. --- DOCS/interface-changes/geometry-behavior.txt | 1 + options/m_option.c | 4 ---- video/out/mac/common.swift | 2 +- video/out/vo_sdl.c | 2 +- video/out/w32_common.c | 2 +- video/out/wayland_common.c | 2 +- video/out/win_state.c | 18 +++++++++++++++--- video/out/win_state.h | 4 ++-- video/out/x11_common.c | 2 +- 9 files changed, 23 insertions(+), 14 deletions(-) create mode 100644 DOCS/interface-changes/geometry-behavior.txt diff --git a/DOCS/interface-changes/geometry-behavior.txt b/DOCS/interface-changes/geometry-behavior.txt new file mode 100644 index 0000000000000..cab61a830a536 --- /dev/null +++ b/DOCS/interface-changes/geometry-behavior.txt @@ -0,0 +1 @@ +change `--geometry` so that it no longer unconditionally moves the window on platforms where that is possible. Use `--force-window-position` or add `+50%+50%` to your geometry command to get the old behavior back. diff --git a/options/m_option.c b/options/m_option.c index a6f8bcd45c256..51e08c21e8652 100644 --- a/options/m_option.c +++ b/options/m_option.c @@ -2219,10 +2219,6 @@ void m_geometry_apply(int *xpos, int *ypos, int *widw, int *widh, } else if (!(gm->w > 0) && gm->h > 0) { *widw = *widh * asp; } - // Center window after resize. If valid x:y values are passed to - // geometry, then those values will be overridden. - *xpos += prew / 2 - *widw / 2; - *ypos += preh / 2 - *widh / 2; } if (gm->xy_valid) { diff --git a/video/out/mac/common.swift b/video/out/mac/common.swift index 664665166df26..dcab914f2cc28 100644 --- a/video/out/mac/common.swift +++ b/video/out/mac/common.swift @@ -426,7 +426,7 @@ class Common: NSObject { y1: Int32(originY + rv.size.height)) var geo: vo_win_geometry = vo_win_geometry() - vo_calc_window_geometry(vo, &screenRC, &screenRC, Double(screen.backingScaleFactor), &geo) + vo_calc_window_geometry(vo, &screenRC, &screenRC, Double(screen.backingScaleFactor), false, &geo) vo_apply_window_geometry(vo, &geo) let height = CGFloat(geo.win.y1 - geo.win.y0) diff --git a/video/out/vo_sdl.c b/video/out/vo_sdl.c index 6680a7cef8072..cce07d3d7dd87 100644 --- a/video/out/vo_sdl.c +++ b/video/out/vo_sdl.c @@ -453,7 +453,7 @@ static int reconfig(struct vo *vo, struct mp_image_params *params) struct mp_rect screenrc; update_screeninfo(vo, &screenrc); - vo_calc_window_geometry(vo, &screenrc, &screenrc, 1.0, &geo); + vo_calc_window_geometry(vo, &screenrc, &screenrc, 1.0, false, &geo); vo_apply_window_geometry(vo, &geo); int win_w = vo->dwidth; diff --git a/video/out/w32_common.c b/video/out/w32_common.c index 027c542f54793..73c0f9f83806e 100644 --- a/video/out/w32_common.c +++ b/video/out/w32_common.c @@ -1920,7 +1920,7 @@ static void window_reconfig(struct vo_w32_state *w32, bool force) if (w32->dpi_scale == 0) force_update_display_info(w32); - vo_calc_window_geometry(vo, &screen, &mon, w32->dpi_scale, &geo); + vo_calc_window_geometry(vo, &screen, &mon, w32->dpi_scale, false, &geo); vo_apply_window_geometry(vo, &geo); bool reset_size = ((w32->o_dwidth != vo->dwidth || diff --git a/video/out/wayland_common.c b/video/out/wayland_common.c index e691c957a8ab0..e95730596c9c1 100644 --- a/video/out/wayland_common.c +++ b/video/out/wayland_common.c @@ -2320,7 +2320,7 @@ static void set_geometry(struct vo_wayland_state *wl, bool resize) struct vo_win_geometry geo; struct mp_rect screenrc = wl->current_output->geometry; - vo_calc_window_geometry(vo, &screenrc, &screenrc, wl->scaling_factor, &geo); + vo_calc_window_geometry(vo, &screenrc, &screenrc, wl->scaling_factor, false, &geo); vo_apply_window_geometry(vo, &geo); int gcd = greatest_common_divisor(vo->dwidth, vo->dheight); diff --git a/video/out/win_state.c b/video/out/win_state.c index c30c257b245d1..435c9a090f0b6 100644 --- a/video/out/win_state.c +++ b/video/out/win_state.c @@ -74,14 +74,17 @@ static void apply_autofit(int *w, int *h, int scr_w, int scr_h, // monitor: position of the monitor on virtual desktop (used for pixelaspect). // dpi_scale: the DPI multiplier to get from virtual to real coordinates // (>1 for "hidpi") +// force_center: force centering x/y in the middle of the given screen even if +// opts->force_window_position is not set. ignored if the user +// supplies valid x/y coordinates on their own. // Use vo_apply_window_geometry() to copy the result into the vo. // NOTE: currently, all windowing backends do their own handling of window // geometry additional to this code. This is to deal with initial window // placement, fullscreen handling, avoiding resize on reconfig() with no // size change, multi-monitor stuff, and possibly more. void vo_calc_window_geometry(struct vo *vo, const struct mp_rect *screen, - const struct mp_rect *monitor, - double dpi_scale, struct vo_win_geometry *out_geo) + const struct mp_rect *monitor, double dpi_scale, + bool force_center, struct vo_win_geometry *out_geo) { struct mp_vo_opts *opts = vo->opts; @@ -121,15 +124,24 @@ void vo_calc_window_geometry(struct vo *vo, const struct mp_rect *screen, out_geo->win.x0 = (int)(scr_w - d_w) / 2; out_geo->win.y0 = (int)(scr_h - d_h) / 2; + + int old_w = d_w; + int old_h = d_h; + m_geometry_apply(&out_geo->win.x0, &out_geo->win.y0, &d_w, &d_h, scr_w, scr_h, &opts->geometry); + if ((opts->force_window_position || force_center) && !opts->geometry.xy_valid) { + out_geo->win.x0 += old_w / 2 - d_w / 2; + out_geo->win.y0 += old_h / 2 - d_h / 2; + } + out_geo->win.x0 += screen->x0; out_geo->win.y0 += screen->y0; out_geo->win.x1 = out_geo->win.x0 + d_w; out_geo->win.y1 = out_geo->win.y0 + d_h; - if (opts->geometry.xy_valid || opts->force_window_position) + if (opts->geometry.xy_valid || opts->force_window_position || force_center) out_geo->flags |= VO_WIN_FORCE_POS; } diff --git a/video/out/win_state.h b/video/out/win_state.h index b91e174b18441..f19a15618bae7 100644 --- a/video/out/win_state.h +++ b/video/out/win_state.h @@ -24,8 +24,8 @@ struct vo_win_geometry { }; void vo_calc_window_geometry(struct vo *vo, const struct mp_rect *screen, - const struct mp_rect *monitor, - double dpi_scale, struct vo_win_geometry *out_geo); + const struct mp_rect *monitor, double dpi_scale, + bool force_center, struct vo_win_geometry *out_geo); void vo_apply_window_geometry(struct vo *vo, const struct vo_win_geometry *geo); #endif diff --git a/video/out/x11_common.c b/video/out/x11_common.c index 373c5bd6cb362..0bda5ce95ce1a 100644 --- a/video/out/x11_common.c +++ b/video/out/x11_common.c @@ -1809,7 +1809,7 @@ void vo_x11_config_vo_window(struct vo *vo) vo_x11_update_screeninfo(vo); struct vo_win_geometry geo; - vo_calc_window_geometry(vo, &x11->screenrc, &x11->screenrc, x11->dpi_scale, &geo); + vo_calc_window_geometry(vo, &x11->screenrc, &x11->screenrc, x11->dpi_scale, false, &geo); vo_apply_window_geometry(vo, &geo); struct mp_rect rc = geo.win; From 2fa87117e0905f7aa8ffa4390f76013e5d8dcce8 Mon Sep 17 00:00:00 2001 From: Dudemanguy Date: Fri, 27 Sep 2024 09:19:35 -0500 Subject: [PATCH 11/38] x11: don't unconditionally move the window on geometry changes With the pieces set in place with the previous changes, we can implement the desired behavior. The trick here is that we do want to force centering the window when mpv first initially starts and the window size is not known yet. This can be done by simply checking x11->pseudo_mapped. The other change is to just look if we have the VO_WIN_FORCE_POS flag and feed that to highlevel resize. --- video/out/x11_common.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/video/out/x11_common.c b/video/out/x11_common.c index 0bda5ce95ce1a..6d7871fac5c33 100644 --- a/video/out/x11_common.c +++ b/video/out/x11_common.c @@ -1809,7 +1809,8 @@ void vo_x11_config_vo_window(struct vo *vo) vo_x11_update_screeninfo(vo); struct vo_win_geometry geo; - vo_calc_window_geometry(vo, &x11->screenrc, &x11->screenrc, x11->dpi_scale, false, &geo); + vo_calc_window_geometry(vo, &x11->screenrc, &x11->screenrc, x11->dpi_scale, + !x11->pseudo_mapped, &geo); vo_apply_window_geometry(vo, &geo); struct mp_rect rc = geo.win; @@ -1833,7 +1834,7 @@ void vo_x11_config_vo_window(struct vo *vo) x11->nofsrc = rc; vo_x11_map_window(vo, rc); } else if (reset_size) { - vo_x11_highlevel_resize(vo, rc, x11->geometry_change); + vo_x11_highlevel_resize(vo, rc, geo.flags & VO_WIN_FORCE_POS); } x11->geometry_change = false; From 9791c6d17849cfb342a1c60a69f7d1119b4dd7c8 Mon Sep 17 00:00:00 2001 From: der richter Date: Sat, 5 Oct 2024 14:16:33 +0200 Subject: [PATCH 12/38] mac/common: don't unconditionally move the window on geometry changes --- video/out/cocoa_cb_common.swift | 2 +- video/out/mac/common.swift | 19 ++++++++++--------- video/out/mac_common.swift | 2 +- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/video/out/cocoa_cb_common.swift b/video/out/cocoa_cb_common.swift index 4b4250c565ce5..38540a2040351 100644 --- a/video/out/cocoa_cb_common.swift +++ b/video/out/cocoa_cb_common.swift @@ -92,7 +92,7 @@ class CocoaCB: Common, EventSubscriber { return } - let wr = getWindowGeometry(forScreen: targetScreen, videoOut: vo) + let (wr, _) = getWindowGeometry(forScreen: targetScreen, videoOut: vo) if !(window?.isVisible ?? false) && !(window?.isMiniaturized ?? false) && !NSApp.isHidden { window?.makeKeyAndOrderFront(nil) } diff --git a/video/out/mac/common.swift b/video/out/mac/common.swift index dcab914f2cc28..7e3af8bd46385 100644 --- a/video/out/mac/common.swift +++ b/video/out/mac/common.swift @@ -75,7 +75,7 @@ class Common: NSObject { } func initWindow(_ vo: UnsafeMutablePointer, _ previousActiveApp: NSRunningApplication?) { - let (targetScreen, wr) = getInitProperties(vo) + let (targetScreen, wr, _) = getInitProperties(vo) guard let view = self.view else { log.error("Something went wrong, no View was initialized") @@ -120,7 +120,7 @@ class Common: NSObject { } func initView(_ vo: UnsafeMutablePointer, _ layer: CALayer) { - let (_, wr) = getInitProperties(vo) + let (_, wr, _) = getInitProperties(vo) view = View(frame: wr, common: self) guard let view = self.view else { @@ -408,7 +408,7 @@ class Common: NSObject { } func getWindowGeometry(forScreen screen: NSScreen, - videoOut vo: UnsafeMutablePointer) -> NSRect { + videoOut vo: UnsafeMutablePointer) -> (NSRect, Bool) { let r = screen.convertRectToBacking(screen.frame) let targetFrame = option.mac.macos_geometry_calculation == FRAME_VISIBLE ? screen.visibleFrame : screen.frame @@ -434,18 +434,19 @@ class Common: NSObject { // flip the y origin again let y = CGFloat(-geo.win.y1) let x = CGFloat(geo.win.x0) - return screen.convertRectFromBacking(NSRect(x: x, y: y, width: width, height: height)) + let wr = screen.convertRectFromBacking(NSRect(x: x, y: y, width: width, height: height)) + return (wr, Bool(geo.flags & Int32(VO_WIN_FORCE_POS))) } - func getInitProperties(_ vo: UnsafeMutablePointer) -> (NSScreen, NSRect) { + func getInitProperties(_ vo: UnsafeMutablePointer) -> (NSScreen, NSRect, Bool) { guard let targetScreen = getTargetScreen(forFullscreen: false) ?? NSScreen.main else { log.error("Something went wrong, no Screen was found") exit(1) } - let wr = getWindowGeometry(forScreen: targetScreen, videoOut: vo) + let (wr, forcePosition) = getWindowGeometry(forScreen: targetScreen, videoOut: vo) - return (targetScreen, wr) + return (targetScreen, wr, forcePosition) } // call before initApp, because on macOS +10.15 it changes the active App @@ -535,8 +536,8 @@ class Common: NSObject { TypeHelper.toPointer(&option.voPtr.pointee.autofit_smaller), TypeHelper.toPointer(&option.voPtr.pointee.autofit_larger): DispatchQueue.main.async { - let (_, wr) = self.getInitProperties(vo) - self.window?.updateFrame(wr) + let (_, wr, forcePosition) = self.getInitProperties(vo) + forcePosition ? self.window?.updateFrame(wr) : self.window?.updateSize(wr.size) } default: break diff --git a/video/out/mac_common.swift b/video/out/mac_common.swift index 3184e31c38422..12c499a813bd7 100644 --- a/video/out/mac_common.swift +++ b/video/out/mac_common.swift @@ -47,7 +47,7 @@ class MacCommon: Common { let previousActiveApp = getActiveApp() initApp() - let (_, wr) = getInitProperties(vo) + let (_, wr, _) = getInitProperties(vo) guard let layer = self.layer else { log.error("Something went wrong, no MetalLayer was initialized") From 232919336d567b70330c43a41920238a56e100da Mon Sep 17 00:00:00 2001 From: Dudemanguy Date: Sat, 5 Oct 2024 14:43:06 -0500 Subject: [PATCH 13/38] github/workflows: drop clang32 It's being dropped upstream* and recently lua51 was removed along with luajit*. mingw32 already covers 32-bit support, and it's not like we're in dire need of this so just remove it. *: https://github.com/msys2/msys2.github.io/commit/89521b9f8d43b6ebf4a4f4a51c912066ab5f5b50 *: https://github.com/msys2/MINGW-packages/commit/947a8592ca9b7d4af6d6520d3083f6118a390036 --- .github/workflows/build.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 93ab36d2ed4fe..d118856dfa2d0 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -501,7 +501,6 @@ jobs: fail-fast: false matrix: sys: - - clang32 - clang64 - mingw32 - mingw64 @@ -541,7 +540,7 @@ jobs: vulkan-devel:p - name: Install dependencies - if: ${{ matrix.sys != 'clang32' && matrix.sys != 'mingw32' }} + if: ${{ matrix.sys != 'mingw32' }} run: | pacboy --noconfirm -S angleproject cppwinrt libcdio-paranoia rst2pdf \ rubberband uchardet vapoursynth From 3e74b1176e3cd571dc2ee14a6bc29434e6d486d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kacper=20Michaj=C5=82ow?= Date: Sun, 6 Oct 2024 17:56:47 +0200 Subject: [PATCH 14/38] d3d11_helpers: remove leftover variables --- video/out/gpu/d3d11_helpers.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/video/out/gpu/d3d11_helpers.c b/video/out/gpu/d3d11_helpers.c index 358a7deb8b83f..f4f2e534951f5 100644 --- a/video/out/gpu/d3d11_helpers.c +++ b/video/out/gpu/d3d11_helpers.c @@ -285,8 +285,6 @@ static bool query_output_format_and_colorspace(struct mp_log *log, DXGI_FORMAT *out_fmt, DXGI_COLOR_SPACE_TYPE *out_cspace) { - IDXGIOutput *output = NULL; - IDXGIOutput6 *output6 = NULL; DXGI_OUTPUT_DESC1 desc = { 0 }; char *monitor_name = NULL; bool success = false; @@ -322,8 +320,6 @@ static bool query_output_format_and_colorspace(struct mp_log *log, done: talloc_free(monitor_name); - SAFE_RELEASE(output6); - SAFE_RELEASE(output); return success; } From 51c613bbcdbcdbfd239f2d0f1ff1a11a9b7ef9e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kacper=20Michaj=C5=82ow?= Date: Sun, 6 Oct 2024 18:15:01 +0200 Subject: [PATCH 15/38] README.md: reference nasm instead of yasm yasm is no longer supported by FFmpeg. See: https://github.com/FFmpeg/FFmpeg/commit/2f888fb99eef07a259879273bc9999c5e86620ca --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8f1caf5fe8bfb..7f5a374415761 100644 --- a/README.md +++ b/README.md @@ -120,7 +120,7 @@ Essential dependencies (incomplete list): Libass dependencies (when building libass): -- gcc or clang, yasm on x86 and x86_64 +- gcc or clang, nasm on x86 and x86_64 - fribidi, freetype, fontconfig development headers (for libass) - harfbuzz (required for correct rendering of combining characters, particularly for correct rendering of non-English text on macOS, and Arabic/Indic scripts on @@ -128,7 +128,7 @@ Libass dependencies (when building libass): FFmpeg dependencies (when building FFmpeg): -- gcc or clang, yasm on x86 and x86_64 +- gcc or clang, nasm on x86 and x86_64 - OpenSSL or GnuTLS (have to be explicitly enabled when compiling FFmpeg) - libx264/libmp3lame/libfdk-aac if you want to use encoding (have to be explicitly enabled when compiling FFmpeg) From 28bc58a3e87bcd00e8148be3f3b9711651e288c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kacper=20Michaj=C5=82ow?= Date: Sun, 6 Oct 2024 18:09:40 +0200 Subject: [PATCH 16/38] Revert "ci/msys2: disable some features for 32-bit build" No longer needed after 232919336d567b70330c43a41920238a56e100da. This reverts commit 883a45fa3eb7347431c246d831cf8ece12da8676. --- .github/workflows/build.yml | 6 ++++-- ci/build-msys2.sh | 7 +++---- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d118856dfa2d0..1e0c396c19109 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -527,6 +527,7 @@ jobs: lcms2:p libarchive:p libass:p + libcdio-paranoia:p libdvdnav:p libjpeg-turbo:p libplacebo:p @@ -537,13 +538,14 @@ jobs: python:p shaderc:p spirv-cross:p + uchardet:p + vapoursynth:p vulkan-devel:p - name: Install dependencies if: ${{ matrix.sys != 'mingw32' }} run: | - pacboy --noconfirm -S angleproject cppwinrt libcdio-paranoia rst2pdf \ - rubberband uchardet vapoursynth + pacboy --noconfirm -S {angleproject,cppwinrt,rst2pdf,rubberband}:p - name: Build with meson id: build diff --git a/ci/build-msys2.sh b/ci/build-msys2.sh index 2d150913d6648..8b8eadefd2a9b 100755 --- a/ci/build-msys2.sh +++ b/ci/build-msys2.sh @@ -3,14 +3,13 @@ args=( --werror -Dc_args='-Wno-error=deprecated -Wno-error=deprecated-declarations' - -D{d3d-hwaccel,d3d11,dvdnav,jpeg,lcms2,libarchive}=enabled - -D{libbluray,lua,shaderc,spirv-cross}=enabled + -D{cdda,d3d-hwaccel,d3d11,dvdnav,jpeg,lcms2,libarchive}=enabled + -D{libbluray,lua,shaderc,spirv-cross,uchardet,vapoursynth}=enabled -D{libmpv,tests}=true ) [[ "$SYS" != "clang32" && "$SYS" != "mingw32" ]] && args+=( - -D{cdda,egl-angle-lib,egl-angle-win32,pdf-build}=enabled - -D{rubberband,uchardet,vapoursynth,win32-smtc}=enabled + -D{egl-angle-lib,egl-angle-win32,pdf-build,rubberband,win32-smtc}=enabled ) meson setup build "${args[@]}" From 9d55c5bcaf158e0eef9a1fa32bde68834afa5d61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kacper=20Michaj=C5=82ow?= Date: Sun, 6 Oct 2024 18:26:32 +0200 Subject: [PATCH 17/38] ci/msys2: removed unused clang32 reference --- ci/build-msys2.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/build-msys2.sh b/ci/build-msys2.sh index 8b8eadefd2a9b..c5a7da2800c1d 100755 --- a/ci/build-msys2.sh +++ b/ci/build-msys2.sh @@ -8,7 +8,7 @@ args=( -D{libmpv,tests}=true ) -[[ "$SYS" != "clang32" && "$SYS" != "mingw32" ]] && args+=( +[[ "$SYS" != "mingw32" ]] && args+=( -D{egl-angle-lib,egl-angle-win32,pdf-build,rubberband,win32-smtc}=enabled ) From 1b08e8b08ef7c1f824e5c837eb7373857651ac38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kacper=20Michaj=C5=82ow?= Date: Sun, 6 Oct 2024 18:44:33 +0200 Subject: [PATCH 18/38] ci/{openbsd,win32}: bump FFmpeg to 7.1 --- DOCS/compile-windows.md | 2 +- ci/build-openbsd.sh | 2 +- ci/build-win32.ps1 | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/DOCS/compile-windows.md b/DOCS/compile-windows.md index c4fff4ab4871b..2f21f9a1c2700 100644 --- a/DOCS/compile-windows.md +++ b/DOCS/compile-windows.md @@ -76,7 +76,7 @@ which bootstraps a MinGW-w64 toolchain and builds mpv along with its dependencie cat < subprojects/ffmpeg.wrap [wrap-git] url = https://gitlab.freedesktop.org/gstreamer/meson-ports/ffmpeg.git - revision = meson-6.1 + revision = meson-7.1 depth = 1 [provide] libavcodec = libavcodec_dep diff --git a/ci/build-openbsd.sh b/ci/build-openbsd.sh index b48de5020e2df..26550a7bdc1ed 100755 --- a/ci/build-openbsd.sh +++ b/ci/build-openbsd.sh @@ -7,7 +7,7 @@ mkdir -p subprojects cat < subprojects/ffmpeg.wrap [wrap-git] url = https://gitlab.freedesktop.org/gstreamer/meson-ports/ffmpeg.git -revision = meson-6.1 +revision = meson-7.1 depth = 1 [provide] libavcodec = libavcodec_dep diff --git a/ci/build-win32.ps1 b/ci/build-win32.ps1 index 489e12c794869..6fd2f9b696695 100644 --- a/ci/build-win32.ps1 +++ b/ci/build-win32.ps1 @@ -115,7 +115,7 @@ $projects = @( @{ Path = "$subprojects/ffmpeg.wrap" URL = "https://gitlab.freedesktop.org/gstreamer/meson-ports/ffmpeg.git" - Revision = "meson-7.0" + Revision = "meson-7.1" Provides = @( "libavcodec = libavcodec_dep", "libavdevice = libavdevice_dep", From f7a895e7c15b35316625de67047cabb2b921f573 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kacper=20Michaj=C5=82ow?= Date: Sun, 6 Oct 2024 17:11:48 +0200 Subject: [PATCH 19/38] docs: remove stray newlines --- DOCS/client-api-changes.rst | 1 - DOCS/man/vf.rst | 1 - 2 files changed, 2 deletions(-) diff --git a/DOCS/client-api-changes.rst b/DOCS/client-api-changes.rst index ec2e3b87f9d1b..8826b875d2251 100644 --- a/DOCS/client-api-changes.rst +++ b/DOCS/client-api-changes.rst @@ -286,4 +286,3 @@ API changes - macOS: the "coreaudio" AO spdif code is split into a separate AO --- mpv 0.4.0 --- 1.0 - the API is declared stable - diff --git a/DOCS/man/vf.rst b/DOCS/man/vf.rst index 0331c7e15175a..3a27014b575aa 100644 --- a/DOCS/man/vf.rst +++ b/DOCS/man/vf.rst @@ -840,4 +840,3 @@ Available mpv-only filters are: Do not use this with ``--vo=gpu``. It will apply filtering twice, since most ``--vo=gpu`` options are unconditionally applied to the ``gpu`` filter. There is no mechanism in mpv to prevent this. - From 2fb8b00ac9580109447d1e946f5093833ac38c2e Mon Sep 17 00:00:00 2001 From: der richter Date: Sat, 5 Oct 2024 16:19:48 +0200 Subject: [PATCH 20/38] mac/app: fix building with swift disabled Fixes #14931 --- osdep/mac/app_bridge.m | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/osdep/mac/app_bridge.m b/osdep/mac/app_bridge.m index bea1ecae3edbe..ead9603c9d62c 100644 --- a/osdep/mac/app_bridge.m +++ b/osdep/mac/app_bridge.m @@ -110,6 +110,7 @@ void app_bridge_tarray_append(void *t, char ***a, int *i, char *s) return &vo_sub_opts; } +#if HAVE_SWIFT void cocoa_init_media_keys(void) { [[AppHub shared] startRemote]; @@ -139,4 +140,4 @@ int cocoa_main(int argc, char *argv[]) { return [(Application *)[Application sharedApplication] main:argc :argv]; } - +#endif From 20b7f96ab31c0f6cab88dd34128b01c1bd8d0d21 Mon Sep 17 00:00:00 2001 From: der richter Date: Sun, 6 Oct 2024 16:55:38 +0200 Subject: [PATCH 21/38] meson: error out when swift unavailable or disabled and cplayer enabled without swift mpv as a standalone app is unusable on macOS, since the cocoa main main loop doesn't exists. furthermore most of the other needed functionalities like video outputs, contexts, platform features, etc are also missing. without swift mpv is really only usable as libmpv. --- meson.build | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/meson.build b/meson.build index 2e0b705ae29d5..1b56eb4713aed 100644 --- a/meson.build +++ b/meson.build @@ -1540,6 +1540,10 @@ swift = get_option('swift-build').require( ) features += {'swift': swift.allowed()} +if features['cocoa'] and not features['swift'] and get_option('cplayer') + error('cplayer enabled but no suitable swift version could be found or was disabled!') +endif + swift_sources = [] if features['cocoa'] and features['swift'] swift_sources += files('osdep/mac/application.swift', From 94d034ed994711d4b542982179bab874b6f5f61d Mon Sep 17 00:00:00 2001 From: der richter Date: Sat, 5 Oct 2024 14:38:22 +0200 Subject: [PATCH 22/38] mac/swift: fix typo in mpv_event_id string representation this didn't break anything but might be confusing in log outputs. --- osdep/mac/swift_extensions.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osdep/mac/swift_extensions.swift b/osdep/mac/swift_extensions.swift index e49806aaa0d15..8f3de98802b2a 100644 --- a/osdep/mac/swift_extensions.swift +++ b/osdep/mac/swift_extensions.swift @@ -73,7 +73,7 @@ extension mp_keymap { extension mpv_event_id: CustomStringConvertible { public var description: String { switch self { - case MPV_EVENT_NONE: return "MPV_EVENT_NONE2" + case MPV_EVENT_NONE: return "MPV_EVENT_NONE" case MPV_EVENT_SHUTDOWN: return "MPV_EVENT_SHUTDOWN" case MPV_EVENT_LOG_MESSAGE: return "MPV_EVENT_LOG_MESSAGE" case MPV_EVENT_GET_PROPERTY_REPLY: return "MPV_EVENT_GET_PROPERTY_REPLY" From c5324cc483376b639f361636010adac0dd610e09 Mon Sep 17 00:00:00 2001 From: der richter Date: Sat, 5 Oct 2024 14:53:29 +0200 Subject: [PATCH 23/38] DOCS/input: clarify display-names naming on macOS this was meant to refer to round brackets and not square brackets. --- DOCS/man/input.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DOCS/man/input.rst b/DOCS/man/input.rst index 87b8a03f22613..2be4d3d30f635 100644 --- a/DOCS/man/input.rst +++ b/DOCS/man/input.rst @@ -2778,7 +2778,7 @@ Property list in the list will be the one that Windows considers associated with the window (as determined by the MonitorFromWindow API.) On macOS these are the Display Product Names as used in the System Information with a serial number - in brackets and only one display name is returned since a window can only be + in parentheses and only one display name is returned since a window can only be on one screen. On Wayland, these are the wl_output names if protocol version >= 4 is used (LVDS-1, HDMI-A-1, X11-1, etc.), or the wl_output model reported by the geometry event if protocol version < 4 is used. From 7bd612ee66eac374d0b607e5f36e3afb8ce5cf1f Mon Sep 17 00:00:00 2001 From: der richter Date: Sat, 5 Oct 2024 15:07:33 +0200 Subject: [PATCH 24/38] mac: remove unnecessary window size change check this is already done in the updateSize method of the window. also fixes an issue where the size wasn't properly changed, even though the new and old size were different. the unfsContentFrame should have been checked instead of the pixel representation of the same frame. --- video/out/mac_common.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/video/out/mac_common.swift b/video/out/mac_common.swift index 12c499a813bd7..d853c9c04a732 100644 --- a/video/out/mac_common.swift +++ b/video/out/mac_common.swift @@ -60,7 +60,7 @@ class MacCommon: Common { initWindowState() } - if (window?.unfsContentFramePixel.size ?? NSSize.zero) != wr.size && option.vo.auto_window_resize { + if option.vo.auto_window_resize { window?.updateSize(wr.size) } From 9b571a7aa711b9587e6acf68572e2003e2ddd51e Mon Sep 17 00:00:00 2001 From: nanahi <130121847+na-na-hi@users.noreply.github.com> Date: Tue, 1 Oct 2024 00:36:25 -0400 Subject: [PATCH 25/38] mp_image: copy params before dovi mapping for mp_image_copy_attributes It currently doesn't copy original params before mapping, resulting in wrong colors when some video filters are used, e.g. d3d11vpp=scale. --- video/mp_image.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/video/mp_image.c b/video/mp_image.c index b809dae765407..f770470dd1ff0 100644 --- a/video/mp_image.c +++ b/video/mp_image.c @@ -519,6 +519,9 @@ void mp_image_copy_attributes(struct mp_image *dst, struct mp_image *src) dst->params.chroma_location = src->params.chroma_location; dst->params.crop = src->params.crop; dst->nominal_fps = src->nominal_fps; + dst->params.primaries_orig = dst->params.color.primaries; + dst->params.transfer_orig = dst->params.color.transfer; + dst->params.sys_orig = dst->params.repr.sys; // ensure colorspace consistency enum pl_color_system dst_forced_csp = mp_image_params_get_forced_csp(&dst->params); From e35a559ce1b15bb4af54134e81ddf3d20341abfe Mon Sep 17 00:00:00 2001 From: nanahi <130121847+na-na-hi@users.noreply.github.com> Date: Tue, 1 Oct 2024 00:48:03 -0400 Subject: [PATCH 26/38] mp_image: only restore params when image is dolbyvision Should be no need to do so otherwise. --- video/mp_image.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/video/mp_image.c b/video/mp_image.c index f770470dd1ff0..e6aca6dc0a645 100644 --- a/video/mp_image.c +++ b/video/mp_image.c @@ -855,6 +855,8 @@ bool mp_image_params_static_equal(const struct mp_image_params *p1, // before dovi mapping. void mp_image_params_restore_dovi_mapping(struct mp_image_params *params) { + if (params->repr.sys != PL_COLOR_SYSTEM_DOLBYVISION) + return; params->color.primaries = params->primaries_orig; params->color.transfer = params->transfer_orig; params->repr.sys = params->sys_orig; From e2365bfeceeef8939d159780b607698d05073910 Mon Sep 17 00:00:00 2001 From: nanahi <130121847+na-na-hi@users.noreply.github.com> Date: Tue, 1 Oct 2024 01:13:33 -0400 Subject: [PATCH 27/38] vf_format: set original params when converting format Otherwise it will restore to a format before vf_format conversion when restoring params. Only do this when the out format isn't dolbyvision. --- video/filter/vf_format.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/video/filter/vf_format.c b/video/filter/vf_format.c index cf08297ee34a4..f73e926d99281 100644 --- a/video/filter/vf_format.c +++ b/video/filter/vf_format.c @@ -84,6 +84,11 @@ static void set_params(struct vf_format_opts *p, struct mp_image_params *out, out->light = MP_CSP_LIGHT_AUTO; } } + if (p->colormatrix != PL_COLOR_SYSTEM_DOLBYVISION && !p->dovi) { + out->primaries_orig = out->color.primaries; + out->transfer_orig = out->color.transfer; + out->sys_orig = out->repr.sys; + } if (p->sig_peak) out->color.hdr = (struct pl_hdr_metadata){ .max_luma = p->sig_peak * MP_REF_WHITE }; if (p->light) From f46975c2d20f9304b780c398daded1b9fca17ebd Mon Sep 17 00:00:00 2001 From: nanahi <130121847+na-na-hi@users.noreply.github.com> Date: Wed, 2 Oct 2024 10:57:48 -0400 Subject: [PATCH 28/38] mp_image: restore dovi metadata before converting to AVFrame They should be passed as side data instead. --- video/mp_image.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/video/mp_image.c b/video/mp_image.c index e6aca6dc0a645..d7cc49de0b617 100644 --- a/video/mp_image.c +++ b/video/mp_image.c @@ -1203,13 +1203,16 @@ struct AVFrame *mp_image_to_av_frame(struct mp_image *src) if (src->fields & MP_IMGFIELD_REPEAT_FIRST) dst->repeat_pict = 1; - pl_avframe_set_repr(dst, src->params.repr); + // Image params without dovi mapped; should be passed as side data instead + struct mp_image_params params = src->params; + mp_image_params_restore_dovi_mapping(¶ms); + pl_avframe_set_repr(dst, params.repr); - dst->chroma_location = pl_chroma_to_av(src->params.chroma_location); + dst->chroma_location = pl_chroma_to_av(params.chroma_location); dst->opaque_ref = av_buffer_alloc(sizeof(struct mp_image_params)); MP_HANDLE_OOM(dst->opaque_ref); - *(struct mp_image_params *)dst->opaque_ref->data = src->params; + *(struct mp_image_params *)dst->opaque_ref->data = params; if (src->icc_profile) { AVFrameSideData *sd = @@ -1219,14 +1222,14 @@ struct AVFrame *mp_image_to_av_frame(struct mp_image *src) new_ref->icc_profile = NULL; } - pl_avframe_set_color(dst, src->params.color); + pl_avframe_set_color(dst, params.color); { AVFrameSideData *sd = av_frame_new_side_data(dst, AV_FRAME_DATA_DISPLAYMATRIX, sizeof(int32_t) * 9); MP_HANDLE_OOM(sd); - av_display_rotation_set((int32_t *)sd->data, src->params.rotate); + av_display_rotation_set((int32_t *)sd->data, params.rotate); } // Add back side data, but only for types which are not specially handled From bee3598ba6dc0b0cd0baac009cd4966697f9b536 Mon Sep 17 00:00:00 2001 From: Nathan Ruiz Date: Fri, 13 Sep 2024 17:22:05 +0000 Subject: [PATCH 29/38] ci/lint: add python linting Enabled the ruff python linter in CI, and resolved the issues that were detected by it. Ruff was used due to it's faster checking compared with other linters like pylint. This was added to resolve the python linting request in #13608. --- .github/workflows/lint.yml | 6 ++++++ TOOLS/docutils-wrapper.py | 2 +- TOOLS/dylib_unhell.py | 20 ++++++++++---------- TOOLS/macos-sdk-version.py | 4 +--- TOOLS/matroska.py | 21 +++++++++++---------- TOOLS/stats-conv.py | 2 +- ci/lint-commit-msg.py | 6 +++++- 7 files changed, 35 insertions(+), 26 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 425e8d1a07c46..3aece2f4d71b1 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -33,3 +33,9 @@ jobs: steps: - uses: actions/checkout@v4 - uses: lunarmodules/luacheck@v1 + + python-lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: chartboost/ruff-action@v1 diff --git a/TOOLS/docutils-wrapper.py b/TOOLS/docutils-wrapper.py index 31ba976e64f8b..8e4ce57dc5060 100755 --- a/TOOLS/docutils-wrapper.py +++ b/TOOLS/docutils-wrapper.py @@ -58,7 +58,7 @@ def remove(path): proc = subprocess.run(argv, check=True) if depfile is not None: convert_depfile(output, depfile) -except: +except Exception: remove(output) if depfile is not None: remove(depfile) diff --git a/TOOLS/dylib_unhell.py b/TOOLS/dylib_unhell.py index c8859692845b3..ed2136554d85d 100755 --- a/TOOLS/dylib_unhell.py +++ b/TOOLS/dylib_unhell.py @@ -16,13 +16,13 @@ def is_user_lib(objfile, libname): return not sys_re.match(libname) and \ not usr_re.match(libname) and \ not exe_re.match(libname) and \ - not "libobjc." in libname and \ - not "libSystem." in libname and \ - not "libc." in libname and \ - not "libgcc." in libname and \ + "libobjc." not in libname and \ + "libSystem." not in libname and \ + "libc." not in libname and \ + "libgcc." not in libname and \ not os.path.basename(libname) == 'Python' and \ - not os.path.basename(objfile) in libname and \ - not "libswift" in libname + os.path.basename(objfile) not in libname and \ + "libswift" not in libname def otool(objfile, rapths): command = "otool -L '%s' | grep -e '\t' | awk '{ print $1 }'" % objfile @@ -46,7 +46,7 @@ def get_rapths(objfile): try: result = subprocess.check_output(command, shell = True, universal_newlines=True) - except: + except Exception: return rpaths for line in result.splitlines(): @@ -90,9 +90,9 @@ def resolve_lib_path(objfile, lib, rapths): def check_vulkan_max_version(version): try: - result = subprocess.check_output("pkg-config vulkan --max-version=" + version, shell = True) + subprocess.check_output("pkg-config vulkan --max-version=" + version, shell = True) return True - except: + except Exception: return False def get_homebrew_prefix(): @@ -100,7 +100,7 @@ def get_homebrew_prefix(): result = "/opt/homebrew" try: result = subprocess.check_output("brew --prefix", universal_newlines=True, shell=True, stderr=subprocess.DEVNULL).strip() - except: + except Exception: pass return result diff --git a/TOOLS/macos-sdk-version.py b/TOOLS/macos-sdk-version.py index 12e1071d7588f..eadfda414dc6f 100755 --- a/TOOLS/macos-sdk-version.py +++ b/TOOLS/macos-sdk-version.py @@ -3,9 +3,7 @@ # This checks for the sdk path, the sdk version, and # the sdk build version. -import re import os -import string import subprocess import sys from shutil import which @@ -33,7 +31,7 @@ def find_macos_sdk(): try: sdk_version = check_output([xcodebuild, '-sdk', 'macosx', '-version', 'ProductVersion'], encoding="UTF-8", stderr=subprocess.DEVNULL) - except: + except Exception: pass if not isinstance(sdk_version, str): diff --git a/TOOLS/matroska.py b/TOOLS/matroska.py index 6abece6e95886..445e22237216d 100755 --- a/TOOLS/matroska.py +++ b/TOOLS/matroska.py @@ -4,6 +4,10 @@ Can also be used to directly parse Matroska files and display their contents. """ +import sys +from math import ldexp +from binascii import hexlify + # # This file is part of mpv. # @@ -242,14 +246,11 @@ ) -import sys -from math import ldexp -from binascii import hexlify - def byte2num(s): return int(hexlify(s), 16) -class EOF(Exception): pass +class EOF(Exception): + pass def camelcase_to_words(name): parts = [] @@ -291,9 +292,9 @@ def add_subelements(self, subelements): elementd = {} elementlist = [] -def parse_elems(l, namespace): +def parse_elems(elements, namespace): subelements = [] - for el in l: + for el in elements: if isinstance(el, str): name, hexid, eltype = [x.strip() for x in el.split(',')] hexid = hexid.lower() @@ -328,10 +329,10 @@ def generate_C_header(out): continue printf(out) printf(out, 'struct {0.structname} {{'.format(el)) - l = max(len(subel.valname) for subel, multiple in el.subelements)+1 + length = max(len(subel.valname) for subel, multiple in el.subelements)+1 for subel, multiple in el.subelements: - printf(out, ' {e.valname:{l}} {star}{e.fieldname};'.format( - e=subel, l=l, star=' *'[multiple])) + printf(out, ' {e.valname:{length}} {star}{e.fieldname};'.format( + e=subel, length=length, star=' *'[multiple])) printf(out) for subel, multiple in el.subelements: printf(out, ' int n_{0.fieldname};'.format(subel)) diff --git a/TOOLS/stats-conv.py b/TOOLS/stats-conv.py index 0a9cf4ee9eb25..774e77bdcce72 100755 --- a/TOOLS/stats-conv.py +++ b/TOOLS/stats-conv.py @@ -161,7 +161,7 @@ def mkColor(t): for e in G.sevents: cur = ax[1 if e.type == "value" else 0] - if not cur in G.curveno: + if cur not in G.curveno: G.curveno[cur] = 0 args = {'name': e.name,'antialias':True} color = mkColor(colors[G.curveno[cur] % len(colors)]) diff --git a/ci/lint-commit-msg.py b/ci/lint-commit-msg.py index 3ceaa24fbf0c1..36497b66e45fe 100755 --- a/ci/lint-commit-msg.py +++ b/ci/lint-commit-msg.py @@ -1,5 +1,9 @@ #!/usr/bin/env python3 -import os, sys, json, subprocess, re +import os +import sys +import json +import subprocess +import re from typing import Dict, Tuple, Callable, Optional def call(cmd) -> str: From e5a383a525b724d9e1dcac2b334fe8a67621d68b Mon Sep 17 00:00:00 2001 From: Nathan Ruiz Date: Sun, 15 Sep 2024 00:43:15 +0000 Subject: [PATCH 30/38] ci/lint: enable pyflakes and pycodestyle checks This change required some minor rework to make the code conform to the following: - Restrict line length to 88 character - Use spaces rather than tabs (only affect ci/lint-commit-msg.py) - Use f-strings rather than % formatting or `str.format()` --- TOOLS/dylib_unhell.py | 54 +++++++++--- TOOLS/gen-mpv-desktop.py | 14 +++- TOOLS/macos-sdk-version.py | 7 +- TOOLS/macos-swift-lib-directory.py | 5 +- TOOLS/matroska.py | 5 +- TOOLS/osxbundle.py | 3 +- TOOLS/stats-conv.py | 11 ++- ci/lint-commit-msg.py | 130 +++++++++++++++-------------- pyproject.toml | 8 ++ 9 files changed, 152 insertions(+), 85 deletions(-) create mode 100644 pyproject.toml diff --git a/TOOLS/dylib_unhell.py b/TOOLS/dylib_unhell.py index ed2136554d85d..73e853d5a4f2a 100755 --- a/TOOLS/dylib_unhell.py +++ b/TOOLS/dylib_unhell.py @@ -54,13 +54,17 @@ def get_rapths(objfile): # resolve @loader_path if line_clean.startswith('@loader_path/'): line_clean = line_clean[len('@loader_path/'):] - line_clean = os.path.normpath(os.path.join(os.path.dirname(objfile), line_clean)) + line_clean = os.path.join(os.path.dirname(objfile), line_clean) + line_clean = os.path.normpath(line_clean) rpaths.append(line_clean) return rpaths def get_rpaths_dev_tools(binary): - command = "otool -l '%s' | grep -A2 LC_RPATH | grep path | grep \"Xcode\\|CommandLineTools\"" % binary + command = ( + f"otool -l '{binary}' | grep -A2 LC_RPATH | grep path | " + "grep \"Xcode\\|CommandLineTools\"" + ) result = subprocess.check_output(command, shell = True, universal_newlines=True) pathRe = re.compile(r"^\s*path (.*) \(offset \d*\)$") output = [] @@ -90,26 +94,41 @@ def resolve_lib_path(objfile, lib, rapths): def check_vulkan_max_version(version): try: - subprocess.check_output("pkg-config vulkan --max-version=" + version, shell = True) + subprocess.check_output( + f"pkg-config vulkan --max-version={version}", + shell=True, + ) return True except Exception: return False def get_homebrew_prefix(): - # set default to standard ARM path, intel path is already in the vulkan loader search array + # set default to standard ARM path, intel path is already in the vulkan + # loader search array result = "/opt/homebrew" try: - result = subprocess.check_output("brew --prefix", universal_newlines=True, shell=True, stderr=subprocess.DEVNULL).strip() + result = subprocess.check_output( + "brew --prefix", + universal_newlines=True, + shell=True, + stderr=subprocess.DEVNULL + ).strip() except Exception: pass return result def install_name_tool_change(old, new, objfile): - subprocess.call(["install_name_tool", "-change", old, new, objfile], stderr=subprocess.DEVNULL) + subprocess.call( + ["install_name_tool", "-change", old, new, objfile], + stderr=subprocess.DEVNULL, + ) def install_name_tool_id(name, objfile): - subprocess.call(["install_name_tool", "-id", name, objfile], stderr=subprocess.DEVNULL) + subprocess.call( + ["install_name_tool", "-id", name, objfile], + stderr=subprocess.DEVNULL, + ) def install_name_tool_add_rpath(rpath, binary): subprocess.call(["install_name_tool", "-add_rpath", rpath, binary]) @@ -173,7 +192,10 @@ def process_swift_libraries(binary): swiftLibPath = os.path.join(swiftStdlibTool, '../../lib/swift-5.0/macosx') swiftLibPath = os.path.abspath(swiftLibPath) - command = [swiftStdlibTool, '--copy', '--platform', 'macosx', '--scan-executable', binary, '--destination', lib_path(binary)] + command = [ + swiftStdlibTool, '--copy', '--platform', 'macosx', '--scan-executable', + binary, '--destination', lib_path(binary) + ] if os.path.exists(swiftLibPath): command.extend(['--source-libraries', swiftLibPath]) @@ -221,7 +243,8 @@ def process_vulkan_loader(binary, loaderName, loaderRelativeFolder, libraryNode) loaderSystemFile = open(loaderSystemPath, 'r') loaderJsonData = json.load(loaderSystemFile) - librarySystemPath = os.path.join(loaderSystemFolder, loaderJsonData[libraryNode]["library_path"]) + libraryPath = loaderJsonData[libraryNode]["library_path"] + librarySystemPath = os.path.join(loaderSystemFolder, libraryPath) if not os.path.exists(librarySystemPath): print(">>> could not find loader library " + librarySystemPath) @@ -230,14 +253,16 @@ def process_vulkan_loader(binary, loaderName, loaderRelativeFolder, libraryNode) print(">>> modifiying and writing loader json " + loaderName) loaderBundleFile = open(loaderBundlePath, 'w') loaderLibraryName = os.path.basename(librarySystemPath) - loaderJsonData[libraryNode]["library_path"] = os.path.join(libraryRelativeFolder, loaderLibraryName) + library_path = os.path.join(libraryRelativeFolder, loaderLibraryName) + loaderJsonData[libraryNode]["library_path"] = library_path json.dump(loaderJsonData, loaderBundleFile, indent=4) print(">>> copying loader library " + loaderLibraryName) frameworkBundleFolder = os.path.join(loaderBundleFolder, libraryRelativeFolder) if not os.path.exists(frameworkBundleFolder): os.makedirs(frameworkBundleFolder) - shutil.copy(librarySystemPath, os.path.join(frameworkBundleFolder, loaderLibraryName)) + library_target_path = os.path.join(frameworkBundleFolder, loaderLibraryName) + shutil.copy(librarySystemPath, library_target_path) def remove_dev_tools_rapths(binary): for path in get_rpaths_dev_tools(binary): @@ -262,7 +287,12 @@ def process(binary): print(">> copying and processing vulkan loader") process_vulkan_loader(binary, "MoltenVK_icd.json", "vulkan/icd.d", "ICD") if check_vulkan_max_version("1.3.261.1"): - process_vulkan_loader(binary, "VkLayer_khronos_synchronization2.json", "vulkan/explicit_layer.d", "layer") + process_vulkan_loader( + binary, + "VkLayer_khronos_synchronization2.json", + "vulkan/explicit_layer.d", + "layer", + ) if __name__ == "__main__": process(sys.argv[1]) diff --git a/TOOLS/gen-mpv-desktop.py b/TOOLS/gen-mpv-desktop.py index 7bbb33e5be0fb..f09498bb8213e 100755 --- a/TOOLS/gen-mpv-desktop.py +++ b/TOOLS/gen-mpv-desktop.py @@ -31,13 +31,21 @@ if not mpv_desktop["X-KDE-Protocols"]: raise ValueError("Missing X-KDE-Protocols entry in mpv.desktop file") - mpv_protocols = check_output([sys.argv[2], "--no-config", "--list-protocols"], encoding="UTF-8") - mpv_protocols = set(line.strip(" :/") for line in mpv_protocols.splitlines() if "://" in line) + mpv_protocols = check_output( + [sys.argv[2], "--no-config", "--list-protocols"], + encoding="UTF-8", + ) + mpv_protocols = { + line.strip(" :/") + for line in mpv_protocols.splitlines() + if "://" in line + } if len(mpv_protocols) == 0: raise ValueError("Unable to parse any protocols from mpv '--list-protocols'") protocol_list = set(mpv_desktop["X-KDE-Protocols"].strip().split(",")) - mpv_desktop["X-KDE-Protocols"] = ",".join(sorted(mpv_protocols & protocol_list)) + "\n" + compatible_protocols = sorted(mpv_protocols & protocol_list) + mpv_desktop["X-KDE-Protocols"] = ",".join(compatible_protocols) + "\n" with open(sys.argv[3], "w", encoding="UTF-8") as f: f.write("[Desktop Entry]" + "\n") diff --git a/TOOLS/macos-sdk-version.py b/TOOLS/macos-sdk-version.py index eadfda414dc6f..d487511bb1ad6 100755 --- a/TOOLS/macos-sdk-version.py +++ b/TOOLS/macos-sdk-version.py @@ -29,8 +29,11 @@ def find_macos_sdk(): # use xcode tools when installed, still necessary for xcode versions <12.0 try: - sdk_version = check_output([xcodebuild, '-sdk', 'macosx', '-version', 'ProductVersion'], - encoding="UTF-8", stderr=subprocess.DEVNULL) + sdk_version = check_output( + [xcodebuild, '-sdk', 'macosx', '-version', 'ProductVersion'], + encoding="UTF-8", + stderr=subprocess.DEVNULL + ) except Exception: pass diff --git a/TOOLS/macos-swift-lib-directory.py b/TOOLS/macos-swift-lib-directory.py index 51e8cbe96f099..df967b14c1d68 100755 --- a/TOOLS/macos-swift-lib-directory.py +++ b/TOOLS/macos-swift-lib-directory.py @@ -27,7 +27,10 @@ def find_swift_lib(): xcode_path = check_output([xcode_select, "-p"], encoding="UTF-8") - swift_lib_dir = os.path.join(xcode_path, "Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx") + swift_lib_dir = os.path.join( + xcode_path, + "Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx" + ) if os.path.isdir(swift_lib_dir): return swift_lib_dir diff --git a/TOOLS/matroska.py b/TOOLS/matroska.py index 445e22237216d..79229d410ac46 100755 --- a/TOOLS/matroska.py +++ b/TOOLS/matroska.py @@ -341,7 +341,7 @@ def generate_C_header(out): for el in elementlist: if not el.subelements: continue - printf(out, 'extern const struct ebml_elem_desc {0.structname}_desc;'.format(el)) + printf(out, f'extern const struct ebml_elem_desc {el.structname}_desc;') printf(out) printf(out, '#define MAX_EBML_SUBELEMENTS', max(len(el.subelements) @@ -431,7 +431,8 @@ def parse_one(s, depth, parent, maxlen): this_length = len(elid) / 2 + size + length if elem is not None: if elem.valtype != 'skip': - print(" " * depth, '[' + elid + ']', elem.name, 'size:', length, 'value:', end=' ') + indent = " " * depth + print(f"{indent} [{elid}] {elem.name} size: {length} value:", end=' ') if elem.valtype == 'sub': print('subelements:') while length > 0: diff --git a/TOOLS/osxbundle.py b/TOOLS/osxbundle.py index f096c3856e266..0bcfdf09e21d3 100755 --- a/TOOLS/osxbundle.py +++ b/TOOLS/osxbundle.py @@ -42,7 +42,8 @@ def sign_bundle(binary_name): resolved_dir = os.path.join(bundle_path(binary_name), dir) for root, _dirs, files in os.walk(resolved_dir): for f in files: - subprocess.run(['codesign', '--force', '-s', '-', os.path.join(root, f)]) + path = os.path.join(root, f) + subprocess.run(['codesign', '--force', '-s', '-', path]) subprocess.run(['codesign', '--force', '-s', '-', bundle_path(binary_name)]) def bundle_version(src_path): diff --git a/TOOLS/stats-conv.py b/TOOLS/stats-conv.py index 774e77bdcce72..e853d1d697a69 100755 --- a/TOOLS/stats-conv.py +++ b/TOOLS/stats-conv.py @@ -70,7 +70,16 @@ def get_event(event, evtype): G.events[event] = e return G.events[event] -colors = [(0.0, 0.5, 0.0), (0.0, 0.0, 1.0), (0.0, 0.0, 0.0), (1.0, 0.0, 0.0), (0.75, 0.75, 0), (0.0, 0.75, 0.75), (0.75, 0, 0.75)] +colors = [ + (0.0, 0.5, 0.0), + (0.0, 0.0, 1.0), + (0.0, 0.0, 0.0), + (1.0, 0.0, 0.0), + (0.75, 0.75, 0), + (0.0, 0.75, 0.75), + (0.75, 0, 0.75) +] + def mkColor(t): return pg.mkColor(int(t[0] * 255), int(t[1] * 255), int(t[2] * 255)) diff --git a/ci/lint-commit-msg.py b/ci/lint-commit-msg.py index 36497b66e45fe..e6ff310755d74 100755 --- a/ci/lint-commit-msg.py +++ b/ci/lint-commit-msg.py @@ -7,106 +7,110 @@ from typing import Dict, Tuple, Callable, Optional def call(cmd) -> str: - sys.stdout.flush() - ret = subprocess.run(cmd, check=True, stdout=subprocess.PIPE, text=True) - return ret.stdout + sys.stdout.flush() + ret = subprocess.run(cmd, check=True, stdout=subprocess.PIPE, text=True) + return ret.stdout lint_rules: Dict[str, Tuple[Callable, str]] = {} # A lint rule should return True if everything is okay def lint_rule(description: str): - def f(func): - assert func.__name__ not in lint_rules.keys() - lint_rules[func.__name__] = (func, description) - return f + def f(func): + assert func.__name__ not in lint_rules.keys() + lint_rules[func.__name__] = (func, description) + return f def get_commit_range() -> Optional[str]: - if len(sys.argv) > 1: - return sys.argv[1] - # https://github.com/actions/runner/issues/342#issuecomment-590670059 - event_name = os.environ["GITHUB_EVENT_NAME"] - with open(os.environ["GITHUB_EVENT_PATH"], "rb") as f: - event = json.load(f) - if event_name == "push": - if event["created"] or event["forced"]: - print("Skipping logic on branch creation or force-push") - return None - return event["before"] + "..." + event["after"] - elif event_name == "pull_request": - return event["pull_request"]["base"]["sha"] + ".." + event["pull_request"]["head"]["sha"] - return None + if len(sys.argv) > 1: + return sys.argv[1] + # https://github.com/actions/runner/issues/342#issuecomment-590670059 + event_name = os.environ["GITHUB_EVENT_NAME"] + with open(os.environ["GITHUB_EVENT_PATH"], "rb") as f: + event = json.load(f) + if event_name == "push": + if event["created"] or event["forced"]: + print("Skipping logic on branch creation or force-push") + return None + return event["before"] + "..." + event["after"] + elif event_name == "pull_request": + base = event["pull_request"]["base"]["sha"] + head = event["pull_request"]["head"]["sha"] + return f"{base}..{head}" + return None def do_lint(commit_range: str) -> bool: - commits = call(["git", "log", "--pretty=format:%H %s", commit_range]).splitlines() - print(f"Linting {len(commits)} commit(s):") - any_failed = False - for commit in commits: - sha, _, _ = commit.partition(' ') - body = call(["git", "show", "-s", "--format=%B", sha]).splitlines() - failed = [] - if len(body) == 0: - failed.append("* Commit message must not be empty") - else: - for k, v in lint_rules.items(): - if not v[0](body): - failed.append(f"* {v[1]} [{k}]") - if failed: - any_failed = True - print("-" * 40) - sys.stdout.flush() - subprocess.run(["git", "-P", "show", "-s", sha]) - print("\nhas the following issues:") - print("\n".join(failed)) - print("-" * 40) - return any_failed + commits = call(["git", "log", "--pretty=format:%H %s", commit_range]).splitlines() + print(f"Linting {len(commits)} commit(s):") + any_failed = False + for commit in commits: + sha, _, _ = commit.partition(' ') + body = call(["git", "show", "-s", "--format=%B", sha]).splitlines() + failed = [] + if len(body) == 0: + failed.append("* Commit message must not be empty") + else: + for k, v in lint_rules.items(): + if not v[0](body): + failed.append(f"* {v[1]} [{k}]") + if failed: + any_failed = True + print("-" * 40) + sys.stdout.flush() + subprocess.run(["git", "-P", "show", "-s", sha]) + print("\nhas the following issues:") + print("\n".join(failed)) + print("-" * 40) ################################################################################ -NO_PREFIX_WHITELIST = r"^Revert \"(.*)\"|^Reapply \"(.*)\"|^Release [0-9]|^Update MPV_VERSION$" +NO_PREFIX_WHITELIST = \ + r"^Revert \"(.*)\"|^Reapply \"(.*)\"|^Release [0-9]|^Update MPV_VERSION$" @lint_rule("Subject line must contain a prefix identifying the sub system") def subsystem_prefix(body): - return (re.search(NO_PREFIX_WHITELIST, body[0]) or - re.search(r"^[\w/\.{},-]+: ", body[0])) + return (re.search(NO_PREFIX_WHITELIST, body[0]) or + re.search(r"^[\w/\.{},-]+: ", body[0])) @lint_rule("First word after : must be lower case") def description_lowercase(body): - # Allow all caps for acronyms and options with -- - return (re.search(NO_PREFIX_WHITELIST, body[0]) or - re.search(r": (?:[A-Z]{2,} |--[a-z]|[a-z0-9])", body[0])) + # Allow all caps for acronyms and options with -- + return (re.search(NO_PREFIX_WHITELIST, body[0]) or + re.search(r": (?:[A-Z]{2,} |--[a-z]|[a-z0-9])", body[0])) @lint_rule("Subject line must not end with a full stop") def no_dot(body): - return not body[0].rstrip().endswith('.') + return not body[0].rstrip().endswith('.') @lint_rule("There must be an empty line between subject and extended description") def empty_line(body): - return len(body) == 1 or body[1].strip() == "" + return len(body) == 1 or body[1].strip() == "" # been seeing this one all over github lately, must be the webshits @lint_rule("Do not use 'conventional commits' style") def no_cc(body): - return not re.search(r"(?i)^(feat|fix|chore|refactor)[!:(]", body[0]) + return not re.search(r"(?i)^(feat|fix|chore|refactor)[!:(]", body[0]) @lint_rule("History must be linear, no merge commits") def no_merge(body): - return not body[0].startswith("Merge ") + return not body[0].startswith("Merge ") @lint_rule("Subject line should be shorter than 72 characters") def line_too_long(body): - revert = re.search(r"^Revert \"(.*)\"|^Reapply \"(.*)\"", body[0]) - return revert or len(body[0]) <= 72 + revert = re.search(r"^Revert \"(.*)\"|^Reapply \"(.*)\"", body[0]) + return revert or len(body[0]) <= 72 -@lint_rule("Prefix should not include file extension (use `vo_gpu: ...` not `vo_gpu.c: ...`)") +@lint_rule( + "Prefix should not include file extension (use `vo_gpu: ...` not `vo_gpu.c: ...`)" +) def no_file_exts(body): - return not re.search(r"[a-z0-9]\.([chm]|cpp|swift|py): ", body[0]) + return not re.search(r"[a-z0-9]\.([chm]|cpp|swift|py): ", body[0]) ################################################################################ if __name__ == "__main__": - commit_range = get_commit_range() - if commit_range is None: - exit(0) - print("Commit range:", commit_range) - any_failed = do_lint(commit_range) - exit(1 if any_failed else 0) + commit_range = get_commit_range() + if commit_range is None: + exit(0) + print("Commit range:", commit_range) + any_failed = do_lint(commit_range) + exit(1 if any_failed else 0) diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000000000..c2f7c1879bcf1 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,8 @@ +[tool.ruff] +line-length = 100 + +[tool.ruff.lint] +select = [ + "F", # pyflakes + "E", "W", # pycodestyle +] From 8a82882d5ec24d6a3a5030cd7be9a6aac12cf18b Mon Sep 17 00:00:00 2001 From: Nathan Ruiz Date: Sun, 15 Sep 2024 00:55:28 +0000 Subject: [PATCH 31/38] ci/lint: ensure double quotes are used in python --- TOOLS/docutils-wrapper.py | 12 +- TOOLS/dylib_unhell.py | 38 +-- TOOLS/file2string.py | 7 +- TOOLS/gen-interface-changes.py | 2 +- TOOLS/macos-sdk-version.py | 20 +- TOOLS/macos-swift-lib-directory.py | 2 +- TOOLS/matroska.py | 460 ++++++++++++++--------------- TOOLS/osxbundle.py | 18 +- TOOLS/stats-conv.py | 12 +- ci/lint-commit-msg.py | 4 +- pyproject.toml | 1 + 11 files changed, 288 insertions(+), 288 deletions(-) diff --git a/TOOLS/docutils-wrapper.py b/TOOLS/docutils-wrapper.py index 8e4ce57dc5060..41aa063a6b764 100755 --- a/TOOLS/docutils-wrapper.py +++ b/TOOLS/docutils-wrapper.py @@ -27,17 +27,17 @@ def convert_depfile(output, depfile): - with open(depfile, 'r') as f: + with open(depfile, "r") as f: deps = f.readlines() - with open(depfile, 'w') as f: + with open(depfile, "w") as f: f.write(os.path.abspath(output)) - f.write(': \\\n') + f.write(": \\\n") for dep in deps: dep = dep[:-1] - f.write('\t') + f.write("\t") f.write(os.path.abspath(dep)) - f.write(' \\\n') + f.write(" \\\n") def remove(path): try: @@ -51,7 +51,7 @@ def remove(path): output = argv[-1] for opt, optarg in zip(argv, argv[1:]): - if opt == '--record-dependencies': + if opt == "--record-dependencies": depfile = optarg try: diff --git a/TOOLS/dylib_unhell.py b/TOOLS/dylib_unhell.py index 73e853d5a4f2a..66d0a4474e0da 100755 --- a/TOOLS/dylib_unhell.py +++ b/TOOLS/dylib_unhell.py @@ -20,7 +20,7 @@ def is_user_lib(objfile, libname): "libSystem." not in libname and \ "libc." not in libname and \ "libgcc." not in libname and \ - not os.path.basename(libname) == 'Python' and \ + not os.path.basename(libname) == "Python" and \ os.path.basename(objfile) not in libname and \ "libswift" not in libname @@ -52,8 +52,8 @@ def get_rapths(objfile): for line in result.splitlines(): line_clean = pathRe.search(line).group(1).strip() # resolve @loader_path - if line_clean.startswith('@loader_path/'): - line_clean = line_clean[len('@loader_path/'):] + if line_clean.startswith("@loader_path/"): + line_clean = line_clean[len("@loader_path/"):] line_clean = os.path.join(os.path.dirname(objfile), line_clean) line_clean = os.path.normpath(line_clean) rpaths.append(line_clean) @@ -63,7 +63,7 @@ def get_rapths(objfile): def get_rpaths_dev_tools(binary): command = ( f"otool -l '{binary}' | grep -A2 LC_RPATH | grep path | " - "grep \"Xcode\\|CommandLineTools\"" + 'grep "Xcode\\|CommandLineTools"' ) result = subprocess.check_output(command, shell = True, universal_newlines=True) pathRe = re.compile(r"^\s*path (.*) \(offset \d*\)$") @@ -78,19 +78,19 @@ def resolve_lib_path(objfile, lib, rapths): if os.path.exists(lib): return lib - if lib.startswith('@rpath/'): - lib = lib[len('@rpath/'):] + if lib.startswith("@rpath/"): + lib = lib[len("@rpath/"):] for rpath in rapths: lib_path = os.path.join(rpath, lib) if os.path.exists(lib_path): return lib_path - elif lib.startswith('@loader_path/'): - lib = lib[len('@loader_path/'):] + elif lib.startswith("@loader_path/"): + lib = lib[len("@loader_path/"):] lib_path = os.path.normpath(os.path.join(objfile, lib)) if os.path.exists(lib_path): return lib_path - raise Exception('Could not resolve library: ' + lib) + raise Exception("Could not resolve library: " + lib) def check_vulkan_max_version(version): try: @@ -149,10 +149,10 @@ def libraries(objfile, result = dict(), result_relative = set(), rapths = []): return result, result_relative def lib_path(binary): - return os.path.join(os.path.dirname(binary), 'lib') + return os.path.join(os.path.dirname(binary), "lib") def resources_path(binary): - return os.path.join(os.path.dirname(binary), '../Resources') + return os.path.join(os.path.dirname(binary), "../Resources") def lib_name(lib): return os.path.join("@executable_path", "lib", os.path.basename(lib)) @@ -185,20 +185,20 @@ def process_libraries(libs_dict, libs_dyn, binary): install_name_tool_change(lib, lib_name(lib), binary) def process_swift_libraries(binary): - command = ['xcrun', '--find', 'swift-stdlib-tool'] + command = ["xcrun", "--find", "swift-stdlib-tool"] swiftStdlibTool = subprocess.check_output(command, universal_newlines=True).strip() # from xcode11 on the dynamic swift libs reside in a separate directory from # the std one, might need versioned paths for future swift versions - swiftLibPath = os.path.join(swiftStdlibTool, '../../lib/swift-5.0/macosx') + swiftLibPath = os.path.join(swiftStdlibTool, "../../lib/swift-5.0/macosx") swiftLibPath = os.path.abspath(swiftLibPath) command = [ - swiftStdlibTool, '--copy', '--platform', 'macosx', '--scan-executable', - binary, '--destination', lib_path(binary) + swiftStdlibTool, "--copy", "--platform", "macosx", "--scan-executable", + binary, "--destination", lib_path(binary) ] if os.path.exists(swiftLibPath): - command.extend(['--source-libraries', swiftLibPath]) + command.extend(["--source-libraries", swiftLibPath]) subprocess.check_output(command, universal_newlines=True) @@ -216,7 +216,7 @@ def process_vulkan_loader(binary, loaderName, loaderRelativeFolder, libraryNode) os.path.join(os.path.expanduser("~"), ".local/share", loaderRelativeFolder), os.path.join("/usr/local/share", loaderRelativeFolder), os.path.join("/usr/share/vulkan", loaderRelativeFolder), - os.path.join(get_homebrew_prefix(), 'share', loaderRelativeFolder), + os.path.join(get_homebrew_prefix(), "share", loaderRelativeFolder), ] loaderSystemFolder = "" @@ -241,7 +241,7 @@ def process_vulkan_loader(binary, loaderName, loaderRelativeFolder, libraryNode) if not os.path.exists(loaderBundleFolder): os.makedirs(loaderBundleFolder) - loaderSystemFile = open(loaderSystemPath, 'r') + loaderSystemFile = open(loaderSystemPath, "r") loaderJsonData = json.load(loaderSystemFile) libraryPath = loaderJsonData[libraryNode]["library_path"] librarySystemPath = os.path.join(loaderSystemFolder, libraryPath) @@ -251,7 +251,7 @@ def process_vulkan_loader(binary, loaderName, loaderRelativeFolder, libraryNode) return print(">>> modifiying and writing loader json " + loaderName) - loaderBundleFile = open(loaderBundlePath, 'w') + loaderBundleFile = open(loaderBundlePath, "w") loaderLibraryName = os.path.basename(librarySystemPath) library_path = os.path.join(libraryRelativeFolder, loaderLibraryName) loaderJsonData[libraryNode]["library_path"] = library_path diff --git a/TOOLS/file2string.py b/TOOLS/file2string.py index 93741324c8e85..094176df5e2b4 100755 --- a/TOOLS/file2string.py +++ b/TOOLS/file2string.py @@ -35,11 +35,10 @@ def file2string(infilename, infile, outfile): for c in safe_chars: conv[ord(c)] = c for c, esc in ("\nn", "\tt", r"\\", '""'): - conv[ord(c)] = '\\' + esc + conv[ord(c)] = "\\" + esc for line in infile: - outfile.write('"' + ''.join(conv[c] for c in line) + '"\n') + outfile.write('"' + "".join(conv[c] for c in line) + '"\n') if __name__ == "__main__": - - with open(sys.argv[1], 'rb') as infile, open(sys.argv[2], "w") as outfile: + with open(sys.argv[1], "rb") as infile, open(sys.argv[2], "w") as outfile: file2string(os.path.relpath(sys.argv[1], sys.argv[3]), infile, outfile) diff --git a/TOOLS/gen-interface-changes.py b/TOOLS/gen-interface-changes.py index e7747630f03c3..9d8d1b8f595d1 100755 --- a/TOOLS/gen-interface-changes.py +++ b/TOOLS/gen-interface-changes.py @@ -53,7 +53,7 @@ def add_new_entries(docs_dir, out, git): print(f"Usage: {sys.argv[0]} ") sys.exit(1) - git = which('git') + git = which("git") if not git: print("Unable to find git binary") sys.exit(1) diff --git a/TOOLS/macos-sdk-version.py b/TOOLS/macos-sdk-version.py index d487511bb1ad6..137b300f1bc13 100755 --- a/TOOLS/macos-sdk-version.py +++ b/TOOLS/macos-sdk-version.py @@ -10,27 +10,27 @@ from subprocess import check_output def find_macos_sdk(): - sdk = os.environ.get('MACOS_SDK', '') - sdk_version = os.environ.get('MACOS_SDK_VERSION', '0.0') - xcrun = which('xcrun') - xcodebuild = which('xcodebuild') + sdk = os.environ.get("MACOS_SDK", "") + sdk_version = os.environ.get("MACOS_SDK_VERSION", "0.0") + xcrun = which("xcrun") + xcodebuild = which("xcodebuild") if not xcrun: return sdk,sdk_version if not sdk: - sdk = check_output([xcrun, '--sdk', 'macosx', '--show-sdk-path'], + sdk = check_output([xcrun, "--sdk", "macosx", "--show-sdk-path"], encoding="UTF-8") # find macOS SDK paths and version - if sdk_version == '0.0': - sdk_version = check_output([xcrun, '--sdk', 'macosx', '--show-sdk-version'], + if sdk_version == "0.0": + sdk_version = check_output([xcrun, "--sdk", "macosx", "--show-sdk-version"], encoding="UTF-8") # use xcode tools when installed, still necessary for xcode versions <12.0 try: sdk_version = check_output( - [xcodebuild, '-sdk', 'macosx', '-version', 'ProductVersion'], + [xcodebuild, "-sdk", "macosx", "-version", "ProductVersion"], encoding="UTF-8", stderr=subprocess.DEVNULL ) @@ -38,10 +38,10 @@ def find_macos_sdk(): pass if not isinstance(sdk_version, str): - sdk_version = '10.10.0' + sdk_version = "10.10.0" return sdk.strip(),sdk_version.strip() if __name__ == "__main__": sdk_info = find_macos_sdk() - sys.stdout.write(','.join(sdk_info)) + sys.stdout.write(",".join(sdk_info)) diff --git a/TOOLS/macos-swift-lib-directory.py b/TOOLS/macos-swift-lib-directory.py index df967b14c1d68..2c2b1494138ec 100755 --- a/TOOLS/macos-swift-lib-directory.py +++ b/TOOLS/macos-swift-lib-directory.py @@ -9,7 +9,7 @@ from subprocess import check_output def find_swift_lib(): - swift_lib_dir = os.environ.get('SWIFT_LIB_DYNAMIC', '') + swift_lib_dir = os.environ.get("SWIFT_LIB_DYNAMIC", "") if swift_lib_dir: return swift_lib_dir diff --git a/TOOLS/matroska.py b/TOOLS/matroska.py index 79229d410ac46..6b0c8a4556b64 100755 --- a/TOOLS/matroska.py +++ b/TOOLS/matroska.py @@ -27,218 +27,218 @@ elements_ebml = ( - 'EBML, 1a45dfa3, sub', ( - 'EBMLVersion, 4286, uint', - 'EBMLReadVersion, 42f7, uint', - 'EBMLMaxIDLength, 42f2, uint', - 'EBMLMaxSizeLength, 42f3, uint', - 'DocType, 4282, str', - 'DocTypeVersion, 4287, uint', - 'DocTypeReadVersion, 4285, uint', + "EBML, 1a45dfa3, sub", ( + "EBMLVersion, 4286, uint", + "EBMLReadVersion, 42f7, uint", + "EBMLMaxIDLength, 42f2, uint", + "EBMLMaxSizeLength, 42f3, uint", + "DocType, 4282, str", + "DocTypeVersion, 4287, uint", + "DocTypeReadVersion, 4285, uint", ), - 'CRC32, bf, binary', - 'Void, ec, binary', + "CRC32, bf, binary", + "Void, ec, binary", ) elements_matroska = ( - 'Segment, 18538067, sub', ( + "Segment, 18538067, sub", ( - 'SeekHead*, 114d9b74, sub', ( - 'Seek*, 4dbb, sub', ( - 'SeekID, 53ab, ebml_id', - 'SeekPosition, 53ac, uint', + "SeekHead*, 114d9b74, sub", ( + "Seek*, 4dbb, sub", ( + "SeekID, 53ab, ebml_id", + "SeekPosition, 53ac, uint", ), ), - 'Info*, 1549a966, sub', ( - 'SegmentUID, 73a4, binary', - 'PrevUID, 3cb923, binary', - 'NextUID, 3eb923, binary', - 'TimecodeScale, 2ad7b1, uint', - 'DateUTC, 4461, sint', - 'Title, 7ba9, str', - 'MuxingApp, 4d80, str', - 'WritingApp, 5741, str', - 'Duration, 4489, float', + "Info*, 1549a966, sub", ( + "SegmentUID, 73a4, binary", + "PrevUID, 3cb923, binary", + "NextUID, 3eb923, binary", + "TimecodeScale, 2ad7b1, uint", + "DateUTC, 4461, sint", + "Title, 7ba9, str", + "MuxingApp, 4d80, str", + "WritingApp, 5741, str", + "Duration, 4489, float", ), - 'Cluster*, 1f43b675, sub', ( - 'Timecode, e7, uint', - 'BlockGroup*, a0, sub', ( - 'Block, a1, binary', - 'BlockDuration, 9b, uint', - 'ReferenceBlock*, fb, sint', - 'DiscardPadding, 75A2, sint', - 'BlockAdditions, 75A1, sub', ( - 'BlockMore*, A6, sub', ( - 'BlockAddID, EE, uint', - 'BlockAdditional, A5, binary', + "Cluster*, 1f43b675, sub", ( + "Timecode, e7, uint", + "BlockGroup*, a0, sub", ( + "Block, a1, binary", + "BlockDuration, 9b, uint", + "ReferenceBlock*, fb, sint", + "DiscardPadding, 75A2, sint", + "BlockAdditions, 75A1, sub", ( + "BlockMore*, A6, sub", ( + "BlockAddID, EE, uint", + "BlockAdditional, A5, binary", ), ), ), - 'SimpleBlock*, a3, binary', + "SimpleBlock*, a3, binary", ), - 'Tracks*, 1654ae6b, sub', ( - 'TrackEntry*, ae, sub', ( - 'TrackNumber, d7, uint', - 'TrackUID, 73c5, uint', - 'TrackType, 83, uint', - 'FlagEnabled, b9, uint', - 'FlagDefault, 88, uint', - 'FlagForced, 55aa, uint', - 'FlagLacing, 9c, uint', - 'MinCache, 6de7, uint', - 'MaxCache, 6df8, uint', - 'DefaultDuration, 23e383, uint', - 'TrackTimecodeScale, 23314f, float', - 'MaxBlockAdditionID, 55ee, uint', - 'Name, 536e, str', - 'Language, 22b59c, str', - 'LanguageBCP47, 22b59d, str', - 'CodecID, 86, str', - 'CodecPrivate, 63a2, binary', - 'CodecName, 258688, str', - 'CodecDecodeAll, aa, uint', - 'CodecDelay, 56aa, uint', - 'SeekPreRoll, 56bb, uint', - 'Video, e0, sub', ( - 'FlagInterlaced, 9a, uint', - 'PixelWidth, b0, uint', - 'PixelHeight, ba, uint', - 'DisplayWidth, 54b0, uint', - 'DisplayHeight, 54ba, uint', - 'DisplayUnit, 54b2, uint', - 'PixelCropTop, 54bb, uint', - 'PixelCropLeft, 54cc, uint', - 'PixelCropRight, 54dd, uint', - 'PixelCropBottom, 54aa, uint', - 'FrameRate, 2383e3, float', - 'ColourSpace, 2eb524, binary', - 'StereoMode, 53b8, uint', - 'Colour, 55b0, sub', ( - 'MatrixCoefficients, 55B1, uint', - 'BitsPerChannel, 55B2, uint', - 'ChromaSubsamplingHorz, 55B3, uint', - 'ChromaSubsamplingVert, 55B4, uint', - 'CbSubsamplingHorz, 55B5, uint', - 'CbSubsamplingVert, 55B6, uint', - 'ChromaSitingHorz, 55B7, uint', - 'ChromaSitingVert, 55B8, uint', - 'Range, 55B9, uint', - 'TransferCharacteristics, 55BA, uint', - 'Primaries, 55BB, uint', - 'MaxCLL, 55BC, uint', - 'MaxFALL, 55BD, uint', - 'MasteringMetadata, 55D0, sub', ( - 'PrimaryRChromaticityX, 55D1, float', - 'PrimaryRChromaticityY, 55D2, float', - 'PrimaryGChromaticityX, 55D3, float', - 'PrimaryGChromaticityY, 55D4, float', - 'PrimaryBChromaticityX, 55D5, float', - 'PrimaryBChromaticityY, 55D6, float', - 'WhitePointChromaticityX, 55D7, float', - 'WhitePointChromaticityY, 55D8, float', - 'LuminanceMax, 55D9, float', - 'LuminanceMin, 55DA, float', + "Tracks*, 1654ae6b, sub", ( + "TrackEntry*, ae, sub", ( + "TrackNumber, d7, uint", + "TrackUID, 73c5, uint", + "TrackType, 83, uint", + "FlagEnabled, b9, uint", + "FlagDefault, 88, uint", + "FlagForced, 55aa, uint", + "FlagLacing, 9c, uint", + "MinCache, 6de7, uint", + "MaxCache, 6df8, uint", + "DefaultDuration, 23e383, uint", + "TrackTimecodeScale, 23314f, float", + "MaxBlockAdditionID, 55ee, uint", + "Name, 536e, str", + "Language, 22b59c, str", + "LanguageBCP47, 22b59d, str", + "CodecID, 86, str", + "CodecPrivate, 63a2, binary", + "CodecName, 258688, str", + "CodecDecodeAll, aa, uint", + "CodecDelay, 56aa, uint", + "SeekPreRoll, 56bb, uint", + "Video, e0, sub", ( + "FlagInterlaced, 9a, uint", + "PixelWidth, b0, uint", + "PixelHeight, ba, uint", + "DisplayWidth, 54b0, uint", + "DisplayHeight, 54ba, uint", + "DisplayUnit, 54b2, uint", + "PixelCropTop, 54bb, uint", + "PixelCropLeft, 54cc, uint", + "PixelCropRight, 54dd, uint", + "PixelCropBottom, 54aa, uint", + "FrameRate, 2383e3, float", + "ColourSpace, 2eb524, binary", + "StereoMode, 53b8, uint", + "Colour, 55b0, sub", ( + "MatrixCoefficients, 55B1, uint", + "BitsPerChannel, 55B2, uint", + "ChromaSubsamplingHorz, 55B3, uint", + "ChromaSubsamplingVert, 55B4, uint", + "CbSubsamplingHorz, 55B5, uint", + "CbSubsamplingVert, 55B6, uint", + "ChromaSitingHorz, 55B7, uint", + "ChromaSitingVert, 55B8, uint", + "Range, 55B9, uint", + "TransferCharacteristics, 55BA, uint", + "Primaries, 55BB, uint", + "MaxCLL, 55BC, uint", + "MaxFALL, 55BD, uint", + "MasteringMetadata, 55D0, sub", ( + "PrimaryRChromaticityX, 55D1, float", + "PrimaryRChromaticityY, 55D2, float", + "PrimaryGChromaticityX, 55D3, float", + "PrimaryGChromaticityY, 55D4, float", + "PrimaryBChromaticityX, 55D5, float", + "PrimaryBChromaticityY, 55D6, float", + "WhitePointChromaticityX, 55D7, float", + "WhitePointChromaticityY, 55D8, float", + "LuminanceMax, 55D9, float", + "LuminanceMin, 55DA, float", ), ), - 'Projection, 7670, sub', ( - 'ProjectionType, 7671, uint', - 'ProjectionPrivate, 7672, binary', - 'ProjectionPoseYaw, 7673, float', - 'ProjectionPosePitch, 7674, float', - 'ProjectionPoseRoll, 7675, float', + "Projection, 7670, sub", ( + "ProjectionType, 7671, uint", + "ProjectionPrivate, 7672, binary", + "ProjectionPoseYaw, 7673, float", + "ProjectionPosePitch, 7674, float", + "ProjectionPoseRoll, 7675, float", ), ), - 'Audio, e1, sub', ( - 'SamplingFrequency, b5, float', - 'OutputSamplingFrequency, 78b5, float', - 'Channels, 9f, uint', - 'BitDepth, 6264, uint', + "Audio, e1, sub", ( + "SamplingFrequency, b5, float", + "OutputSamplingFrequency, 78b5, float", + "Channels, 9f, uint", + "BitDepth, 6264, uint", ), - 'ContentEncodings, 6d80, sub', ( - 'ContentEncoding*, 6240, sub', ( - 'ContentEncodingOrder, 5031, uint', - 'ContentEncodingScope, 5032, uint', - 'ContentEncodingType, 5033, uint', - 'ContentCompression, 5034, sub', ( - 'ContentCompAlgo, 4254, uint', - 'ContentCompSettings, 4255, binary', + "ContentEncodings, 6d80, sub", ( + "ContentEncoding*, 6240, sub", ( + "ContentEncodingOrder, 5031, uint", + "ContentEncodingScope, 5032, uint", + "ContentEncodingType, 5033, uint", + "ContentCompression, 5034, sub", ( + "ContentCompAlgo, 4254, uint", + "ContentCompSettings, 4255, binary", ), ), ), - 'BlockAdditionMapping*, 41e4, sub', ( - 'BlockAddIDValue, 41f0, uint', - 'BlockAddIDName, 41a4, str', - 'BlockAddIDType, 41e7, uint', - 'BlockAddIDExtraData, 41ed, binary', + "BlockAdditionMapping*, 41e4, sub", ( + "BlockAddIDValue, 41f0, uint", + "BlockAddIDName, 41a4, str", + "BlockAddIDType, 41e7, uint", + "BlockAddIDExtraData, 41ed, binary", ), ), ), - 'Cues, 1c53bb6b, sub', ( - 'CuePoint*, bb, sub', ( - 'CueTime, b3, uint', - 'CueTrackPositions*, b7, sub', ( - 'CueTrack, f7, uint', - 'CueClusterPosition, f1, uint', - 'CueRelativePosition, f0, uint', - 'CueDuration, b2, uint', + "Cues, 1c53bb6b, sub", ( + "CuePoint*, bb, sub", ( + "CueTime, b3, uint", + "CueTrackPositions*, b7, sub", ( + "CueTrack, f7, uint", + "CueClusterPosition, f1, uint", + "CueRelativePosition, f0, uint", + "CueDuration, b2, uint", ), ), ), - 'Attachments, 1941a469, sub', ( - 'AttachedFile*, 61a7, sub', ( - 'FileDescription, 467e, str', - 'FileName, 466e, str', - 'FileMimeType, 4660, str', - 'FileData, 465c, binary', - 'FileUID, 46ae, uint', + "Attachments, 1941a469, sub", ( + "AttachedFile*, 61a7, sub", ( + "FileDescription, 467e, str", + "FileName, 466e, str", + "FileMimeType, 4660, str", + "FileData, 465c, binary", + "FileUID, 46ae, uint", ), ), - 'Chapters, 1043a770, sub', ( - 'EditionEntry*, 45b9, sub', ( - 'EditionUID, 45bc, uint', - 'EditionFlagHidden, 45bd, uint', - 'EditionFlagDefault, 45db, uint', - 'EditionFlagOrdered, 45dd, uint', - 'ChapterAtom*, b6, sub', ( - 'ChapterUID, 73c4, uint', - 'ChapterTimeStart, 91, uint', - 'ChapterTimeEnd, 92, uint', - 'ChapterFlagHidden, 98, uint', - 'ChapterFlagEnabled, 4598, uint', - 'ChapterSegmentUID, 6e67, binary', - 'ChapterSegmentEditionUID, 6ebc, uint', - 'ChapterDisplay*, 80, sub', ( - 'ChapString, 85, str', - 'ChapLanguage*, 437c, str', - 'ChapLanguageBCP47*, 437d, str', - 'ChapCountry*, 437e, str', + "Chapters, 1043a770, sub", ( + "EditionEntry*, 45b9, sub", ( + "EditionUID, 45bc, uint", + "EditionFlagHidden, 45bd, uint", + "EditionFlagDefault, 45db, uint", + "EditionFlagOrdered, 45dd, uint", + "ChapterAtom*, b6, sub", ( + "ChapterUID, 73c4, uint", + "ChapterTimeStart, 91, uint", + "ChapterTimeEnd, 92, uint", + "ChapterFlagHidden, 98, uint", + "ChapterFlagEnabled, 4598, uint", + "ChapterSegmentUID, 6e67, binary", + "ChapterSegmentEditionUID, 6ebc, uint", + "ChapterDisplay*, 80, sub", ( + "ChapString, 85, str", + "ChapLanguage*, 437c, str", + "ChapLanguageBCP47*, 437d, str", + "ChapCountry*, 437e, str", ), ), ), ), - 'Tags*, 1254c367, sub', ( - 'Tag*, 7373, sub', ( - 'Targets, 63c0, sub', ( - 'TargetTypeValue, 68ca, uint', - 'TargetType, 63ca, str', - 'TargetTrackUID, 63c5, uint', - 'TargetEditionUID, 63c9, uint', - 'TargetChapterUID, 63c4, uint', - 'TargetAttachmentUID, 63c6, uint', + "Tags*, 1254c367, sub", ( + "Tag*, 7373, sub", ( + "Targets, 63c0, sub", ( + "TargetTypeValue, 68ca, uint", + "TargetType, 63ca, str", + "TargetTrackUID, 63c5, uint", + "TargetEditionUID, 63c9, uint", + "TargetChapterUID, 63c4, uint", + "TargetAttachmentUID, 63c6, uint", ), - 'SimpleTag*, 67c8, sub', ( - 'TagName, 45a3, str', - 'TagLanguage, 447a, str', - 'TagLanguageBCP47, 447b, str', - 'TagString, 4487, str', - 'TagDefault, 4484, uint', + "SimpleTag*, 67c8, sub", ( + "TagName, 45a3, str", + "TagLanguage, 447a, str", + "TagLanguageBCP47, 447b, str", + "TagString, 4487, str", + "TagDefault, 4484, uint", ), ), ), @@ -261,29 +261,29 @@ def camelcase_to_words(name): parts.append(name[start:i]) start = i parts.append(name[start:]) - return '_'.join(parts).lower() + return "_".join(parts).lower() class MatroskaElement(object): def __init__(self, name, elid, valtype, namespace): self.name = name - self.definename = '{0}_ID_{1}'.format(namespace, name.upper()) + self.definename = "{0}_ID_{1}".format(namespace, name.upper()) self.fieldname = camelcase_to_words(name) - self.structname = 'ebml_' + self.fieldname + self.structname = "ebml_" + self.fieldname self.elid = elid self.valtype = valtype - if valtype == 'sub': - self.ebmltype = 'EBML_TYPE_SUBELEMENTS' - self.valname = 'struct ' + self.structname + if valtype == "sub": + self.ebmltype = "EBML_TYPE_SUBELEMENTS" + self.valname = "struct " + self.structname else: - self.ebmltype = 'EBML_TYPE_' + valtype.upper() + self.ebmltype = "EBML_TYPE_" + valtype.upper() try: - self.valname = {'uint': 'uint64_t', 'str': 'char *', - 'binary': 'bstr', 'ebml_id': 'uint32_t', - 'float': 'double', 'sint': 'int64_t', + self.valname = {"uint": "uint64_t", "str": "char *", + "binary": "bstr", "ebml_id": "uint32_t", + "float": "double", "sint": "int64_t", }[valtype] except KeyError: - raise SyntaxError('Unrecognized value type ' + valtype) + raise SyntaxError("Unrecognized value type " + valtype) self.subelements = () def add_subelements(self, subelements): @@ -296,10 +296,10 @@ def parse_elems(elements, namespace): subelements = [] for el in elements: if isinstance(el, str): - name, hexid, eltype = [x.strip() for x in el.split(',')] + name, hexid, eltype = [x.strip() for x in el.split(",")] hexid = hexid.lower() - multiple = name.endswith('*') - name = name.strip('*') + multiple = name.endswith("*") + name = name.strip("*") new = MatroskaElement(name, hexid, eltype, namespace) elementd[hexid] = new elementlist.append(new) @@ -308,19 +308,19 @@ def parse_elems(elements, namespace): new.add_subelements(parse_elems(el, namespace)) return subelements -parse_elems(elements_ebml, 'EBML') -parse_elems(elements_matroska, 'MATROSKA') +parse_elems(elements_ebml, "EBML") +parse_elems(elements_matroska, "MATROSKA") def printf(out, *args): - out.write(' '.join(str(x) for x in args)) - out.write('\n') + out.write(" ".join(str(x) for x in args)) + out.write("\n") def generate_C_header(out): - printf(out, '// Generated by TOOLS/matroska.py, do not edit manually') + printf(out, "// Generated by TOOLS/matroska.py, do not edit manually") printf(out) for el in elementlist: - printf(out, '#define {0.definename:40} 0x{0.elid}'.format(el)) + printf(out, "#define {0.definename:40} 0x{0.elid}".format(el)) printf(out) @@ -328,39 +328,39 @@ def generate_C_header(out): if not el.subelements: continue printf(out) - printf(out, 'struct {0.structname} {{'.format(el)) + printf(out, "struct {0.structname} {{".format(el)) length = max(len(subel.valname) for subel, multiple in el.subelements)+1 for subel, multiple in el.subelements: - printf(out, ' {e.valname:{length}} {star}{e.fieldname};'.format( - e=subel, length=length, star=' *'[multiple])) + printf(out, " {e.valname:{length}} {star}{e.fieldname};".format( + e=subel, length=length, star=" *"[multiple])) printf(out) for subel, multiple in el.subelements: - printf(out, ' int n_{0.fieldname};'.format(subel)) - printf(out, '};') + printf(out, " int n_{0.fieldname};".format(subel)) + printf(out, "};") for el in elementlist: if not el.subelements: continue - printf(out, f'extern const struct ebml_elem_desc {el.structname}_desc;') + printf(out, f"extern const struct ebml_elem_desc {el.structname}_desc;") printf(out) - printf(out, '#define MAX_EBML_SUBELEMENTS', max(len(el.subelements) + printf(out, "#define MAX_EBML_SUBELEMENTS", max(len(el.subelements) for el in elementlist)) def generate_C_definitions(out): - printf(out, '// Generated by TOOLS/matroska.py, do not edit manually') + printf(out, "// Generated by TOOLS/matroska.py, do not edit manually") printf(out) for el in reversed(elementlist): printf(out) if el.subelements: - printf(out, '#define N', el.fieldname) + printf(out, "#define N", el.fieldname) printf(out, 'E_S("{0}", {1})'.format(el.name, len(el.subelements))) for subel, multiple in el.subelements: - printf(out, 'F({0.definename}, {0.fieldname}, {1})'.format( + printf(out, "F({0.definename}, {0.fieldname}, {1})".format( subel, int(multiple))) - printf(out, '}};') - printf(out, '#undef N') + printf(out, "}};") + printf(out, "#undef N") else: printf(out, 'E("{0.name}", {0.fieldname}, {0.ebmltype})'.format(el)) @@ -425,48 +425,48 @@ def read_float(s, length): return f def parse_one(s, depth, parent, maxlen): - elid = hexlify(read_id(s)).decode('ascii') + elid = hexlify(read_id(s)).decode("ascii") elem = elementd.get(elid) size, length = read_vint(s) this_length = len(elid) / 2 + size + length if elem is not None: - if elem.valtype != 'skip': + if elem.valtype != "skip": indent = " " * depth - print(f"{indent} [{elid}] {elem.name} size: {length} value:", end=' ') - if elem.valtype == 'sub': - print('subelements:') + print(f"{indent} [{elid}] {elem.name} size: {length} value:", end=" ") + if elem.valtype == "sub": + print("subelements:") while length > 0: length -= parse_one(s, depth + 1, elem, length) if length < 0: raise SyntaxError - elif elem.valtype == 'str': - print('string', repr(read_str(s, length).decode('utf8', 'replace'))) - elif elem.valtype in ('binary', 'ebml_id'): + elif elem.valtype == "str": + print("string", repr(read_str(s, length).decode("utf8", "replace"))) + elif elem.valtype in ("binary", "ebml_id"): t = read_str(s, length) - dec = '' - if elem.valtype == 'ebml_id': - idelem = elementd.get(hexlify(t).decode('ascii')) + dec = "" + if elem.valtype == "ebml_id": + idelem = elementd.get(hexlify(t).decode("ascii")) if idelem is None: - dec = '(UNKNOWN)' + dec = "(UNKNOWN)" else: - dec = '({0.name})'.format(idelem) + dec = "({0.name})".format(idelem) if len(t) < 20: - t = hexlify(t).decode('ascii') + t = hexlify(t).decode("ascii") else: - t = '<{0} bytes>'.format(len(t)) - print('binary', t, dec) - elif elem.valtype == 'uint': - print('uint', read_uint(s, length)) - elif elem.valtype == 'sint': - print('sint', read_sint(s, length)) - elif elem.valtype == 'float': - print('float', read_float(s, length)) - elif elem.valtype == 'skip': + t = "<{0} bytes>".format(len(t)) + print("binary", t, dec) + elif elem.valtype == "uint": + print("uint", read_uint(s, length)) + elif elem.valtype == "sint": + print("sint", read_sint(s, length)) + elif elem.valtype == "float": + print("float", read_float(s, length)) + elif elem.valtype == "skip": read(s, length) else: raise NotImplementedError else: - print(" " * depth, '[' + elid + '] Unknown element! size:', length) + print(" " * depth, "[" + elid + "] Unknown element! size:", length) read(s, length) return this_length @@ -474,9 +474,9 @@ def parse_one(s, depth, parent, maxlen): def parse_toplevel(s): parse_one(s, 0, None, 1 << 63) - if sys.argv[1] == '--generate-header': + if sys.argv[1] == "--generate-header": generate_C_header(open(sys.argv[2], "w")) - elif sys.argv[1] == '--generate-definitions': + elif sys.argv[1] == "--generate-definitions": generate_C_definitions(open(sys.argv[2], "w")) else: s = open(sys.argv[1], "rb") diff --git a/TOOLS/osxbundle.py b/TOOLS/osxbundle.py index 0bcfdf09e21d3..c440918e5fa84 100755 --- a/TOOLS/osxbundle.py +++ b/TOOLS/osxbundle.py @@ -13,10 +13,10 @@ def bundle_name(binary_name): return os.path.basename(bundle_path(binary_name)) def target_plist(binary_name): - return os.path.join(bundle_path(binary_name), 'Contents', 'Info.plist') + return os.path.join(bundle_path(binary_name), "Contents", "Info.plist") def target_directory(binary_name): - return os.path.join(bundle_path(binary_name), 'Contents', 'MacOS') + return os.path.join(bundle_path(binary_name), "Contents", "MacOS") def target_binary(binary_name): return os.path.join(target_directory(binary_name), @@ -26,7 +26,7 @@ def copy_bundle(binary_name, src_path): if os.path.isdir(bundle_path(binary_name)): shutil.rmtree(bundle_path(binary_name)) shutil.copytree( - os.path.join(src_path, 'TOOLS', 'osxbundle', bundle_name(binary_name)), + os.path.join(src_path, "TOOLS", "osxbundle", bundle_name(binary_name)), bundle_path(binary_name)) def copy_binary(binary_name): @@ -34,21 +34,21 @@ def copy_binary(binary_name): def apply_plist_template(plist_file, version): for line in fileinput.input(plist_file, inplace=1): - print(line.rstrip().replace('${VERSION}', version)) + print(line.rstrip().replace("${VERSION}", version)) def sign_bundle(binary_name): - sign_directories = ['Contents/Frameworks', 'Contents/MacOS'] + sign_directories = ["Contents/Frameworks", "Contents/MacOS"] for dir in sign_directories: resolved_dir = os.path.join(bundle_path(binary_name), dir) for root, _dirs, files in os.walk(resolved_dir): for f in files: path = os.path.join(root, f) - subprocess.run(['codesign', '--force', '-s', '-', path]) - subprocess.run(['codesign', '--force', '-s', '-', bundle_path(binary_name)]) + subprocess.run(["codesign", "--force", "-s", "-", path]) + subprocess.run(["codesign", "--force", "-s", "-", bundle_path(binary_name)]) def bundle_version(src_path): - version = 'UNKNOWN' - version_path = os.path.join(src_path, 'MPV_VERSION') + version = "UNKNOWN" + version_path = os.path.join(src_path, "MPV_VERSION") if os.path.exists(version_path): x = open(version_path) version = x.read() diff --git a/TOOLS/stats-conv.py b/TOOLS/stats-conv.py index e853d1d697a69..794c41fc57d6b 100755 --- a/TOOLS/stats-conv.py +++ b/TOOLS/stats-conv.py @@ -149,8 +149,8 @@ def mkColor(t): else: e.vals = [(x, y * (m - index) / m) for (x, y) in e.vals] -pg.setConfigOption('background', 'w') -pg.setConfigOption('foreground', 'k') +pg.setConfigOption("background", "w") +pg.setConfigOption("foreground", "k") app = QtWidgets.QApplication([]) win = pg.GraphicsLayoutWidget() win.show() @@ -172,13 +172,13 @@ def mkColor(t): cur = ax[1 if e.type == "value" else 0] if cur not in G.curveno: G.curveno[cur] = 0 - args = {'name': e.name,'antialias':True} + args = {"name": e.name,"antialias":True} color = mkColor(colors[G.curveno[cur] % len(colors)]) if e.type == "event-signal": - args['symbol'] = e.marker - args['symbolBrush'] = pg.mkBrush(color, width=0) + args["symbol"] = e.marker + args["symbolBrush"] = pg.mkBrush(color, width=0) else: - args['pen'] = pg.mkPen(color, width=0) + args["pen"] = pg.mkPen(color, width=0) G.curveno[cur] += 1 cur.plot(*zip(*e.vals), **args) diff --git a/ci/lint-commit-msg.py b/ci/lint-commit-msg.py index e6ff310755d74..859519080ad73 100755 --- a/ci/lint-commit-msg.py +++ b/ci/lint-commit-msg.py @@ -43,7 +43,7 @@ def do_lint(commit_range: str) -> bool: print(f"Linting {len(commits)} commit(s):") any_failed = False for commit in commits: - sha, _, _ = commit.partition(' ') + sha, _, _ = commit.partition(" ") body = call(["git", "show", "-s", "--format=%B", sha]).splitlines() failed = [] if len(body) == 0: @@ -79,7 +79,7 @@ def description_lowercase(body): @lint_rule("Subject line must not end with a full stop") def no_dot(body): - return not body[0].rstrip().endswith('.') + return not body[0].rstrip().endswith(".") @lint_rule("There must be an empty line between subject and extended description") def empty_line(body): diff --git a/pyproject.toml b/pyproject.toml index c2f7c1879bcf1..cca05c6e4e806 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,4 +5,5 @@ line-length = 100 select = [ "F", # pyflakes "E", "W", # pycodestyle + "Q", # flake8-quotes ] From 1562895af7b537d620536e6a060942bcda595289 Mon Sep 17 00:00:00 2001 From: Nathan Ruiz Date: Sun, 15 Sep 2024 12:08:30 +0000 Subject: [PATCH 32/38] ci/lint: add pyupgrade check --- TOOLS/docutils-wrapper.py | 2 +- TOOLS/dylib_unhell.py | 102 ++++++++++++++++------------- TOOLS/file2string.py | 5 +- TOOLS/gen-interface-changes.py | 5 +- TOOLS/gen-mpv-desktop.py | 2 +- TOOLS/macos-swift-lib-directory.py | 2 +- TOOLS/matroska.py | 26 ++++---- TOOLS/osxbundle.py | 10 +-- TOOLS/stats-conv.py | 11 ++-- ci/lint-commit-msg.py | 13 ++-- pyproject.toml | 1 + 11 files changed, 97 insertions(+), 82 deletions(-) diff --git a/TOOLS/docutils-wrapper.py b/TOOLS/docutils-wrapper.py index 41aa063a6b764..23c3552fd229e 100755 --- a/TOOLS/docutils-wrapper.py +++ b/TOOLS/docutils-wrapper.py @@ -27,7 +27,7 @@ def convert_depfile(output, depfile): - with open(depfile, "r") as f: + with open(depfile) as f: deps = f.readlines() with open(depfile, "w") as f: diff --git a/TOOLS/dylib_unhell.py b/TOOLS/dylib_unhell.py index 66d0a4474e0da..871cd5d7116f0 100755 --- a/TOOLS/dylib_unhell.py +++ b/TOOLS/dylib_unhell.py @@ -1,11 +1,11 @@ #!/usr/bin/env python3 -import re +import json import os -import sys +import re import shutil import subprocess -import json +import sys from functools import partial sys_re = re.compile("^/System") @@ -20,13 +20,13 @@ def is_user_lib(objfile, libname): "libSystem." not in libname and \ "libc." not in libname and \ "libgcc." not in libname and \ - not os.path.basename(libname) == "Python" and \ + os.path.basename(libname) != "Python" and \ os.path.basename(objfile) not in libname and \ "libswift" not in libname def otool(objfile, rapths): - command = "otool -L '%s' | grep -e '\t' | awk '{ print $1 }'" % objfile - output = subprocess.check_output(command, shell = True, universal_newlines=True) + command = f"otool -L '{objfile}' | grep -e '\t' | awk '{{ print $1 }}'" + output = subprocess.check_output(command, shell=True, universal_newlines=True) libs = set(filter(partial(is_user_lib, objfile), output.split())) libs_resolved = set() @@ -41,16 +41,16 @@ def otool(objfile, rapths): def get_rapths(objfile): rpaths = [] - command = "otool -l '%s' | grep -A2 LC_RPATH | grep path" % objfile - pathRe = re.compile(r"^\s*path (.*) \(offset \d*\)$") + command = f"otool -l '{objfile}' | grep -A2 LC_RPATH | grep path" + path_re = re.compile(r"^\s*path (.*) \(offset \d*\)$") try: - result = subprocess.check_output(command, shell = True, universal_newlines=True) + result = subprocess.check_output(command, shell=True, universal_newlines=True) except Exception: return rpaths for line in result.splitlines(): - line_clean = pathRe.search(line).group(1).strip() + line_clean = path_re.search(line).group(1).strip() # resolve @loader_path if line_clean.startswith("@loader_path/"): line_clean = line_clean[len("@loader_path/"):] @@ -66,13 +66,11 @@ def get_rpaths_dev_tools(binary): 'grep "Xcode\\|CommandLineTools"' ) result = subprocess.check_output(command, shell = True, universal_newlines=True) - pathRe = re.compile(r"^\s*path (.*) \(offset \d*\)$") - output = [] - - for line in result.splitlines(): - output.append(pathRe.search(line).group(1).strip()) - - return output + path_re = re.compile(r"^\s*path (.*) \(offset \d*\)$") + return [ + path_re.search(line).group(1).strip() + for line in result.splitlines() + ] def resolve_lib_path(objfile, lib, rapths): if os.path.exists(lib): @@ -108,10 +106,9 @@ def get_homebrew_prefix(): result = "/opt/homebrew" try: result = subprocess.check_output( - "brew --prefix", + ["brew", "--prefix"], universal_newlines=True, - shell=True, - stderr=subprocess.DEVNULL + stderr=subprocess.DEVNULL, ).strip() except Exception: pass @@ -136,7 +133,16 @@ def install_name_tool_add_rpath(rpath, binary): def install_name_tool_delete_rpath(rpath, binary): subprocess.call(["install_name_tool", "-delete_rpath", rpath, binary]) -def libraries(objfile, result = dict(), result_relative = set(), rapths = []): +def libraries(objfile, result=None, result_relative=None, rapths=None): + if result is None: + result = {} + + if result_relative is None: + result_relative = set() + + if rapths is None: + rapths = [] + rapths = get_rapths(objfile) + rapths libs_list, libs_relative = otool(objfile, rapths) result[objfile] = libs_list @@ -185,38 +191,40 @@ def process_libraries(libs_dict, libs_dyn, binary): install_name_tool_change(lib, lib_name(lib), binary) def process_swift_libraries(binary): - command = ["xcrun", "--find", "swift-stdlib-tool"] - swiftStdlibTool = subprocess.check_output(command, universal_newlines=True).strip() + swift_stdlib_tool = subprocess.check_output( + ["xcrun", "--find", "swift-stdlib-tool"], + universal_newlines=True, + ).strip() # from xcode11 on the dynamic swift libs reside in a separate directory from # the std one, might need versioned paths for future swift versions - swiftLibPath = os.path.join(swiftStdlibTool, "../../lib/swift-5.0/macosx") - swiftLibPath = os.path.abspath(swiftLibPath) + swift_lib_path = os.path.join(swift_stdlib_tool, "../../lib/swift-5.0/macosx") + swift_lib_path = os.path.abspath(swift_lib_path) command = [ - swiftStdlibTool, "--copy", "--platform", "macosx", "--scan-executable", - binary, "--destination", lib_path(binary) + swift_stdlib_tool, "--copy", "--platform", "macosx", + "--scan-executable", binary, "--destination", lib_path(binary), ] - if os.path.exists(swiftLibPath): - command.extend(["--source-libraries", swiftLibPath]) + if os.path.exists(swift_lib_path): + command.extend(["--source-libraries", swift_lib_path]) subprocess.check_output(command, universal_newlines=True) print(">> setting additional rpath for swift libraries") install_name_tool_add_rpath("@executable_path/lib", binary) -def process_vulkan_loader(binary, loaderName, loaderRelativeFolder, libraryNode): +def process_vulkan_loader(binary, loader_name, loader_relative_folder, library_node): # https://github.com/KhronosGroup/Vulkan-Loader/blob/main/docs/LoaderDriverInterface.md#example-macos-driver-search-path # https://github.com/KhronosGroup/Vulkan-Loader/blob/main/docs/LoaderLayerInterface.md#macos-layer-discovery loaderSystemSearchFolders = [ - os.path.join(os.path.expanduser("~"), ".config", loaderRelativeFolder), - os.path.join("/etc/xdg", loaderRelativeFolder), - os.path.join("/usr/local/etc", loaderRelativeFolder), - os.path.join("/etc", loaderRelativeFolder), - os.path.join(os.path.expanduser("~"), ".local/share", loaderRelativeFolder), - os.path.join("/usr/local/share", loaderRelativeFolder), - os.path.join("/usr/share/vulkan", loaderRelativeFolder), - os.path.join(get_homebrew_prefix(), "share", loaderRelativeFolder), + os.path.join(os.path.expanduser("~"), ".config", loader_relative_folder), + os.path.join("/etc/xdg", loader_relative_folder), + os.path.join("/usr/local/etc", loader_relative_folder), + os.path.join("/etc", loader_relative_folder), + os.path.join(os.path.expanduser("~"), ".local/share", loader_relative_folder), + os.path.join("/usr/local/share", loader_relative_folder), + os.path.join("/usr/share/vulkan", loader_relative_folder), + os.path.join(get_homebrew_prefix(), "share", loader_relative_folder), ] loaderSystemFolder = "" @@ -226,35 +234,35 @@ def process_vulkan_loader(binary, loaderName, loaderRelativeFolder, libraryNode) break if not loaderSystemFolder: - print(">>> could not find loader folder " + loaderRelativeFolder) + print(">>> could not find loader folder " + loader_relative_folder) return - loaderBundleFolder = os.path.join(resources_path(binary), loaderRelativeFolder) - loaderSystemPath = os.path.join(loaderSystemFolder, loaderName) - loaderBundlePath = os.path.join(loaderBundleFolder, loaderName) + loaderBundleFolder = os.path.join(resources_path(binary), loader_relative_folder) + loaderSystemPath = os.path.join(loaderSystemFolder, loader_name) + loaderBundlePath = os.path.join(loaderBundleFolder, loader_name) libraryRelativeFolder = "../../../Frameworks/" if not os.path.exists(loaderSystemPath): - print(">>> could not find loader " + loaderName) + print(">>> could not find loader " + loader_name) return if not os.path.exists(loaderBundleFolder): os.makedirs(loaderBundleFolder) - loaderSystemFile = open(loaderSystemPath, "r") + loaderSystemFile = open(loaderSystemPath) loaderJsonData = json.load(loaderSystemFile) - libraryPath = loaderJsonData[libraryNode]["library_path"] + libraryPath = loaderJsonData[library_node]["library_path"] librarySystemPath = os.path.join(loaderSystemFolder, libraryPath) if not os.path.exists(librarySystemPath): print(">>> could not find loader library " + librarySystemPath) return - print(">>> modifiying and writing loader json " + loaderName) + print(">>> modifiying and writing loader json " + loader_name) loaderBundleFile = open(loaderBundlePath, "w") loaderLibraryName = os.path.basename(librarySystemPath) library_path = os.path.join(libraryRelativeFolder, loaderLibraryName) - loaderJsonData[libraryNode]["library_path"] = library_path + loaderJsonData[library_node]["library_path"] = library_path json.dump(loaderJsonData, loaderBundleFile, indent=4) print(">>> copying loader library " + loaderLibraryName) diff --git a/TOOLS/file2string.py b/TOOLS/file2string.py index 094176df5e2b4..93efcc0ee6876 100755 --- a/TOOLS/file2string.py +++ b/TOOLS/file2string.py @@ -25,10 +25,11 @@ import os import sys + def file2string(infilename, infile, outfile): - outfile.write("// Generated from %s\n\n" % infilename) + outfile.write(f"// Generated from {infilename}\n\n") - conv = ["\\%03o" % c for c in range(256)] + conv = [f"\\{c:03o}" for c in range(256)] safe_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" \ "0123456789!#%&'()*+,-./:;<=>[]^_{|}~ " diff --git a/TOOLS/gen-interface-changes.py b/TOOLS/gen-interface-changes.py index 9d8d1b8f595d1..affbe92054008 100755 --- a/TOOLS/gen-interface-changes.py +++ b/TOOLS/gen-interface-changes.py @@ -26,11 +26,12 @@ from shutil import which from subprocess import check_output + def add_new_entries(docs_dir, out, git): changes_dir = pathlib.Path(docs_dir) / "interface-changes" files = [] for f in pathlib.Path(changes_dir).glob("*.txt"): - if f.is_file() and not f.name == "example.txt": + if f.is_file() and f.name != "example.txt": timestamp = check_output([git, "log", "--format=%ct", "-n", "1", "--", f], encoding="UTF-8") if timestamp: @@ -73,7 +74,7 @@ def add_new_entries(docs_dir, out, git): docs_dir = pathlib.Path(sys.argv[0]).resolve().parents[1] / "DOCS" interface_changes = docs_dir / "interface-changes.rst" - with open(interface_changes, "r") as f: + with open(interface_changes) as f: lines = [line.rstrip() for line in f] ver_line = " --- mpv 0." + major_version + ".0 ---" diff --git a/TOOLS/gen-mpv-desktop.py b/TOOLS/gen-mpv-desktop.py index f09498bb8213e..681633acda3e8 100755 --- a/TOOLS/gen-mpv-desktop.py +++ b/TOOLS/gen-mpv-desktop.py @@ -24,7 +24,7 @@ from subprocess import check_output if __name__ == "__main__": - with open(sys.argv[1], "r", encoding="UTF-8") as f: + with open(sys.argv[1], encoding="UTF-8") as f: next(f) mpv_desktop = dict([line.split("=", 1) for line in f]) diff --git a/TOOLS/macos-swift-lib-directory.py b/TOOLS/macos-swift-lib-directory.py index 2c2b1494138ec..72b79d9d18e0d 100755 --- a/TOOLS/macos-swift-lib-directory.py +++ b/TOOLS/macos-swift-lib-directory.py @@ -29,7 +29,7 @@ def find_swift_lib(): swift_lib_dir = os.path.join( xcode_path, - "Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx" + "Toolchains/XcodeDefault.xctoolchain/usr/lib/swift/macosx", ) if os.path.isdir(swift_lib_dir): return swift_lib_dir diff --git a/TOOLS/matroska.py b/TOOLS/matroska.py index 6b0c8a4556b64..9de9b07340533 100755 --- a/TOOLS/matroska.py +++ b/TOOLS/matroska.py @@ -5,8 +5,8 @@ """ import sys -from math import ldexp from binascii import hexlify +from math import ldexp # # This file is part of mpv. @@ -263,11 +263,11 @@ def camelcase_to_words(name): parts.append(name[start:]) return "_".join(parts).lower() -class MatroskaElement(object): +class MatroskaElement: def __init__(self, name, elid, valtype, namespace): self.name = name - self.definename = "{0}_ID_{1}".format(namespace, name.upper()) + self.definename = f"{namespace}_ID_{name.upper()}" self.fieldname = camelcase_to_words(name) self.structname = "ebml_" + self.fieldname self.elid = elid @@ -296,7 +296,7 @@ def parse_elems(elements, namespace): subelements = [] for el in elements: if isinstance(el, str): - name, hexid, eltype = [x.strip() for x in el.split(",")] + name, hexid, eltype = (x.strip() for x in el.split(",")) hexid = hexid.lower() multiple = name.endswith("*") name = name.strip("*") @@ -320,7 +320,7 @@ def generate_C_header(out): printf(out) for el in elementlist: - printf(out, "#define {0.definename:40} 0x{0.elid}".format(el)) + printf(out, f"#define {el.definename:40} 0x{el.elid}") printf(out) @@ -328,14 +328,14 @@ def generate_C_header(out): if not el.subelements: continue printf(out) - printf(out, "struct {0.structname} {{".format(el)) + printf(out, f"struct {el.structname} {{") length = max(len(subel.valname) for subel, multiple in el.subelements)+1 for subel, multiple in el.subelements: printf(out, " {e.valname:{length}} {star}{e.fieldname};".format( e=subel, length=length, star=" *"[multiple])) printf(out) for subel, multiple in el.subelements: - printf(out, " int n_{0.fieldname};".format(subel)) + printf(out, f" int n_{subel.fieldname};") printf(out, "};") for el in elementlist: @@ -355,14 +355,14 @@ def generate_C_definitions(out): printf(out) if el.subelements: printf(out, "#define N", el.fieldname) - printf(out, 'E_S("{0}", {1})'.format(el.name, len(el.subelements))) + printf(out, f'E_S("{el.name}", {len(el.subelements)})') for subel, multiple in el.subelements: - printf(out, "F({0.definename}, {0.fieldname}, {1})".format( - subel, int(multiple))) + msg = f"F({subel.definename}, {subel.fieldname}, {int(multiple)})" + printf(out, msg) printf(out, "}};") printf(out, "#undef N") else: - printf(out, 'E("{0.name}", {0.fieldname}, {0.ebmltype})'.format(el)) + printf(out, f'E("{el.name}", {el.fieldname}, {el.ebmltype})') def read(s, length): t = s.read(length) @@ -449,11 +449,11 @@ def parse_one(s, depth, parent, maxlen): if idelem is None: dec = "(UNKNOWN)" else: - dec = "({0.name})".format(idelem) + dec = f"({idelem.name})" if len(t) < 20: t = hexlify(t).decode("ascii") else: - t = "<{0} bytes>".format(len(t)) + t = f"<{len(t)} bytes>" print("binary", t, dec) elif elem.valtype == "uint": print("uint", read_uint(s, length)) diff --git a/TOOLS/osxbundle.py b/TOOLS/osxbundle.py index c440918e5fa84..c21661c3180ae 100755 --- a/TOOLS/osxbundle.py +++ b/TOOLS/osxbundle.py @@ -1,13 +1,15 @@ #!/usr/bin/env python3 +import fileinput import os import shutil -import fileinput -import dylib_unhell import subprocess from optparse import OptionParser +import dylib_unhell + + def bundle_path(binary_name): - return "%s.app" % binary_name + return f"{binary_name}.app" def bundle_name(binary_name): return os.path.basename(bundle_path(binary_name)) @@ -72,7 +74,7 @@ def main(): version = bundle_version(src_path).rstrip() - print("Creating macOS application bundle (version: %s)..." % version) + print(f"Creating macOS application bundle (version: {version})...") print("> copying bundle skeleton") copy_bundle(binary_name, src_path) print("> copying binary") diff --git a/TOOLS/stats-conv.py b/TOOLS/stats-conv.py index 794c41fc57d6b..d6baee5a0c0ca 100755 --- a/TOOLS/stats-conv.py +++ b/TOOLS/stats-conv.py @@ -1,8 +1,9 @@ #!/usr/bin/env python3 -from PyQt6 import QtWidgets -import pyqtgraph as pg -import sys import re +import sys + +import pyqtgraph as pg +from PyQt6 import QtWidgets filename = sys.argv[1] @@ -77,7 +78,7 @@ def get_event(event, evtype): (1.0, 0.0, 0.0), (0.75, 0.75, 0), (0.0, 0.75, 0.75), - (0.75, 0, 0.75) + (0.75, 0, 0.75), ] def mkColor(t): @@ -85,7 +86,7 @@ def mkColor(t): SCALE = 1e6 # microseconds to seconds -with open(filename, "r") as file: +with open(filename) as file: for line in file: line = line.split("#")[0].strip() if not line: diff --git a/ci/lint-commit-msg.py b/ci/lint-commit-msg.py index 859519080ad73..f6862b35fd4dd 100755 --- a/ci/lint-commit-msg.py +++ b/ci/lint-commit-msg.py @@ -1,10 +1,11 @@ #!/usr/bin/env python3 -import os -import sys import json -import subprocess +import os import re -from typing import Dict, Tuple, Callable, Optional +import subprocess +import sys +from typing import Callable, Dict, Optional, Tuple + def call(cmd) -> str: sys.stdout.flush() @@ -16,7 +17,7 @@ def call(cmd) -> str: # A lint rule should return True if everything is okay def lint_rule(description: str): def f(func): - assert func.__name__ not in lint_rules.keys() + assert func.__name__ not in lint_rules lint_rules[func.__name__] = (func, description) return f @@ -100,7 +101,7 @@ def line_too_long(body): return revert or len(body[0]) <= 72 @lint_rule( - "Prefix should not include file extension (use `vo_gpu: ...` not `vo_gpu.c: ...`)" + "Prefix should not include file extension (use `vo_gpu: ...` not `vo_gpu.c: ...`)", ) def no_file_exts(body): return not re.search(r"[a-z0-9]\.([chm]|cpp|swift|py): ", body[0]) diff --git a/pyproject.toml b/pyproject.toml index cca05c6e4e806..be20dde845cda 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,5 +5,6 @@ line-length = 100 select = [ "F", # pyflakes "E", "W", # pycodestyle + "UP", # pyupgrade "Q", # flake8-quotes ] From 416035a1741d64f3b0b82d114b804874d47f38f5 Mon Sep 17 00:00:00 2001 From: Nathan Ruiz Date: Sun, 15 Sep 2024 12:22:22 +0000 Subject: [PATCH 33/38] ci/lint: check for pep8 naming convention --- TOOLS/dylib_unhell.py | 64 ++++++++++++++++++++++--------------------- TOOLS/matroska.py | 15 ++++------ TOOLS/osxbundle.py | 4 +-- TOOLS/stats-conv.py | 4 +-- pyproject.toml | 2 ++ 5 files changed, 45 insertions(+), 44 deletions(-) diff --git a/TOOLS/dylib_unhell.py b/TOOLS/dylib_unhell.py index 871cd5d7116f0..efd389a06864d 100755 --- a/TOOLS/dylib_unhell.py +++ b/TOOLS/dylib_unhell.py @@ -216,7 +216,7 @@ def process_swift_libraries(binary): def process_vulkan_loader(binary, loader_name, loader_relative_folder, library_node): # https://github.com/KhronosGroup/Vulkan-Loader/blob/main/docs/LoaderDriverInterface.md#example-macos-driver-search-path # https://github.com/KhronosGroup/Vulkan-Loader/blob/main/docs/LoaderLayerInterface.md#macos-layer-discovery - loaderSystemSearchFolders = [ + loader_system_search_folders = [ os.path.join(os.path.expanduser("~"), ".config", loader_relative_folder), os.path.join("/etc/xdg", loader_relative_folder), os.path.join("/usr/local/etc", loader_relative_folder), @@ -227,50 +227,52 @@ def process_vulkan_loader(binary, loader_name, loader_relative_folder, library_n os.path.join(get_homebrew_prefix(), "share", loader_relative_folder), ] - loaderSystemFolder = "" - for loaderSystemSearchFolder in loaderSystemSearchFolders: - if os.path.exists(loaderSystemSearchFolder): - loaderSystemFolder = loaderSystemSearchFolder + loader_system_folder = "" + for loader_system_search_folder in loader_system_search_folders: + if os.path.exists(loader_system_search_folder): + loader_system_folder = loader_system_search_folder break - if not loaderSystemFolder: + if not loader_system_folder: print(">>> could not find loader folder " + loader_relative_folder) return - loaderBundleFolder = os.path.join(resources_path(binary), loader_relative_folder) - loaderSystemPath = os.path.join(loaderSystemFolder, loader_name) - loaderBundlePath = os.path.join(loaderBundleFolder, loader_name) - libraryRelativeFolder = "../../../Frameworks/" + loader_bundle_folder = os.path.join(resources_path(binary), loader_relative_folder) + loader_system_path = os.path.join(loader_system_folder, loader_name) + loader_bundle_path = os.path.join(loader_bundle_folder, loader_name) + library_relative_folder = "../../../Frameworks/" - if not os.path.exists(loaderSystemPath): + if not os.path.exists(loader_system_path): print(">>> could not find loader " + loader_name) return - if not os.path.exists(loaderBundleFolder): - os.makedirs(loaderBundleFolder) + if not os.path.exists(loader_bundle_folder): + os.makedirs(loader_bundle_folder) - loaderSystemFile = open(loaderSystemPath) - loaderJsonData = json.load(loaderSystemFile) - libraryPath = loaderJsonData[library_node]["library_path"] - librarySystemPath = os.path.join(loaderSystemFolder, libraryPath) + loader_system_file = open(loader_system_path) + loader_json_data = json.load(loader_system_file) + library_path = loader_json_data[library_node]["library_path"] + library_system_path = os.path.join(loader_system_folder, library_path) - if not os.path.exists(librarySystemPath): - print(">>> could not find loader library " + librarySystemPath) + if not os.path.exists(library_system_path): + print(">>> could not find loader library " + library_system_path) return print(">>> modifiying and writing loader json " + loader_name) - loaderBundleFile = open(loaderBundlePath, "w") - loaderLibraryName = os.path.basename(librarySystemPath) - library_path = os.path.join(libraryRelativeFolder, loaderLibraryName) - loaderJsonData[library_node]["library_path"] = library_path - json.dump(loaderJsonData, loaderBundleFile, indent=4) - - print(">>> copying loader library " + loaderLibraryName) - frameworkBundleFolder = os.path.join(loaderBundleFolder, libraryRelativeFolder) - if not os.path.exists(frameworkBundleFolder): - os.makedirs(frameworkBundleFolder) - library_target_path = os.path.join(frameworkBundleFolder, loaderLibraryName) - shutil.copy(librarySystemPath, library_target_path) + loader_bundle_file = open(loader_bundle_path, "w") + loader_library_name = os.path.basename(library_system_path) + library_path = os.path.join(library_relative_folder, loader_library_name) + loader_json_data[library_node]["library_path"] = library_path + json.dump(loader_json_data, loader_bundle_file, indent=4) + + print(">>> copying loader library " + loader_library_name) + framework_bundle_folder = os.path.join( + loader_bundle_folder, library_relative_folder + ) + if not os.path.exists(framework_bundle_folder): + os.makedirs(framework_bundle_folder) + library_target_path = os.path.join(framework_bundle_folder, loader_library_name) + shutil.copy(library_system_path, library_target_path) def remove_dev_tools_rapths(binary): for path in get_rpaths_dev_tools(binary): diff --git a/TOOLS/matroska.py b/TOOLS/matroska.py index 9de9b07340533..37ae86df90215 100755 --- a/TOOLS/matroska.py +++ b/TOOLS/matroska.py @@ -249,9 +249,6 @@ def byte2num(s): return int(hexlify(s), 16) -class EOF(Exception): - pass - def camelcase_to_words(name): parts = [] start = 0 @@ -315,7 +312,7 @@ def printf(out, *args): out.write(" ".join(str(x) for x in args)) out.write("\n") -def generate_C_header(out): +def generate_c_header(out): printf(out, "// Generated by TOOLS/matroska.py, do not edit manually") printf(out) @@ -348,7 +345,7 @@ def generate_C_header(out): for el in elementlist)) -def generate_C_definitions(out): +def generate_c_definitions(out): printf(out, "// Generated by TOOLS/matroska.py, do not edit manually") printf(out) for el in reversed(elementlist): @@ -367,7 +364,7 @@ def generate_C_definitions(out): def read(s, length): t = s.read(length) if len(t) != length: - raise EOF + raise EOFError return t def read_id(s): @@ -475,16 +472,16 @@ def parse_toplevel(s): parse_one(s, 0, None, 1 << 63) if sys.argv[1] == "--generate-header": - generate_C_header(open(sys.argv[2], "w")) + generate_c_header(open(sys.argv[2], "w")) elif sys.argv[1] == "--generate-definitions": - generate_C_definitions(open(sys.argv[2], "w")) + generate_c_definitions(open(sys.argv[2], "w")) else: s = open(sys.argv[1], "rb") while 1: start = s.tell() try: parse_toplevel(s) - except EOF: + except EOFError: if s.tell() != start: raise Exception("Unexpected end of file") break diff --git a/TOOLS/osxbundle.py b/TOOLS/osxbundle.py index c21661c3180ae..bf144fe0129a9 100755 --- a/TOOLS/osxbundle.py +++ b/TOOLS/osxbundle.py @@ -40,8 +40,8 @@ def apply_plist_template(plist_file, version): def sign_bundle(binary_name): sign_directories = ["Contents/Frameworks", "Contents/MacOS"] - for dir in sign_directories: - resolved_dir = os.path.join(bundle_path(binary_name), dir) + for sign_dir in sign_directories: + resolved_dir = os.path.join(bundle_path(binary_name), sign_dir) for root, _dirs, files in os.walk(resolved_dir): for f in files: path = os.path.join(root, f) diff --git a/TOOLS/stats-conv.py b/TOOLS/stats-conv.py index d6baee5a0c0ca..e217570a634f1 100755 --- a/TOOLS/stats-conv.py +++ b/TOOLS/stats-conv.py @@ -81,7 +81,7 @@ def get_event(event, evtype): (0.75, 0, 0.75), ] -def mkColor(t): +def mk_color(t): return pg.mkColor(int(t[0] * 255), int(t[1] * 255), int(t[2] * 255)) SCALE = 1e6 # microseconds to seconds @@ -174,7 +174,7 @@ def mkColor(t): if cur not in G.curveno: G.curveno[cur] = 0 args = {"name": e.name,"antialias":True} - color = mkColor(colors[G.curveno[cur] % len(colors)]) + color = mk_color(colors[G.curveno[cur] % len(colors)]) if e.type == "event-signal": args["symbol"] = e.marker args["symbolBrush"] = pg.mkBrush(color, width=0) diff --git a/pyproject.toml b/pyproject.toml index be20dde845cda..f4b272337b56c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,6 +5,8 @@ line-length = 100 select = [ "F", # pyflakes "E", "W", # pycodestyle + "N", # pep8-naming "UP", # pyupgrade + "A", # flake8-builtins "Q", # flake8-quotes ] From c6903f9963b16ec6835439a6c21cdb621cba24b5 Mon Sep 17 00:00:00 2001 From: Nathan Ruiz Date: Sat, 21 Sep 2024 10:47:30 +0000 Subject: [PATCH 34/38] ci/lint: add isort checks --- TOOLS/macos-sdk-version.py | 1 + TOOLS/macos-swift-lib-directory.py | 1 + pyproject.toml | 1 + 3 files changed, 3 insertions(+) diff --git a/TOOLS/macos-sdk-version.py b/TOOLS/macos-sdk-version.py index 137b300f1bc13..103e6cafa657a 100755 --- a/TOOLS/macos-sdk-version.py +++ b/TOOLS/macos-sdk-version.py @@ -9,6 +9,7 @@ from shutil import which from subprocess import check_output + def find_macos_sdk(): sdk = os.environ.get("MACOS_SDK", "") sdk_version = os.environ.get("MACOS_SDK_VERSION", "0.0") diff --git a/TOOLS/macos-swift-lib-directory.py b/TOOLS/macos-swift-lib-directory.py index 72b79d9d18e0d..a7aca05b9cbc8 100755 --- a/TOOLS/macos-swift-lib-directory.py +++ b/TOOLS/macos-swift-lib-directory.py @@ -8,6 +8,7 @@ from shutil import which from subprocess import check_output + def find_swift_lib(): swift_lib_dir = os.environ.get("SWIFT_LIB_DYNAMIC", "") if swift_lib_dir: diff --git a/pyproject.toml b/pyproject.toml index f4b272337b56c..7e72b41e2db89 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,6 +5,7 @@ line-length = 100 select = [ "F", # pyflakes "E", "W", # pycodestyle + "I", # pycodestyle "N", # pep8-naming "UP", # pyupgrade "A", # flake8-builtins From 44a296be9796b952992150bf8505959203246ce3 Mon Sep 17 00:00:00 2001 From: Nathan Ruiz Date: Sat, 21 Sep 2024 10:58:14 +0000 Subject: [PATCH 35/38] ci/lint: add flake8-commas check --- TOOLS/dylib_unhell.py | 2 +- TOOLS/macos-sdk-version.py | 2 +- pyproject.toml | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/TOOLS/dylib_unhell.py b/TOOLS/dylib_unhell.py index efd389a06864d..cecef2a5f3758 100755 --- a/TOOLS/dylib_unhell.py +++ b/TOOLS/dylib_unhell.py @@ -267,7 +267,7 @@ def process_vulkan_loader(binary, loader_name, loader_relative_folder, library_n print(">>> copying loader library " + loader_library_name) framework_bundle_folder = os.path.join( - loader_bundle_folder, library_relative_folder + loader_bundle_folder, library_relative_folder, ) if not os.path.exists(framework_bundle_folder): os.makedirs(framework_bundle_folder) diff --git a/TOOLS/macos-sdk-version.py b/TOOLS/macos-sdk-version.py index 103e6cafa657a..55e8975b77336 100755 --- a/TOOLS/macos-sdk-version.py +++ b/TOOLS/macos-sdk-version.py @@ -33,7 +33,7 @@ def find_macos_sdk(): sdk_version = check_output( [xcodebuild, "-sdk", "macosx", "-version", "ProductVersion"], encoding="UTF-8", - stderr=subprocess.DEVNULL + stderr=subprocess.DEVNULL, ) except Exception: pass diff --git a/pyproject.toml b/pyproject.toml index 7e72b41e2db89..d370f5cd4a1fb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,4 +10,5 @@ select = [ "UP", # pyupgrade "A", # flake8-builtins "Q", # flake8-quotes + "COM", # flake8-commas ] From 62abcbdd88cb49b62b67a17e424a1d6b97949954 Mon Sep 17 00:00:00 2001 From: Nathan Ruiz Date: Sun, 29 Sep 2024 02:15:29 +0000 Subject: [PATCH 36/38] ci/lint: fix missing return value in lint-commit-msg --- ci/lint-commit-msg.py | 1 + 1 file changed, 1 insertion(+) diff --git a/ci/lint-commit-msg.py b/ci/lint-commit-msg.py index f6862b35fd4dd..a6ed9ecc41de9 100755 --- a/ci/lint-commit-msg.py +++ b/ci/lint-commit-msg.py @@ -61,6 +61,7 @@ def do_lint(commit_range: str) -> bool: print("\nhas the following issues:") print("\n".join(failed)) print("-" * 40) + return any_failed ################################################################################ From 6667b9723ec788179c54794a016e5810e922c415 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kacper=20Michaj=C5=82ow?= Date: Tue, 5 Dec 2023 12:57:52 +0100 Subject: [PATCH 37/38] win32: fix window size restore after maximize state This remembers and sets window-scale when exiting maximized state. Also fixes not staying in maximized state when exiting fullscreen mode. Fixes: #14126 --- video/out/w32_common.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/video/out/w32_common.c b/video/out/w32_common.c index 73c0f9f83806e..26b395fefe8a1 100644 --- a/video/out/w32_common.c +++ b/video/out/w32_common.c @@ -1069,7 +1069,7 @@ static void update_fullscreen_state(struct vo_w32_state *w32) m_config_cache_write_opt(w32->opts_cache, &w32->opts->fullscreen); - if (toggle_fs) { + if (toggle_fs && (!w32->opts->window_maximized || w32->unmaximize)) { if (w32->current_fs) { // Save window rect when switching to fullscreen. w32->prev_windowrc = w32->windowrc; @@ -1104,6 +1104,8 @@ static void update_minimized_state(struct vo_w32_state *w32) } } +static void update_window_state(struct vo_w32_state *w32); + static void update_maximized_state(struct vo_w32_state *w32, bool leaving_fullscreen) { if (w32->parent) @@ -1115,6 +1117,8 @@ static void update_maximized_state(struct vo_w32_state *w32, bool leaving_fullsc if (w32->current_fs && !leaving_fullscreen) return; + bool toggle = !w32->opts->window_maximized && IsMaximized(w32->window); + WINDOWPLACEMENT wp = { .length = sizeof wp }; GetWindowPlacement(w32->window, &wp); @@ -1134,6 +1138,11 @@ static void update_maximized_state(struct vo_w32_state *w32, bool leaving_fullsc ShowWindow(w32->window, SW_SHOWNOACTIVATE); } } + + if (toggle && !w32->current_fs) { + w32->windowrc = w32->prev_windowrc; + update_window_state(w32); + } } static bool is_visible(HWND window) @@ -1168,7 +1177,7 @@ static void update_window_state(struct vo_w32_state *w32) // doesn't change the window maximized state. // ShowWindow(SW_SHOWNOACTIVATE) can't be used here because it tries to // "restore" the window to its size before it's maximized. - if (w32->unmaximize) { + if (w32->unmaximize && !w32->current_fs) { WINDOWPLACEMENT wp = { .length = sizeof wp }; GetWindowPlacement(w32->window, &wp); wp.showCmd = SW_SHOWNOACTIVATE; @@ -2268,7 +2277,8 @@ static int gui_thread_control(struct vo_w32_state *w32, int request, void *arg) if (!w32->window_bounds_initialized) return VO_FALSE; - RECT *rc = w32->current_fs ? &w32->prev_windowrc : &w32->windowrc; + RECT *rc = (w32->current_fs || w32->opts->window_maximized) + ? &w32->prev_windowrc : &w32->windowrc; s[0] = rect_w(*rc); s[1] = rect_h(*rc); return VO_TRUE; @@ -2282,7 +2292,7 @@ static int gui_thread_control(struct vo_w32_state *w32, int request, void *arg) RECT *rc = w32->current_fs ? &w32->prev_windowrc : &w32->windowrc; resize_and_move_rect(w32, rc, s[0], s[1]); - if (w32->opts->window_maximized) { + if (w32->opts->window_maximized && !w32->current_fs) { w32->unmaximize = true; } w32->fit_on_screen = true; From fb9ac9b570a6b320cc47d680bfc5c89591ff13aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kacper=20Michaj=C5=82ow?= Date: Mon, 7 Oct 2024 02:31:34 +0200 Subject: [PATCH 38/38] win32: don't change window size on video reconfig when maximized Fixes: #7265 --- video/out/w32_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/video/out/w32_common.c b/video/out/w32_common.c index 26b395fefe8a1..691ef3d57c18f 100644 --- a/video/out/w32_common.c +++ b/video/out/w32_common.c @@ -1959,7 +1959,7 @@ static void window_reconfig(struct vo_w32_state *w32, bool force) vo->dwidth = r.right; vo->dheight = r.bottom; } else { - if (w32->current_fs) + if (w32->current_fs || w32->opts->window_maximized) rc = &w32->prev_windowrc; w32->fit_on_screen = true; }