style: reconfigured and run the whole codebase through lua formatter

This commit is contained in:
tomasklaen
2023-10-14 13:22:43 +02:00
parent 3679ba3278
commit 3e685c52b8
24 changed files with 1094 additions and 708 deletions

View File

@@ -1,83 +1,167 @@
[*.lua]
# see https://github.com/CppCXY/EmmyLuaCodeStyle
[*]
indent_style = tab
indent_size = 4
end_of_line = lf
insert_final_newline = true
[*.md]
indent_style = space
indent_size = 2
# see https://github.com/CppCXY/EmmyLuaCodeStyle
[*.lua]
# [basic]
# optional space/tab
indent_style = tab
# if indent_style is space, this is valid
indent_size = 4
# if indent_style is tab, this is valid
tab_width = 4
# none/single/double
quote_style = single
continuation_indent_size = 4
continuation_indent = 4
# this mean utf8 length , if this is 'unset' then the line width is no longer checked
# this option decides when to chopdown the code
max_line_length = 120
# crlf/lf/cr/auto
# optional crlf/lf/cr/auto, if it is 'auto', in windows it is crlf other platforms are lf
# in neovim the value 'auto' is not a valid option, please use 'unset'
end_of_line = lf
detect_end_of_line = false
insert_final_newline = true
# [function]
# none/ comma / semicolon / only_kv_colon
table_separator_style = comma
# true/false/only_after_more_indention_statement/only_not_exist_cross_row_expression
align_call_args = false
align_function_define_params = true
remove_expression_list_finish_comma = true
# keep/remove/remove_table_only/remove_string_only/unambiguous_remove_string_only
#optional keep/never/always/smart
trailing_table_separator = smart
# keep/remove/remove_table_only/remove_string_only
call_arg_parentheses = keep
# [table]
detect_end_of_line = false
# none/comma/semicolon
table_separator_style = comma
# keep/never/always/smart
trailing_table_separator = smart
# align equal signs in tables
continuous_assign_table_field_align_to_equal_sign = false
# if true "local t = { 1, 2, 3 }"
keep_one_space_between_table_and_bracket = false
# [statement]
align_chained_expression_statement = false
max_continuous_line_distance = 1
# align equal signs in value assignments
continuous_assign_statement_align_to_equal_sign = false
if_condition_align_with_each_other = false
local_assign_continuation_align_to_first_expression = false
statement_inline_comment_space = 1
# [indentation]
# labels (e.g.::continue::) will not be intended
label_no_indent = false
# no indentation for do statement
do_statement_no_indent = false
# no indentation for conditions of an if statement when on new line
if_condition_no_continuation_indent = false
if_branch_comments_after_block_no_indent = false
# this will check text end with new line
insert_final_newline = true
# [space]
space_around_table_field_list = false
space_before_attribute = false
# if true, t[#t+1] will not space wrapper '+'
table_append_expression_no_space = false
long_chain_expression_allow_one_space_after_colon = false
remove_empty_header_and_footer_lines_in_function = true
space_before_function_open_parenthesis = false
space_before_function_call_open_parenthesis = false
space_before_closure_open_parenthesis = false
# optional always/only_string/only_table/none
# or true/false
space_before_function_call_single_arg = always
space_before_open_square_bracket = false
# format like this "local t <const> = 1"
keep_one_space_between_namedef_and_attribute = false
# [row_layout]
# Each can be: minLine:${n}, keepLine, keepLine:${n}, maxLine:${n}
space_inside_function_call_parentheses = false
keep_line_after_if_statement = keepLine
keep_line_after_do_statement = keepLine
keep_line_after_while_statement = keepLine
keep_line_after_repeat_statement = keepLine
keep_line_after_for_statement = keepLine
keep_line_after_local_or_assign_statement = keepLine
keep_line_after_function_define_statement = keepLine
keep_line_after_expression_statement = keepLine
space_inside_function_param_list_parentheses = false
# [diagnostic]
# creates a lot of warnings I can't do anything about so disable it is
space_inside_square_brackets = false
enable_check_codestyle = false
# like t[#t+1] = 1
space_around_table_append_operator = false
ignore_spaces_inside_function_call = false
space_before_inline_comment = 1
# [operator space]
space_around_math_operator = true
space_after_comma = true
space_after_comma_in_for_statement = true
# true/false or none/always/no_space_asym
space_around_concat_operator = true
space_around_logical_operator = true
# true/false or none/always/no_space_asym
space_around_assign_operator = true
# [align]
align_call_args = false
align_function_params = false
align_continuous_assign_statement = false
align_continuous_rect_table_field = false
align_continuous_line_space = 2
align_if_branch = false
# option none / always / contain_curly/
align_array_table = none
align_continuous_similar_call_args = false
align_continuous_inline_comment = false
# option none / always / only_call_stmt
align_chain_expr = none
# [indent]
never_indent_before_if_condition = false
never_indent_comment_on_if_branch = true
keep_indents_on_empty_lines = false
# [line space]
# The following configuration supports four expressions
# keep
# fixed(n)
# min(n)
# max(n)
# for eg. min(2)
line_space_after_if_statement = keep
line_space_after_do_statement = keep
line_space_after_while_statement = keep
line_space_after_repeat_statement = keep
line_space_after_for_statement = keep
line_space_after_local_or_assign_statement = keep
line_space_after_function_statement = keep
line_space_after_expression_statement = keep
line_space_after_comment = keep
line_space_around_block = fixed(1)
# [line break]
break_all_list_when_line_exceed = false
auto_collapse_lines = false
break_before_braces = false
# [preference]
ignore_space_after_colon = false
remove_call_expression_list_finish_comma = false
# keep / always / same_line / repalce_with_newline
end_statement_with_semicolon = keep

View File

@@ -16,7 +16,9 @@ function BufferingIndicator:decide_enabled()
local player = state.core_idle and not state.eof_reached
if self.enabled then
if not player or (state.pause and not cache) then self.enabled = false end
elseif player and cache and state.uncached_ranges then self.enabled = true end
elseif player and cache and state.uncached_ranges then
self.enabled = true
end
end
function BufferingIndicator:on_prop_pause() self:decide_enabled() end

View File

@@ -47,7 +47,8 @@ function Button:render()
-- Background
if is_hover_or_active then
ass:rect(self.ax, self.ay, self.bx, self.by, {
color = self.active and background or foreground, radius = state.radius,
color = self.active and background or foreground,
radius = state.radius,
opacity = visibility * (self.active and 1 or 0.3),
})
end
@@ -64,8 +65,11 @@ function Button:render()
local width, height = math.ceil(badge_width + (badge_font_size / 7) * 2), math.ceil(badge_font_size * 0.93)
local bx, by = self.bx - 1, self.by - 1
ass:rect(bx - width, by - height, bx, by, {
color = foreground, radius = state.radius, opacity = visibility,
border = self.active and 0 or 1, border_color = background,
color = foreground,
radius = state.radius,
opacity = visibility,
border = self.active and 0 or 1,
border_color = background,
})
ass:txt(bx - width / 2, by - height / 2, 5, self.badge, badge_opts)
@@ -80,8 +84,11 @@ function Button:render()
-- Icon
local x, y = round(self.ax + (self.bx - self.ax) / 2), round(self.ay + (self.by - self.ay) / 2)
ass:icon(x, y, self.font_size, self.icon, {
color = foreground, border = self.active and 0 or options.text_border * state.scale, border_color = background,
opacity = visibility, clip = icon_clip,
color = foreground,
border = self.active and 0 or options.text_border * state.scale,
border_color = background,
opacity = visibility,
clip = icon_clip,
})
return ass

View File

@@ -57,8 +57,10 @@ function Controls:init_options()
local current_item = nil
for c in options.controls:gmatch('.') do
if not current_item then current_item = {disposition = '', config = ''} end
if c == '<' and #current_item.config == 0 then in_disposition = true
elseif c == '>' and #current_item.config == 0 then in_disposition = false
if c == '<' and #current_item.config == 0 then
in_disposition = true
elseif c == '>' and #current_item.config == 0 then
in_disposition = false
elseif c == ',' and not in_disposition then
items[#items + 1] = current_item
current_item = nil
@@ -224,8 +226,11 @@ function Controls:register_badge_updater(badge, element)
request_render()
end
if is_external_prop then element['on_external_prop_' .. prop] = function(_, value) handler(prop, value) end
else self:observe_mp_property(observable_name, handler) end
if is_external_prop then
element['on_external_prop_' .. prop] = function(_, value) handler(prop, value) end
else
self:observe_mp_property(observable_name, handler)
end
end
function Controls:get_visibility()

View File

@@ -34,8 +34,11 @@ function Element:init(id, props)
self._flash_out_timer = mp.add_timeout(options.flash_duration / 1000, function()
local function getTo() return self.proximity end
local function onTweenEnd() self.forced_visibility = nil end
if self.enabled then self:tween_property('forced_visibility', 1, getTo, onTweenEnd)
else onTweenEnd() end
if self.enabled then
self:tween_property('forced_visibility', 1, getTo, onTweenEnd)
else
onTweenEnd()
end
end)
self._flash_out_timer:kill()

View File

@@ -43,8 +43,11 @@ function Elements:update_proximities()
-- If menu is open, all other elements have to be disabled
if menu_only then
if element.ignores_menu then element:update_proximity()
else element:reset_proximity() end
if element.ignores_menu then
element:update_proximity()
else
element:reset_proximity()
end
else
element:update_proximity()
end

View File

@@ -64,8 +64,11 @@ function Menu:close(immediate, callback)
menu.is_closing = true
if immediate then close()
else menu:fadeout(close) end
if immediate then
close()
else
menu:fadeout(close)
end
end
end
@@ -155,10 +158,10 @@ function Menu:update(data)
local menus_to_serialize = {{new_root, data}}
local old_current_id = self.current and self.current.id
local menu_props_to_copy = {
'title', 'hint', 'keep_open', 'palette', 'on_search', 'search_submenus', 'search_suggestion'
'title', 'hint', 'keep_open', 'palette', 'on_search', 'search_submenus', 'search_suggestion',
}
local item_props_to_copy = itable_join(menu_props_to_copy, {
'icon', 'active', 'bold', 'italic', 'muted', 'value', 'separator', 'selectable', 'align'
'icon', 'active', 'bold', 'italic', 'muted', 'value', 'separator', 'selectable', 'align',
})
table_assign(new_root, data, itable_join({'type'}, menu_props_to_copy))
@@ -189,7 +192,7 @@ function Menu:update(data)
-- Update items
local first_active_index = nil
menu.items = {
{title = t('Empty'), value = 'ignore', italic = 'true', muted = 'true', selectable = false, align = 'center'}
{title = t('Empty'), value = 'ignore', italic = 'true', muted = 'true', selectable = false, align = 'center'},
}
for i, item_data in ipairs(menu_data.items or {}) do
@@ -213,8 +216,11 @@ function Menu:update(data)
-- Retain old state
local old_menu = self.by_id[menu.id]
if old_menu then table_assign(menu, old_menu, {'selected_index', 'scroll_y', 'fling', 'search'})
else new_menus[#new_menus + 1] = menu end
if old_menu then
table_assign(menu, old_menu, {'selected_index', 'scroll_y', 'fling', 'search'})
else
new_menus[#new_menus + 1] = menu
end
if menu.selected_index then self:select_by_offset(0, menu) end
@@ -403,8 +409,11 @@ end
function Menu:scroll_to(pos, menu, fling_options)
menu = menu or self.current
menu.fling = {
y = menu.scroll_y, distance = clamp(-menu.scroll_y, pos - menu.scroll_y, menu.scroll_height - menu.scroll_y),
time = mp.get_time(), duration = 0.1, easing = ease_out_sext,
y = menu.scroll_y,
distance = clamp(-menu.scroll_y, pos - menu.scroll_y, menu.scroll_height - menu.scroll_y),
time = mp.get_time(),
duration = 0.1,
easing = ease_out_sext,
}
if fling_options then table_assign(menu.fling, fling_options) end
request_render()
@@ -425,8 +434,11 @@ function Menu:scroll_to_index(index, menu, immediate)
menu = menu or self.current
if (index and index >= 1 and index <= #menu.items) then
local position = round((self.scroll_step * (index - 1)) - ((menu.height - self.scroll_step) / 2))
if immediate then self:set_scroll_to(position, menu)
else self:scroll_to(position, menu) end
if immediate then
self:set_scroll_to(position, menu)
else
self:scroll_to(position, menu)
end
end
end
@@ -500,8 +512,11 @@ end
---@param id string
function Menu:activate_submenu(id)
local submenu = self.by_id[id]
if submenu then self:activate_menu(submenu)
else msg.error(string.format('Requested submenu id "%s" doesn\'t exist', id)) end
if submenu then
self:activate_menu(submenu)
else
msg.error(string.format('Requested submenu id "%s" doesn\'t exist', id))
end
end
---@param index? integer
@@ -617,8 +632,12 @@ function Menu:handle_cursor_up()
local distance = cursor.get_velocity().y / -3
if math.abs(distance) > 50 then
self.current.fling = {
y = self.current.scroll_y, distance = distance, time = cursor.history:head().time,
easing = ease_out_quart, duration = 0.5, update_cursor = true,
y = self.current.scroll_y,
distance = distance,
time = cursor.history:head().time,
easing = ease_out_quart,
duration = 0.5,
update_cursor = true,
}
end
end
@@ -648,9 +667,13 @@ function Menu:select_by_offset(offset, menu)
local prev_index = itable_find(menu.items, function(item) return item.selectable ~= false end, index, 1)
local next_index = itable_find(menu.items, function(item) return item.selectable ~= false end, index)
if prev_index and next_index then
if offset == 0 then menu.selected_index = index - prev_index <= next_index - index and prev_index or next_index
elseif offset > 0 then menu.selected_index = next_index
else menu.selected_index = prev_index end
if offset == 0 then
menu.selected_index = index - prev_index <= next_index - index and prev_index or next_index
elseif offset > 0 then
menu.selected_index = next_index
else
menu.selected_index = prev_index
end
else
menu.selected_index = prev_index or next_index or nil
end
@@ -752,8 +775,8 @@ function Menu:search_submit(menu)
italic = true,
align = 'center',
selectable = false,
muted = true
}
muted = true,
},
}
self:update_items(self.root.items)
end
@@ -767,7 +790,9 @@ function Menu:search_submit(menu)
else
menu.on_search(menu.search.query)
end
else self:search_internal(menu) end
else
self:search_internal(menu)
end
end
---@param query string
@@ -841,11 +866,16 @@ function Menu:search_init(menu)
timeout:kill()
end
menu.search = {
query = '', timeout = timeout, min_top = menu.top, max_width = menu.width,
query = '',
timeout = timeout,
min_top = menu.top,
max_width = menu.width,
source = {
width = menu.width, top = menu.top,
scroll_y = menu.scroll_y, selected_index = menu.selected_index,
items = not menu.on_search and menu.items or nil
width = menu.width,
top = menu.top,
scroll_y = menu.scroll_y,
selected_index = menu.selected_index,
items = not menu.on_search and menu.items or nil,
},
}
end
@@ -860,34 +890,49 @@ end
function Menu:key_esc()
if self.current.search then
if self.current.palette then
if self.current.search.query == '' then self:close()
else self:search_query_update('') end
if self.current.search.query == '' then
self:close()
else
self:search_query_update('')
end
else
self:search_stop()
end
else self:close() end
else
self:close()
end
end
function Menu:key_bs(info)
if info.event ~= 'up' then
if self.current.search then self:search_backspace(info.event)
elseif info.event ~= 'repeat' then self:back() end
if self.current.search then
self:search_backspace(info.event)
elseif info.event ~= 'repeat' then
self:back()
end
end
end
function Menu:key_ctrl_enter()
if self.current.search then self:search_submit()
else self:open_selected_item_preselect() end
if self.current.search then
self:search_submit()
else
self:open_selected_item_preselect()
end
end
function Menu:key_left()
if self.current.search then -- control cursor when it's implemented
else self:back() end
else
self:back()
end
end
function Menu:key_right()
if self.current.search then -- control cursor when it's implemented
else self:open_selected_item_preselect() end
else
self:open_selected_item_preselect()
end
end
function Menu:search_enable_key_bindings()
@@ -905,8 +950,11 @@ end
function Menu:search_ensure_key_bindings()
if self.type_to_search then return end
if self.current.search then self:search_enable_key_bindings()
else self:search_disable_key_bindings() end
if self.current.search then
self:search_enable_key_bindings()
else
self:search_disable_key_bindings()
end
end
function Menu:search_disable_key_bindings()
@@ -942,8 +990,7 @@ function Menu:enable_key_bindings()
self:add_key_binding('bs', 'menu-back-alt4', self:create_key_action('key_bs'), {repeatable = true, complex = true})
self:add_key_binding('enter', 'menu-select-alt3', self:create_key_action('open_selected_item_preselect'))
self:add_key_binding('kp_enter', 'menu-select-alt4', self:create_key_action('open_selected_item_preselect'))
self:add_key_binding('ctrl+enter', 'menu-select-ctrl1',
self:create_key_action('key_ctrl_enter', {ctrl = true}))
self:add_key_binding('ctrl+enter', 'menu-select-ctrl1', self:create_key_action('key_ctrl_enter', {ctrl = true}))
self:add_key_binding('alt+enter', 'menu-select-alt1',
self:create_key_action('open_selected_item_preselect', {alt = true}))
self:add_key_binding('ctrl+kp_enter', 'menu-select-ctrl2',
@@ -1040,14 +1087,16 @@ function Menu:render()
local start_index = math.floor(menu.scroll_y / self.scroll_step) + 1
local end_index = math.ceil((menu.scroll_y + menu.height) / self.scroll_step)
local menu_rect = {
ax = ax, ay = ay - (draw_title and self.scroll_step or 0) - self.padding,
bx = bx, by = by + self.padding
ax = ax,
ay = ay - (draw_title and self.scroll_step or 0) - self.padding,
bx = bx,
by = by + self.padding,
}
local blur_selected_index = is_current and self.mouse_nav
-- Background
ass:rect(menu_rect.ax, menu_rect.ay, menu_rect.bx, menu_rect.by, {
color = bg, opacity = menu_opacity * config.opacity.menu, radius = state.radius + self.padding
color = bg, opacity = menu_opacity * config.opacity.menu, radius = state.radius + self.padding,
})
if is_parent and get_point_to_rectangle_proximity(cursor, menu_rect) == 0 then
@@ -1088,7 +1137,7 @@ function Menu:render()
ax = menu_rect.ax + self.padding,
ay = item_ay,
bx = menu_rect.bx + (item.items and self.gap or -self.padding), -- to bridge the gap with cursor
by = item_by
by = item_by,
}
if submenu_is_hovered or get_point_to_rectangle_proximity(cursor, item_rect_hitbox) == 0 then
blur_selected_index = false
@@ -1117,7 +1166,9 @@ function Menu:render()
local highlight_opacity = 0 + (item.active and 0.8 or 0) + (menu.selected_index == index and 0.15 or 0)
if not is_submenu and highlight_opacity > 0 then
ass:rect(ax + self.padding, item_ay, bx - self.padding, item_by, {
radius = state.radius, color = fg, opacity = highlight_opacity * menu_opacity,
radius = state.radius,
color = fg,
opacity = highlight_opacity * menu_opacity,
clip = item_clip,
})
end
@@ -1168,8 +1219,13 @@ function Menu:render()
title_x, align = content_ax + (title_cut_x - content_ax) / 2, 5
end
ass:txt(title_x, item_center_y, align, item.ass_safe_title, {
size = self.font_size, color = font_color, italic = item.italic, bold = item.bold, wrap = 2,
opacity = menu_opacity * (item.muted and 0.5 or 1), clip = clip,
size = self.font_size,
color = font_color,
italic = item.italic,
bold = item.bold,
wrap = 2,
opacity = menu_opacity * (item.muted and 0.5 or 1),
clip = clip,
})
end
end
@@ -1201,8 +1257,10 @@ function Menu:render()
end
ass:icon(rect.ax + icon_size / 2, rect.cy, icon_size, 'search', {
color = fg, opacity = icon_opacity,
clip = '\\clip(' .. icon_rect.ax .. ',' .. icon_rect.ay .. ',' .. icon_rect.bx .. ',' .. icon_rect.by .. ')'
color = fg,
opacity = icon_opacity,
clip = '\\clip(' ..
icon_rect.ax .. ',' .. icon_rect.ay .. ',' .. icon_rect.bx .. ',' .. icon_rect.by .. ')',
})
-- Query/Placeholder
@@ -1210,7 +1268,10 @@ function Menu:render()
-- Add a ZWNBSP suffix to prevent libass from trimming trailing spaces
local query = ass_escape(menu.search.query) .. '\239\187\191'
ass:txt(rect.bx, rect.cy, 6, query, {
size = self.font_size, color = bgt, wrap = 2, opacity = menu_opacity,
size = self.font_size,
color = bgt,
wrap = 2,
opacity = menu_opacity,
clip = '\\clip(' .. icon_rect.bx .. ',' .. rect.ay .. ',' .. rect.bx .. ',' .. rect.by .. ')',
})
else
@@ -1218,7 +1279,11 @@ function Menu:render()
and menu.ass_safe_title
or (requires_submit and t('type & ctrl+enter to search') or t('type to search'))
ass:txt(rect.bx, rect.cy, 6, placeholder, {
size = self.font_size, italic = true, color = bgt, wrap = 2, opacity = menu_opacity * 0.4,
size = self.font_size,
italic = true,
color = bgt,
wrap = 2,
opacity = menu_opacity * 0.4,
clip = '\\clip(' .. rect.ax .. ',' .. rect.ay .. ',' .. rect.bx .. ',' .. rect.by .. ')',
})
end
@@ -1227,12 +1292,17 @@ function Menu:render()
local font_size_half, cursor_thickness = round(self.font_size / 2), round(self.font_size / 14)
local cursor_ax, cursor_bx = rect.bx + 1, rect.bx + 1 + cursor_thickness
ass:rect(cursor_ax, rect.cy - font_size_half, cursor_bx, rect.cy + font_size_half, {
color = fg, opacity = menu_opacity * 0.5,
color = fg,
opacity = menu_opacity * 0.5,
clip = '\\clip(' .. cursor_ax .. ',' .. rect.ay .. ',' .. cursor_bx .. ',' .. rect.by .. ')',
})
else
ass:txt(rect.cx, rect.cy, 5, menu.ass_safe_title, {
size = self.font_size, bold = true, color = bgt, wrap = 2, opacity = menu_opacity,
size = self.font_size,
bold = true,
color = bgt,
wrap = 2,
opacity = menu_opacity,
clip = '\\clip(' .. rect.ax .. ',' .. rect.ay .. ',' .. rect.bx .. ',' .. rect.by .. ')',
})
end

View File

@@ -127,7 +127,7 @@ function Speed:render()
-- Background
ass:rect(self.ax, self.ay, self.bx, self.by, {
color = bg, radius = state.radius, opacity = opacity * config.opacity.speed
color = bg, radius = state.radius, opacity = opacity * config.opacity.speed,
})
-- Coordinates
@@ -166,7 +166,9 @@ function Speed:render()
end
ass:rect(notch_x - notch_thickness, notch_ay, notch_x + notch_thickness, notch_by, {
color = fg, border = 1, border_color = bg,
color = fg,
border = 1,
border_color = bg,
opacity = math.min(1.2 - (math.abs((notch_x - ax - half_width) / half_width)), 1) * opacity,
})
end
@@ -186,7 +188,10 @@ function Speed:render()
-- Speed value
local speed_text = (round(state.speed * 100) / 100) .. 'x'
ass:txt(half_x, ay + (notch_ay_big - ay) / 2, 5, speed_text, {
size = self.font_size, color = bgt, border = options.text_border * state.scale, border_color = bg,
size = self.font_size,
color = bgt,
border = options.text_border * state.scale,
border_color = bg,
opacity = opacity,
})

View File

@@ -83,8 +83,11 @@ function Timeline:get_time_at_x(x)
local fbx = fax + line_width
-- time starts 0.5 pixels in
x = x - self.ax - 0.5
if x > fbx then x = x - line_width
elseif x > fax then x = fax end
if x > fbx then
x = x - line_width
elseif x > fax then
x = fax
end
local progress = clamp(0, x / time_width, 1)
return state.duration * progress
end
@@ -133,7 +136,9 @@ function Timeline:on_global_mouse_move()
self.pressed.last.x, self.pressed.last.y = cursor.x, cursor.y
if state.is_video and math.abs(cursor.get_velocity().x) / self.width * state.duration > 30 then
self:set_from_cursor(true)
else self:set_from_cursor() end
else
self:set_from_cursor()
end
end
end
function Timeline:handle_wheel_up() mp.commandv('seek', options.timeline_step) end
@@ -254,7 +259,7 @@ function Timeline:render()
-- Chapters
local hovered_chapter = nil
if (config.opacity.chapters > 0
and (#state.chapters > 0 or state.ab_loop_a or state.ab_loop_b)
and (#state.chapters > 0 or state.ab_loop_a or state.ab_loop_b)
) then
local diamond_radius = foreground_size < 3 and foreground_size or self.chapter_size
local diamond_radius_hovered = diamond_radius * 2
@@ -351,7 +356,7 @@ function Timeline:render()
and buffered_playtime < options.buffered_time_threshold then
local x, align = fbx + 5, 4
local cache_opts = {
size = self.font_size * 0.8, opacity = text_opacity * 0.6, border = options.text_border * state.scale
size = self.font_size * 0.8, opacity = text_opacity * 0.6, border = options.text_border * state.scale,
}
local human = round(math.max(buffered_playtime, 0)) .. 's'
local width = text_width(human, cache_opts)
@@ -411,8 +416,12 @@ function Timeline:render()
local ax, ay = (thumb_x - border), (thumb_y - border)
local bx, by = (thumb_x + thumb_width + border), (thumb_y + thumb_height + border)
ass:rect(ax, ay, bx, by, {
color = bg, border = 1, opacity = config.opacity.thumbnail,
border_color = fg, border_opacity = 0.08 * config.opacity.thumbnail, radius = state.radius
color = bg,
border = 1,
opacity = config.opacity.thumbnail,
border_color = fg,
border_opacity = 0.08 * config.opacity.thumbnail,
radius = state.radius,
})
mp.commandv('script-message-to', 'thumbfast', 'thumb', hovered_seconds, thumb_x, thumb_y)
self.has_thumbnail, rendered_thumbnail = true, true
@@ -421,12 +430,17 @@ function Timeline:render()
-- Chapter title
if #state.chapters > 0 then
local _, chapter = itable_find(state.chapters, function(c) return hovered_seconds >= c.time end, #state.chapters, 1)
local _, chapter = itable_find(state.chapters, function(c) return hovered_seconds >= c.time end,
#state.chapters, 1)
if chapter and not chapter.is_end_only then
ass:tooltip(tooltip_anchor, chapter.title_wrapped, {
size = self.font_size, offset = tooltip_gap, responsive = false, bold = true,
size = self.font_size,
offset = tooltip_gap,
responsive = false,
bold = true,
width_overwrite = chapter.title_wrapped_width * self.font_size,
lines = chapter.title_lines, margin = tooltip_margin,
lines = chapter.title_lines,
margin = tooltip_margin,
})
end
end

View File

@@ -62,15 +62,19 @@ function TopBar:init()
-- Order aligns from right to left
self.buttons = {
TopBarButton:new('tb_close', {
icon = 'close', background = '2311e8', command = 'quit', render_order = self.render_order
icon = 'close', background = '2311e8', command = 'quit', render_order = self.render_order,
}),
TopBarButton:new('tb_max', {
icon = 'crop_square', background = '222222', command = get_maximized_command,
render_order = self.render_order
icon = 'crop_square',
background = '222222',
command = get_maximized_command,
render_order = self.render_order,
}),
TopBarButton:new('tb_min', {
icon = 'minimize', background = '222222', command = 'cycle window-minimized',
render_order = self.render_order
icon = 'minimize',
background = '222222',
command = 'cycle window-minimized',
render_order = self.render_order,
}),
}
@@ -117,7 +121,7 @@ function TopBar:decide_titles()
longer_title, shorter_title = self.main_title, self.alt_title
end
local escaped_shorter_title = string.gsub(shorter_title --[[@as string]], "[%(%)%.%+%-%*%?%[%]%^%$%%]", "%%%1")
local escaped_shorter_title = string.gsub(shorter_title --[[@as string]], '[%(%)%.%+%-%*%?%[%]%^%$%%]', '%%%1')
if string.match(longer_title --[[@as string]], escaped_shorter_title) then
self.main_title, self.alt_title = longer_title, nil
end
@@ -208,7 +212,7 @@ function TopBar:render()
ax = title_ax,
ay = title_ay,
bx = round(title_ax + text_width(text, opts) + padding * 2),
by = self.by - bg_margin
by = self.by - bg_margin,
}
ass:rect(rect.ax, rect.ay, rect.bx, rect.by, {color = fg, opacity = visibility, radius = state.radius})
ass:txt(rect.ax + (rect.bx - rect.ax) / 2, rect.ay + (rect.by - rect.ay) / 2, 5, formatted_text, opts)
@@ -226,8 +230,12 @@ function TopBar:render()
local main_title = self.show_alt_title and self.alt_title or self.main_title
if main_title then
local opts = {
size = self.font_size, wrap = 2, color = bgt, opacity = visibility,
border = options.text_border * state.scale, border_color = bg,
size = self.font_size,
wrap = 2,
color = bgt,
opacity = visibility,
border = options.text_border * state.scale,
border_color = bg,
clip = string.format('\\clip(%d, %d, %d, %d)', self.ax, self.ay, max_bx, self.by),
}
local bx = round(math.min(max_bx, title_ax + text_width(main_title, opts) + padding * 2))
@@ -253,8 +261,12 @@ function TopBar:render()
local height = font_size * 1.3
local by = title_ay + height
local opts = {
size = font_size, wrap = 2, color = bgt,
border = options.text_border * state.scale, border_color = bg, opacity = visibility
size = font_size,
wrap = 2,
color = bgt,
border = options.text_border * state.scale,
border_color = bg,
opacity = visibility,
}
local bx = round(math.min(max_bx, title_ax + text_width(self.alt_title, opts) + padding * 2))
opts.clip = string.format('\\clip(%d, %d, %d, %d)', title_ax, title_ay, bx, by)
@@ -271,14 +283,19 @@ function TopBar:render()
local height = font_size * 1.3
local text = '' .. state.current_chapter.index .. ': ' .. state.current_chapter.title
local opts = {
size = font_size, italic = true, wrap = 2, color = bgt,
border = options.text_border * state.scale, border_color = bg, opacity = visibility * 0.8,
size = font_size,
italic = true,
wrap = 2,
color = bgt,
border = options.text_border * state.scale,
border_color = bg,
opacity = visibility * 0.8,
}
local rect = {
ax = title_ax,
ay = title_ay,
bx = round(math.min(max_bx, title_ax + text_width(text, opts) + padding * 2)),
by = title_ay + height
by = title_ay + height,
}
opts.clip = string.format('\\clip(%d, %d, %d, %d)', title_ax, title_ay, rect.bx, rect.by)
ass:rect(rect.ax, rect.ay, rect.bx, rect.by, {

View File

@@ -66,8 +66,10 @@ function VolumeSlider:render()
cursor.on_wheel_down = function() self:handle_wheel_down() end
cursor.on_wheel_up = function() self:handle_wheel_up() end
end
if self.pressed then cursor.on_primary_up = function()
self.pressed = false end
if self.pressed then
cursor.on_primary_up = function()
self.pressed = false
end
end
local ass = assdraw.ass_new()
@@ -166,13 +168,17 @@ function VolumeSlider:render()
local font_size = round(((width * 0.6) - (#volume_string * (width / 20))) * options.font_scale)
if volume_y < self.by - self.spacing then
ass:txt(self.ax + (width / 2), self.by - self.spacing, 2, volume_string, {
size = font_size, color = fgt, opacity = visibility,
size = font_size,
color = fgt,
opacity = visibility,
clip = '\\clip(' .. fg_path.scale .. ', ' .. fg_path.text .. ')',
})
end
if volume_y > self.by - self.spacing - font_size then
ass:txt(self.ax + (width / 2), self.by - self.spacing, 2, volume_string, {
size = font_size, color = bgt, opacity = visibility,
size = font_size,
color = bgt,
opacity = visibility,
clip = '\\iclip(' .. fg_path.scale .. ', ' .. fg_path.text .. ')',
})
end
@@ -181,7 +187,10 @@ function VolumeSlider:render()
if not state.has_audio then
local fg_100_path = create_nudged_path(self.border_size, state.radius)
local texture_opts = {
size = 200, color = 'ffffff', opacity = visibility * 0.1, anchor_x = ax,
size = 200,
color = 'ffffff',
opacity = visibility * 0.1,
anchor_x = ax,
clip = '\\clip(' .. fg_100_path.scale .. ',' .. fg_100_path.text .. ')',
}
ass:texture(ax, ay, bx, by, 'a', texture_opts)

View File

@@ -1,62 +1,62 @@
{
"Aspect ratio": "Seitenverhältnis",
"Audio": "Audio",
"Audio device": "Audiogerät",
"Audio devices": "Audiogeräte",
"Audio tracks": "Audiospuren",
"Autoselect device": "Automatische Geräteauswahl",
"Chapter %s": "Kapitel %s",
"Chapters": "Kapitel",
"Default": "Standard",
"Default %s": "Standard %s",
"Delete file & Next": "Lösche Datei & Nächstes",
"Delete file & Prev": "Lösche Datei & Vorheriges",
"Delete file & Quit": "Lösche Datei & Beenden",
"Disabled": "Deaktiviert",
"Drives": "Laufwerke",
"Edition": "Edition",
"Edition %s": "Edition %s",
"Editions": "Editionen",
"Empty": "Leer",
"First": "Erstes",
"Fullscreen": "Vollbild",
"Last": "Letztes",
"Load": "Hinzufügen",
"Load audio": "Audio hinzufügen",
"Load subtitles": "Untertitel hinzufügen",
"Load video": "Video hinzufügen",
"Loop file": "Datei wiederholen",
"Loop playlist": "Wiedergabeliste wiederholen",
"Menu": "Menü",
"Navigation": "Navigation",
"Next": "Nächstes",
"No file": "Keine Datei",
"Open config folder": "Konfigurationsordner öffnen",
"Open file": "Datei öffnen",
"Playlist": "Wiedergabeliste",
"Playlist/Files": "Wiedergabeliste/Dateien",
"Prev": "Vorheriges",
"Previous": "Vorheriges",
"Quit": "Beenden",
"Screenshot": "Bildschirmfoto",
"Show in directory": "Im Verzeichnis anzeigen",
"Shuffle": "Zufällig",
"Stream quality": "Streamqualität",
"Subtitles": "Untertitel",
"Track": "Spur",
"Track %s": "Spur %s",
"Utils": "Werkzeuge",
"Video": "Video",
"%s channels": "%s Kanäle",
"%s channel": "%s Kanal",
"default": "Standard",
"drive": "Laufwerk",
"external": "extern",
"forced": "erzwungen",
"open file": "Datei öffnen",
"parent dir": "übergeordnetes Verzeichnis",
"playlist or file": "Wiedergabeliste oder Datei",
"type & ctrl+enter to search": "Tippe & Strg+Eingabe um zu suchen",
"type to search": "Tippe um zu suchen",
"Inputs": "Tastenkürzel"
"Aspect ratio": "Seitenverhältnis",
"Audio": "Audio",
"Audio device": "Audiogerät",
"Audio devices": "Audiogeräte",
"Audio tracks": "Audiospuren",
"Autoselect device": "Automatische Geräteauswahl",
"Chapter %s": "Kapitel %s",
"Chapters": "Kapitel",
"Default": "Standard",
"Default %s": "Standard %s",
"Delete file & Next": "Lösche Datei & Nächstes",
"Delete file & Prev": "Lösche Datei & Vorheriges",
"Delete file & Quit": "Lösche Datei & Beenden",
"Disabled": "Deaktiviert",
"Drives": "Laufwerke",
"Edition": "Edition",
"Edition %s": "Edition %s",
"Editions": "Editionen",
"Empty": "Leer",
"First": "Erstes",
"Fullscreen": "Vollbild",
"Last": "Letztes",
"Load": "Hinzufügen",
"Load audio": "Audio hinzufügen",
"Load subtitles": "Untertitel hinzufügen",
"Load video": "Video hinzufügen",
"Loop file": "Datei wiederholen",
"Loop playlist": "Wiedergabeliste wiederholen",
"Menu": "Menü",
"Navigation": "Navigation",
"Next": "Nächstes",
"No file": "Keine Datei",
"Open config folder": "Konfigurationsordner öffnen",
"Open file": "Datei öffnen",
"Playlist": "Wiedergabeliste",
"Playlist/Files": "Wiedergabeliste/Dateien",
"Prev": "Vorheriges",
"Previous": "Vorheriges",
"Quit": "Beenden",
"Screenshot": "Bildschirmfoto",
"Show in directory": "Im Verzeichnis anzeigen",
"Shuffle": "Zufällig",
"Stream quality": "Streamqualität",
"Subtitles": "Untertitel",
"Track": "Spur",
"Track %s": "Spur %s",
"Utils": "Werkzeuge",
"Video": "Video",
"%s channels": "%s Kanäle",
"%s channel": "%s Kanal",
"default": "Standard",
"drive": "Laufwerk",
"external": "extern",
"forced": "erzwungen",
"open file": "Datei öffnen",
"parent dir": "übergeordnetes Verzeichnis",
"playlist or file": "Wiedergabeliste oder Datei",
"type & ctrl+enter to search": "Tippe & Strg+Eingabe um zu suchen",
"type to search": "Tippe um zu suchen",
"Inputs": "Tastenkürzel"
}

View File

@@ -1,59 +1,59 @@
{
"Aspect ratio": "Relación de aspecto",
"Audio": "Audio",
"Audio device": "Dispositivo de audio",
"Audio devices": "Dispositivos de audio",
"Audio tracks": "Pistas de audio",
"Autoselect device": "Selección automática",
"Chapter %s": "Capítulo %s",
"Chapters": "Capítulos",
"Default": "Por defecto",
"Default %s": "Por defecto %s",
"Delete file & Next": "Eliminar archivo y siguiente",
"Delete file & Prev": "Eliminar archivo y anterior",
"Delete file & Quit": "Eliminar archivo y salir",
"Disabled": "Desactivado",
"Drives": "Unidades",
"Edition": "Edición",
"Edition %s": "Edición %s",
"Editions": "Ediciones",
"Empty": "Vacío",
"First": "Primero",
"Fullscreen": "Pantalla completa",
"Last": "Último",
"Load": "Abrir",
"Load audio": "Añadir una pista de audio",
"Load subtitles": "Añadir una pista de subtítulos",
"Load video": "Añadir una pista de vídeo",
"Loop file": "Repetir archivo",
"Loop playlist": "Repetir lista de reproducción",
"Menu": "Menú",
"Navigation": "Navegación",
"Next": "Siguiente",
"No file": "Ningún archivo",
"Open config folder": "Abrir carpeta de configuración",
"Open file": "Abrir un archivo",
"Playlist": "Lista de reproducción",
"Playlist/Files": "Lista de reproducción / Archivos",
"Prev": "Anterior",
"Previous": "Anterior",
"Quit": "Salir",
"Screenshot": "Captura de pantalla",
"Show in directory": "Acceder a la carpeta",
"Shuffle": "Reproducción aleatoria",
"Stream quality": "Calidad del flujo",
"Subtitles": "Subtítulos",
"Track": "Pista",
"Track %s": "Pista %s",
"Utils": "Utilidades",
"Video": "Vídeo",
"%s channel": "%s canal",
"%s channels": "%s canales",
"default": "por defecto",
"drive": "unidad",
"external": "externo",
"forced": "forzado",
"open file": "seleccionar un archivo",
"parent dir": "directorio padre",
"playlist or file": "archivo o lista de reproducción"
"Aspect ratio": "Relación de aspecto",
"Audio": "Audio",
"Audio device": "Dispositivo de audio",
"Audio devices": "Dispositivos de audio",
"Audio tracks": "Pistas de audio",
"Autoselect device": "Selección automática",
"Chapter %s": "Capítulo %s",
"Chapters": "Capítulos",
"Default": "Por defecto",
"Default %s": "Por defecto %s",
"Delete file & Next": "Eliminar archivo y siguiente",
"Delete file & Prev": "Eliminar archivo y anterior",
"Delete file & Quit": "Eliminar archivo y salir",
"Disabled": "Desactivado",
"Drives": "Unidades",
"Edition": "Edición",
"Edition %s": "Edición %s",
"Editions": "Ediciones",
"Empty": "Vacío",
"First": "Primero",
"Fullscreen": "Pantalla completa",
"Last": "Último",
"Load": "Abrir",
"Load audio": "Añadir una pista de audio",
"Load subtitles": "Añadir una pista de subtítulos",
"Load video": "Añadir una pista de vídeo",
"Loop file": "Repetir archivo",
"Loop playlist": "Repetir lista de reproducción",
"Menu": "Menú",
"Navigation": "Navegación",
"Next": "Siguiente",
"No file": "Ningún archivo",
"Open config folder": "Abrir carpeta de configuración",
"Open file": "Abrir un archivo",
"Playlist": "Lista de reproducción",
"Playlist/Files": "Lista de reproducción / Archivos",
"Prev": "Anterior",
"Previous": "Anterior",
"Quit": "Salir",
"Screenshot": "Captura de pantalla",
"Show in directory": "Acceder a la carpeta",
"Shuffle": "Reproducción aleatoria",
"Stream quality": "Calidad del flujo",
"Subtitles": "Subtítulos",
"Track": "Pista",
"Track %s": "Pista %s",
"Utils": "Utilidades",
"Video": "Vídeo",
"%s channel": "%s canal",
"%s channels": "%s canales",
"default": "por defecto",
"drive": "unidad",
"external": "externo",
"forced": "forzado",
"open file": "seleccionar un archivo",
"parent dir": "directorio padre",
"playlist or file": "archivo o lista de reproducción"
}

View File

@@ -1,59 +1,59 @@
{
"Aspect ratio": "Format d'image",
"Audio": "Audio",
"Audio device": "Périphérique audio",
"Audio devices": "Périphériques audio",
"Audio tracks": "Pistes audio",
"Autoselect device": "Sélection automatique",
"Chapter %s": "Chapitre %s",
"Chapters": "Chapitres",
"Default": "Par défaut",
"Default %s": "Par défaut %s",
"Delete file & Next": "Supprimer le fichier et Suivant",
"Delete file & Prev": "Supprimer le fichier et Précédent",
"Delete file & Quit": "Supprimer le fichier et Quitter",
"Disabled": "Désactivé",
"Drives": "Lecteurs",
"Edition": "Édition",
"Edition %s": "Édition %s",
"Editions": "Éditions",
"Empty": "Vide",
"First": "Premier",
"Fullscreen": "Plein écran",
"Last": "Dernier",
"Load": "Ouvrir",
"Load audio": "Ajouter une piste audio",
"Load subtitles": "Ajouter une piste de sous-titres",
"Load video": "Ajouter une piste vidéo",
"Loop file": "Lire en boucle le fichier",
"Loop playlist": "Lire en boucle la liste de lecture",
"Menu": "Menu",
"Navigation": "Navigation",
"Next": "Suivant",
"No file": "Aucun fichier",
"Open config folder": "Ouvrir le dossier de configuration",
"Open file": "Ouvrir un fichier",
"Playlist": "Liste de lecture",
"Playlist/Files": "Liste de lecture / Fichiers",
"Prev": "Précédent",
"Previous": "Précédent",
"Quit": "Quitter",
"Screenshot": "Capture d'écran",
"Show in directory": "Accéder au dossier",
"Shuffle": "Lecture aléatoire",
"Stream quality": "Qualité du flux",
"Subtitles": "Sous-titres",
"Track": "Piste",
"Track %s": "Piste %s",
"Utils": "Outils",
"Video": "Vidéo",
"%s channel": "%s canal",
"%s channels": "%s canaux",
"default": "par défaut",
"drive": "lecteur",
"external": "externe",
"forced": "forcé",
"open file": "sélectionner un fichier",
"parent dir": "répertoire parent",
"playlist or file": "fichier ou liste de lecture"
"Aspect ratio": "Format d'image",
"Audio": "Audio",
"Audio device": "Périphérique audio",
"Audio devices": "Périphériques audio",
"Audio tracks": "Pistes audio",
"Autoselect device": "Sélection automatique",
"Chapter %s": "Chapitre %s",
"Chapters": "Chapitres",
"Default": "Par défaut",
"Default %s": "Par défaut %s",
"Delete file & Next": "Supprimer le fichier et Suivant",
"Delete file & Prev": "Supprimer le fichier et Précédent",
"Delete file & Quit": "Supprimer le fichier et Quitter",
"Disabled": "Désactivé",
"Drives": "Lecteurs",
"Edition": "Édition",
"Edition %s": "Édition %s",
"Editions": "Éditions",
"Empty": "Vide",
"First": "Premier",
"Fullscreen": "Plein écran",
"Last": "Dernier",
"Load": "Ouvrir",
"Load audio": "Ajouter une piste audio",
"Load subtitles": "Ajouter une piste de sous-titres",
"Load video": "Ajouter une piste vidéo",
"Loop file": "Lire en boucle le fichier",
"Loop playlist": "Lire en boucle la liste de lecture",
"Menu": "Menu",
"Navigation": "Navigation",
"Next": "Suivant",
"No file": "Aucun fichier",
"Open config folder": "Ouvrir le dossier de configuration",
"Open file": "Ouvrir un fichier",
"Playlist": "Liste de lecture",
"Playlist/Files": "Liste de lecture / Fichiers",
"Prev": "Précédent",
"Previous": "Précédent",
"Quit": "Quitter",
"Screenshot": "Capture d'écran",
"Show in directory": "Accéder au dossier",
"Shuffle": "Lecture aléatoire",
"Stream quality": "Qualité du flux",
"Subtitles": "Sous-titres",
"Track": "Piste",
"Track %s": "Piste %s",
"Utils": "Outils",
"Video": "Vidéo",
"%s channel": "%s canal",
"%s channels": "%s canaux",
"default": "par défaut",
"drive": "lecteur",
"external": "externe",
"forced": "forcé",
"open file": "sélectionner un fichier",
"parent dir": "répertoire parent",
"playlist or file": "fichier ou liste de lecture"
}

View File

@@ -1,59 +1,59 @@
{
"Aspect ratio": "Raportul de aspect",
"Audio": "Audio",
"Audio device": "Dispozitiv audio",
"Audio devices": "Dispozitive audio",
"Audio tracks": "Piese audio",
"Autoselect device": "Selectare automată",
"Chapter %s": "Capitolul %s",
"Chapters": "Capitole",
"Default": "Implicit",
"Default %s": "Implicit %s",
"Delete file & Next": "Ștergere fișier și următorul",
"Delete file & Prev": "Ștergere fișier și anteriorul",
"Delete file & Quit": "Ștergere fișier și ieși",
"Disabled": "Dezactivat",
"Drives": "Unități",
"Edition": "Ediție",
"Edition %s": "Ediție %s",
"Editions": "Ediții",
"Empty": "Gol",
"First": "Primul",
"Fullscreen": "Ecran complet",
"Last": "Ultimul",
"Load": "Încarcă",
"Load audio": "Deschide audio",
"Load subtitles": "Deschide subtitrările",
"Load video": "Deschide video",
"Loop file": "Repetă fișierul",
"Loop playlist": "Repetă lista de redare",
"Menu": "Meniu",
"Navigation": "Navigare",
"Next": "Următor",
"No file": "Niciun fisier",
"Open config folder": "Deschide dosarul de configurație",
"Open file": "Deschide fișierul",
"Playlist": "Listă de redare",
"Playlist/Files": "Listă de redare/Fișiere",
"Prev": "Precedent",
"Previous": "Precedent",
"Quit": "Ieșire",
"Screenshot": "Captură de ecran",
"Show in directory": "Arată în dosar",
"Shuffle": "Amestecă",
"Stream quality": "Calitatea fluxului",
"Subtitles": "Subtitrări",
"Track": "Pistă",
"Track %s": "Pistă %s",
"Utils": "Utilități",
"Video": "Video",
"%s channel": "%s canal",
"%s channels": "%s canale",
"default": "implicit",
"drive": "unitate",
"external": "extern",
"forced": "forțat",
"open file": "deschide fișierul",
"parent dir": "director părinte",
"playlist or file": "fișier sau listă de redare"
"Aspect ratio": "Raportul de aspect",
"Audio": "Audio",
"Audio device": "Dispozitiv audio",
"Audio devices": "Dispozitive audio",
"Audio tracks": "Piese audio",
"Autoselect device": "Selectare automată",
"Chapter %s": "Capitolul %s",
"Chapters": "Capitole",
"Default": "Implicit",
"Default %s": "Implicit %s",
"Delete file & Next": "Ștergere fișier și următorul",
"Delete file & Prev": "Ștergere fișier și anteriorul",
"Delete file & Quit": "Ștergere fișier și ieși",
"Disabled": "Dezactivat",
"Drives": "Unități",
"Edition": "Ediție",
"Edition %s": "Ediție %s",
"Editions": "Ediții",
"Empty": "Gol",
"First": "Primul",
"Fullscreen": "Ecran complet",
"Last": "Ultimul",
"Load": "Încarcă",
"Load audio": "Deschide audio",
"Load subtitles": "Deschide subtitrările",
"Load video": "Deschide video",
"Loop file": "Repetă fișierul",
"Loop playlist": "Repetă lista de redare",
"Menu": "Meniu",
"Navigation": "Navigare",
"Next": "Următor",
"No file": "Niciun fisier",
"Open config folder": "Deschide dosarul de configurație",
"Open file": "Deschide fișierul",
"Playlist": "Listă de redare",
"Playlist/Files": "Listă de redare/Fișiere",
"Prev": "Precedent",
"Previous": "Precedent",
"Quit": "Ieșire",
"Screenshot": "Captură de ecran",
"Show in directory": "Arată în dosar",
"Shuffle": "Amestecă",
"Stream quality": "Calitatea fluxului",
"Subtitles": "Subtitrări",
"Track": "Pistă",
"Track %s": "Pistă %s",
"Utils": "Utilități",
"Video": "Video",
"%s channel": "%s canal",
"%s channels": "%s canale",
"default": "implicit",
"drive": "unitate",
"external": "extern",
"forced": "forțat",
"open file": "deschide fișierul",
"parent dir": "director părinte",
"playlist or file": "fișier sau listă de redare"
}

View File

@@ -1,59 +1,59 @@
{
"Aspect ratio": "Соотношение сторон",
"Audio": "Аудио",
"Audio device": "Аудиоустройство",
"Audio devices": "Аудиоустройства",
"Audio tracks": "Аудиодорожки",
"Autoselect device": "Автовыбор устройства",
"Chapter %s": "Глава %s",
"Chapters": "Главы",
"Default": "По умолчанию",
"Default %s": "По умолчанию %s",
"Delete file & Next": "Удалить файл и след.",
"Delete file & Prev": "Удалить файл и пред.",
"Delete file & Quit": "Удалить файл и выйти",
"Disabled": "Отключено",
"Drives": "Диски",
"Edition": "Редакция",
"Edition %s": "Редакция %s",
"Editions": "Редакции",
"Empty": "Пусто",
"First": "Первый",
"Fullscreen": "Полный экран",
"Last": "Последний",
"Load": "Загрузить",
"Load audio": "Загрузить аудио",
"Load subtitles": "Загрузить субтитры",
"Load video": "Загрузить видео",
"Loop file": "Повторять файл",
"Loop playlist": "Повторять плейлист",
"Menu": "Меню",
"Navigation": "Навигация",
"Next": "Следующий",
"No file": "Нет файла",
"Open config folder": "Открыть папку конфигурации",
"Open file": "Открыть файл",
"Playlist": "Плейлист",
"Playlist/Files": "Плейлист / файлы",
"Prev": "Предыдущий",
"Previous": "Предыдущий",
"Quit": "Выйти",
"Screenshot": "Скриншот",
"Show in directory": "Показать в папке",
"Shuffle": "Перемешать",
"Stream quality": "Качество потока",
"Subtitles": "Субтитры",
"Track": "Дорожка",
"Track %s": "Дорожка %s",
"Utils": "Инструменты",
"Video": "Видео",
"%s channels": "%s канала/-ов",
"%s channel": "%s канал",
"default": "по умолчанию",
"drive": "диск",
"external": "внешняя",
"forced": "форсированная",
"open file": "открыть файл",
"parent dir": "родительская папка",
"playlist or file": "плейлист или файл"
"Aspect ratio": "Соотношение сторон",
"Audio": "Аудио",
"Audio device": "Аудиоустройство",
"Audio devices": "Аудиоустройства",
"Audio tracks": "Аудиодорожки",
"Autoselect device": "Автовыбор устройства",
"Chapter %s": "Глава %s",
"Chapters": "Главы",
"Default": "По умолчанию",
"Default %s": "По умолчанию %s",
"Delete file & Next": "Удалить файл и след.",
"Delete file & Prev": "Удалить файл и пред.",
"Delete file & Quit": "Удалить файл и выйти",
"Disabled": "Отключено",
"Drives": "Диски",
"Edition": "Редакция",
"Edition %s": "Редакция %s",
"Editions": "Редакции",
"Empty": "Пусто",
"First": "Первый",
"Fullscreen": "Полный экран",
"Last": "Последний",
"Load": "Загрузить",
"Load audio": "Загрузить аудио",
"Load subtitles": "Загрузить субтитры",
"Load video": "Загрузить видео",
"Loop file": "Повторять файл",
"Loop playlist": "Повторять плейлист",
"Menu": "Меню",
"Navigation": "Навигация",
"Next": "Следующий",
"No file": "Нет файла",
"Open config folder": "Открыть папку конфигурации",
"Open file": "Открыть файл",
"Playlist": "Плейлист",
"Playlist/Files": "Плейлист / файлы",
"Prev": "Предыдущий",
"Previous": "Предыдущий",
"Quit": "Выйти",
"Screenshot": "Скриншот",
"Show in directory": "Показать в папке",
"Shuffle": "Перемешать",
"Stream quality": "Качество потока",
"Subtitles": "Субтитры",
"Track": "Дорожка",
"Track %s": "Дорожка %s",
"Utils": "Инструменты",
"Video": "Видео",
"%s channels": "%s канала/-ов",
"%s channel": "%s канал",
"default": "по умолчанию",
"drive": "диск",
"external": "внешняя",
"forced": "форсированная",
"open file": "открыть файл",
"parent dir": "родительская папка",
"playlist or file": "плейлист или файл"
}

View File

@@ -1,63 +1,63 @@
{
"Aspect ratio": "纵横比",
"Audio": "音频",
"Audio device": "音频设备",
"Audio devices": "音频设备",
"Audio tracks": "音频轨道",
"Autoselect device": "自动选择",
"Chapter %s": "第 %s 章",
"Chapters": "章节",
"Default": "默认",
"Default %s": "默认 %s",
"Delete file & Next": "删除文件并播放下一个",
"Delete file & Prev": "删除文件并播放上一个",
"Delete file & Quit": "删除文件并退出",
"Disabled": "禁用",
"Drives": "驱动器",
"Edition": "版本",
"Edition %s": "版本 %s",
"Editions": "版本",
"Empty": "空",
"First": "第一个",
"Fullscreen": "全屏",
"Last": "最后一个",
"Load": "加载",
"Load audio": "加载音频",
"Load subtitles": "加载字幕",
"Load video": "加载视频",
"Loop file": "单个循环",
"Loop playlist": "列表循环",
"Menu": "菜单",
"Navigation": "导航",
"Next": "下一个",
"No file": "无文件",
"Open config folder": "打开设置文件夹",
"Open file": "打开文件",
"Playlist": "播放列表",
"Playlist/Files": "播放/文件列表",
"Prev": "上一个",
"Previous": "上一个",
"Quit": "退出",
"Screenshot": "截图",
"Show in directory": "打开所在文件夹",
"Shuffle": "乱序",
"Stream quality": "流媒体品质",
"Subtitles": "字幕",
"Track": "轨道",
"Track %s": "轨道 %s",
"Utils": "工具",
"Video": "视频",
"%s channel": "%s 声道",
"%s channels": "%s 声道",
"default": "默认",
"drive": "磁盘",
"external": "外置",
"forced": "强制",
"open file": "打开文件",
"parent dir": "父文件夹",
"playlist or file": "播放列表或文件",
"type to search": "输入搜索内容",
"type & ctrl+enter to search": "输入并按 ctrl+enter 进行搜索",
"Inputs": "输入",
"Drop files or URLs to play here": "拖放文件或 URL 到此处进行播放"
"Aspect ratio": "纵横比",
"Audio": "音频",
"Audio device": "音频设备",
"Audio devices": "音频设备",
"Audio tracks": "音频轨道",
"Autoselect device": "自动选择",
"Chapter %s": "第 %s 章",
"Chapters": "章节",
"Default": "默认",
"Default %s": "默认 %s",
"Delete file & Next": "删除文件并播放下一个",
"Delete file & Prev": "删除文件并播放上一个",
"Delete file & Quit": "删除文件并退出",
"Disabled": "禁用",
"Drives": "驱动器",
"Edition": "版本",
"Edition %s": "版本 %s",
"Editions": "版本",
"Empty": "空",
"First": "第一个",
"Fullscreen": "全屏",
"Last": "最后一个",
"Load": "加载",
"Load audio": "加载音频",
"Load subtitles": "加载字幕",
"Load video": "加载视频",
"Loop file": "单个循环",
"Loop playlist": "列表循环",
"Menu": "菜单",
"Navigation": "导航",
"Next": "下一个",
"No file": "无文件",
"Open config folder": "打开设置文件夹",
"Open file": "打开文件",
"Playlist": "播放列表",
"Playlist/Files": "播放/文件列表",
"Prev": "上一个",
"Previous": "上一个",
"Quit": "退出",
"Screenshot": "截图",
"Show in directory": "打开所在文件夹",
"Shuffle": "乱序",
"Stream quality": "流媒体品质",
"Subtitles": "字幕",
"Track": "轨道",
"Track %s": "轨道 %s",
"Utils": "工具",
"Video": "视频",
"%s channel": "%s 声道",
"%s channels": "%s 声道",
"default": "默认",
"drive": "磁盘",
"external": "外置",
"forced": "强制",
"open file": "打开文件",
"parent dir": "父文件夹",
"playlist or file": "播放列表或文件",
"type to search": "输入搜索内容",
"type & ctrl+enter to search": "输入并按 ctrl+enter 进行搜索",
"Inputs": "输入",
"Drop files or URLs to play here": "拖放文件或 URL 到此处进行播放"
}

View File

@@ -98,7 +98,7 @@ function ass_mt:tooltip(element, value, opts)
local by = (align_top and y or y + opts.size * opts.lines + 2 * padding_y)
self:rect(ax, ay, bx, by, {color = bg, opacity = config.opacity.tooltip, radius = state.radius})
self:txt(x, align_top and y - padding_y or y + padding_y, align_top and 2 or 8, value, opts)
return { ax = element.ax, ay = ay, bx = element.bx, by = by }
return {ax = element.ax, ay = ay, bx = element.bx, by = by}
end
-- Rectangle.

View File

@@ -13,7 +13,7 @@ function get_languages()
itable_append(languages, slang)
end
else
itable_append(languages, { lang })
itable_append(languages, {lang})
end
end
@@ -22,7 +22,7 @@ end
---@param path string
function get_locale_from_json(path)
local expand_path = mp.command_native({ 'expand-path', path })
local expand_path = mp.command_native({'expand-path', path})
local meta, meta_error = utils.file_info(expand_path)
if not meta or not meta.is_file then

View File

@@ -22,14 +22,20 @@ end
---@param opts? {submenu?: string; mouse_nav?: boolean; on_close?: string | string[]}
function toggle_menu_with_items(opts)
if Menu:is_open('menu') then Menu:close()
else open_command_menu({type = 'menu', items = get_menu_items(), search_submenus = true}, opts) end
if Menu:is_open('menu') then
Menu:close()
else
open_command_menu({type = 'menu', items = get_menu_items(), search_submenus = true}, opts)
end
end
---@param options {type: string; title: string; list_prop: string; active_prop?: string; serializer: fun(list: any, active: any): MenuDataItem[]; on_select: fun(value: any); on_move_item?: fun(from_index: integer, to_index: integer, submenu_path: integer[]); on_delete_item?: fun(index: integer, submenu_path: integer[])}
function create_self_updating_menu_opener(options)
return function()
if Menu:is_open(options.type) then Menu:close() return end
if Menu:is_open(options.type) then
Menu:close()
return
end
local list = mp.get_property_native(options.list_prop)
local active = options.active_prop and mp.get_property_native(options.active_prop) or nil
local menu
@@ -38,14 +44,22 @@ function create_self_updating_menu_opener(options)
local ignore_initial_list = true
local function handle_list_prop_change(name, value)
if ignore_initial_list then ignore_initial_list = false
else list = value update() end
if ignore_initial_list then
ignore_initial_list = false
else
list = value
update()
end
end
local ignore_initial_active = true
local function handle_active_prop_change(name, value)
if ignore_initial_active then ignore_initial_active = false
else active = value update() end
if ignore_initial_active then
ignore_initial_active = false
else
active = value
update()
end
end
local initial_items, selected_index = options.serializer(list, active)
@@ -55,19 +69,19 @@ function create_self_updating_menu_opener(options)
menu = Menu:open(
{type = options.type, title = options.title, items = initial_items, selected_index = selected_index},
options.on_select, {
on_open = function()
mp.observe_property(options.list_prop, 'native', handle_list_prop_change)
if options.active_prop then
mp.observe_property(options.active_prop, 'native', handle_active_prop_change)
end
end,
on_close = function()
mp.unobserve_property(handle_list_prop_change)
mp.unobserve_property(handle_active_prop_change)
end,
on_move_item = options.on_move_item,
on_delete_item = options.on_delete_item,
})
on_open = function()
mp.observe_property(options.list_prop, 'native', handle_list_prop_change)
if options.active_prop then
mp.observe_property(options.active_prop, 'native', handle_active_prop_change)
end
end,
on_close = function()
mp.unobserve_property(handle_list_prop_change)
mp.unobserve_property(handle_active_prop_change)
end,
on_move_item = options.on_move_item,
on_delete_item = options.on_delete_item,
})
end
end
@@ -106,7 +120,8 @@ function create_select_tracklist_type_menu_opener(menu_title, track_type, track_
end
if track['demux-fps'] then h(string.format('%.5gfps', track['demux-fps'])) end
h(track.codec)
if track['audio-channels'] then h(t(track['audio-channels'] == 1 and '%s channel' or '%s channels', track['audio-channels'])) end
if track['audio-channels'] then h(t(track['audio-channels'] == 1 and '%s channel' or '%s channels',
track['audio-channels'])) end
if track['demux-samplerate'] then h(string.format('%.3gkHz', track['demux-samplerate'] / 1000)) end
if track.forced then h(t('forced')) end
if track.default then h(t('default')) end
@@ -168,7 +183,7 @@ function open_file_navigation_menu(directory_path, handle_select, opts)
local files, directories = read_directory(directory.path, {
types = opts.allowed_types,
hidden = options.show_hidden_files
hidden = options.show_hidden_files,
})
local is_root = not directory.dirname
local path_separator = path_separator(directory.path)
@@ -222,8 +237,11 @@ function open_file_navigation_menu(directory_path, handle_select, opts)
open_drives_menu(function(drive_path)
open_file_navigation_menu(drive_path, handle_select, inheritable_options)
end, {
type = inheritable_options.type, title = inheritable_options.title, selected_path = directory.path,
on_open = opts.on_open, on_close = opts.on_close,
type = inheritable_options.type,
title = inheritable_options.title,
selected_path = directory.path,
on_open = opts.on_open,
on_close = opts.on_close,
})
return
end
@@ -252,7 +270,9 @@ function open_file_navigation_menu(directory_path, handle_select, opts)
end
local menu_data = {
type = opts.type, title = opts.title or directory.basename .. path_separator, items = items,
type = opts.type,
title = opts.title or directory.basename .. path_separator,
items = items,
selected_index = selected_index,
}
local menu_options = {on_open = opts.on_open, on_close = opts.on_close, on_back = handle_back}
@@ -382,17 +402,17 @@ end
-- Adapted from `stats.lua`
function get_input_items()
local bindings = mp.get_property_native("input-bindings", {})
local active = {} -- map: key-name -> bind-info
local bindings = mp.get_property_native('input-bindings', {})
local active = {} -- map: key-name -> bind-info
local items = {}
-- Find active keybinds
for _, bind in pairs(bindings) do
if bind.priority >= 0 and (
not active[bind.key]
or (active[bind.key].is_weak and not bind.is_weak)
or (bind.is_weak == active[bind.key].is_weak and bind.priority > active[bind.key].priority)
)
not active[bind.key]
or (active[bind.key].is_weak and not bind.is_weak)
or (bind.is_weak == active[bind.key].is_weak and bind.priority > active[bind.key].priority)
)
then
active[bind.key] = bind
end
@@ -412,7 +432,7 @@ function get_input_items()
selectable = false,
align = 'center',
italic = true,
muted = true
}
muted = true,
},
}
end

View File

@@ -3,33 +3,33 @@
---@type CodePointRange[]
local zero_width_blocks = {
{0x0000, 0x001F}, -- C0
{0x007F, 0x009F}, -- Delete + C1
{0x034F, 0x034F}, -- combining grapheme joiner
{0x061C, 0x061C}, -- Arabic Letter Strong
{0x200B, 0x200F}, -- {zero-width space, zero-width non-joiner, zero-width joiner, left-to-right mark, right-to-left mark}
{0x2028, 0x202E}, -- {line separator, paragraph separator, Left-to-Right Embedding, Right-to-Left Embedding, Pop Directional Format, Left-to-Right Override, Right-to-Left Override}
{0x2060, 0x2060}, -- word joiner
{0x2066, 0x2069}, -- {Left-to-Right Isolate, Right-to-Left Isolate, First Strong Isolate, Pop Directional Isolate}
{0xFEFF, 0xFEFF}, -- zero-width non-breaking space
{0x0000, 0x001F}, -- C0
{0x007F, 0x009F}, -- Delete + C1
{0x034F, 0x034F}, -- combining grapheme joiner
{0x061C, 0x061C}, -- Arabic Letter Strong
{0x200B, 0x200F}, -- {zero-width space, zero-width non-joiner, zero-width joiner, left-to-right mark, right-to-left mark}
{0x2028, 0x202E}, -- {line separator, paragraph separator, Left-to-Right Embedding, Right-to-Left Embedding, Pop Directional Format, Left-to-Right Override, Right-to-Left Override}
{0x2060, 0x2060}, -- word joiner
{0x2066, 0x2069}, -- {Left-to-Right Isolate, Right-to-Left Isolate, First Strong Isolate, Pop Directional Isolate}
{0xFEFF, 0xFEFF}, -- zero-width non-breaking space
-- Some other characters can also be combined https://en.wikipedia.org/wiki/Combining_character
{0x0300, 0x036F}, -- Combining Diacritical Marks 0 BMP Inherited
{0x1AB0, 0x1AFF}, -- Combining Diacritical Marks Extended 0 BMP Inherited
{0x1DC0, 0x1DFF}, -- Combining Diacritical Marks Supplement 0 BMP Inherited
{0x20D0, 0x20FF}, -- Combining Diacritical Marks for Symbols 0 BMP Inherited
{0xFE20, 0xFE2F}, -- Combining Half Marks 0 BMP Cyrillic (2 characters), Inherited (14 characters)
{0x0300, 0x036F}, -- Combining Diacritical Marks 0 BMP Inherited
{0x1AB0, 0x1AFF}, -- Combining Diacritical Marks Extended 0 BMP Inherited
{0x1DC0, 0x1DFF}, -- Combining Diacritical Marks Supplement 0 BMP Inherited
{0x20D0, 0x20FF}, -- Combining Diacritical Marks for Symbols 0 BMP Inherited
{0xFE20, 0xFE2F}, -- Combining Half Marks 0 BMP Cyrillic (2 characters), Inherited (14 characters)
-- Egyptian Hieroglyph Format Controls and Shorthand format Controls
{0x13430, 0x1345F}, -- Egyptian Hieroglyph Format Controls 1 SMP Egyptian Hieroglyphs
{0x1BCA0, 0x1BCAF}, -- Shorthand Format Controls 1 SMP Common
-- not sure how to deal with those https://en.wikipedia.org/wiki/Spacing_Modifier_Letters
{0x02B0, 0x02FF}, -- Spacing Modifier Letters 0 BMP Bopomofo (2 characters), Latin (14 characters), Common (64 characters)
{0x02B0, 0x02FF}, -- Spacing Modifier Letters 0 BMP Bopomofo (2 characters), Latin (14 characters), Common (64 characters)
}
-- All characters have the same width as the first one
---@type CodePointRange[]
local same_width_blocks = {
{0x3400, 0x4DBF}, -- CJK Unified Ideographs Extension A 0 BMP Han
{0x4E00, 0x9FFF}, -- CJK Unified Ideographs 0 BMP Han
{0x3400, 0x4DBF}, -- CJK Unified Ideographs Extension A 0 BMP Han
{0x4E00, 0x9FFF}, -- CJK Unified Ideographs 0 BMP Han
{0x20000, 0x2A6DF}, -- CJK Unified Ideographs Extension B 2 SIP Han
{0x2A700, 0x2B73F}, -- CJK Unified Ideographs Extension C 2 SIP Han
{0x2B740, 0x2B81F}, -- CJK Unified Ideographs Extension D 2 SIP Han
@@ -52,11 +52,17 @@ local osd_width, osd_height = 100, 100
local function utf8_char_bytes(str, i)
local char_byte = str:byte(i)
local max_bytes = #str - i + 1
if char_byte < 0xC0 then return math.min(max_bytes, 1)
elseif char_byte < 0xE0 then return math.min(max_bytes, 2)
elseif char_byte < 0xF0 then return math.min(max_bytes, 3)
elseif char_byte < 0xF8 then return math.min(max_bytes, 4)
else return math.min(max_bytes, 1) end
if char_byte < 0xC0 then
return math.min(max_bytes, 1)
elseif char_byte < 0xE0 then
return math.min(max_bytes, 2)
elseif char_byte < 0xF0 then
return math.min(max_bytes, 3)
elseif char_byte < 0xF8 then
return math.min(max_bytes, 4)
else
return math.min(max_bytes, 1)
end
end
---Creates an iterator for an utf-8 encoded string
@@ -98,13 +104,19 @@ end
---@param unicode integer
---@return string?
local function unicode_to_utf8(unicode)
if unicode < 0x80 then return string.char(unicode)
if unicode < 0x80 then
return string.char(unicode)
else
local byte_count
if unicode < 0x800 then byte_count = 2
elseif unicode < 0x10000 then byte_count = 3
elseif unicode < 0x110000 then byte_count = 4
else return end -- too big
if unicode < 0x800 then
byte_count = 2
elseif unicode < 0x10000 then
byte_count = 3
elseif unicode < 0x110000 then
byte_count = 4
else
return
end -- too big
local res = {}
local shift = 2 ^ 6
@@ -128,13 +140,13 @@ local function update_osd_resolution(width, height)
if width > 0 and height > 0 then osd_width, osd_height = width, height end
end
mp.observe_property('osd-dimensions', 'native', function (_, dim)
mp.observe_property('osd-dimensions', 'native', function(_, dim)
if dim then update_osd_resolution(dim.w, dim.h) end
end)
local measure_bounds
do
local text_osd = mp.create_osd_overlay("ass-events")
local text_osd = mp.create_osd_overlay('ass-events')
text_osd.compute_bounds, text_osd.hidden = true, true
---@param ass_text string
@@ -277,8 +289,11 @@ do
local size = math.min(max_size * 0.9, 50)
char_count = math.min(math.floor(char_count * max_size / size * 0.8), 100)
local enclosing_char, enclosing_width, next_char_count = '|', 0, char_count
if measured_char == enclosing_char then enclosing_char = ''
else enclosing_width = 2 * character_width(enclosing_char, bold) end
if measured_char == enclosing_char then
enclosing_char = ''
else
enclosing_width = 2 * character_width(enclosing_char, bold)
end
local width_ratio, width, px = nil, nil, nil
repeat
char_count = next_char_count
@@ -304,7 +319,7 @@ end
local function character_based_width(text, bold)
local max_width = 0
local min_px = math.huge
for line in tostring(text):gmatch("([^\n]*)\n?") do
for line in tostring(text):gmatch('([^\n]*)\n?') do
local total_width = 0
for _, char in utf8_iter(line) do
local width, px = character_width(char, bold)
@@ -397,8 +412,8 @@ do
end
do
local wrap_at_chars = { ' ', ' ', '-', '' }
local remove_when_wrap = { ' ', ' ' }
local wrap_at_chars = {' ', ' ', '-', ''}
local remove_when_wrap = {' ', ' '}
---Wrap the text at the closest opportunity to target_line_length
---@param text string
@@ -445,8 +460,11 @@ do
end
end
end
if #text_line >= line_start then lines[#lines + 1] = text_line:sub(line_start)
elseif text_line == '' then lines[#lines + 1] = '' end
if #text_line >= line_start then
lines[#lines + 1] = text_line:sub(line_start)
elseif text_line == '' then
lines[#lines + 1] = ''
end
end
return table.concat(lines, '\n'), #lines
end

View File

@@ -12,7 +12,7 @@ function sort_filenames(filenames)
local tuples = {}
for i, f in ipairs(filenames) do
tuples[i] = { f:lower():gsub('0*(%d+)%.?(%d*)', padnum), f }
tuples[i] = {f:lower():gsub('0*(%d+)%.?(%d*)', padnum), f}
end
table.sort(tuples, function(a, b)
return a[1] == b[1] and #b[2] < #a[2] or a[1] < b[1]
@@ -53,8 +53,11 @@ function tween(from, to, setter, duration_or_callback, callback)
local is_end = math.abs(to - current) <= cutoff
setter(is_end and to or current)
request_render()
if is_end then finish()
else timeout:resume() end
if is_end then
finish()
else
timeout:resume()
end
end
timeout = mp.add_timeout(state.render_delay, tick)
@@ -88,12 +91,12 @@ end
---@param mby number
function get_line_to_line_intersection(lax, lay, lbx, lby, max, may, mbx, mby)
-- Calculate the direction of the lines
local uA = ((mbx-max)*(lay-may) - (mby-may)*(lax-max)) / ((mby-may)*(lbx-lax) - (mbx-max)*(lby-lay))
local uB = ((lbx-lax)*(lay-may) - (lby-lay)*(lax-max)) / ((mby-may)*(lbx-lax) - (mbx-max)*(lby-lay))
local uA = ((mbx - max) * (lay - may) - (mby - may) * (lax - max)) / ((mby - may) * (lbx - lax) - (mbx - max) * (lby - lay))
local uB = ((lbx - lax) * (lay - may) - (lby - lay) * (lax - max)) / ((mby - may) * (lbx - lax) - (mbx - max) * (lby - lay))
-- If uA and uB are between 0-1, lines are colliding
if uA >= 0 and uA <= 1 and uB >= 0 and uB <= 1 then
return lax + (uA * (lbx-lax)), lay + (uA * (lby-lay))
return lax + (uA * (lbx - lax)), lay + (uA * (lby - lay))
end
return nil, nil
@@ -230,16 +233,20 @@ function join_path(p1, p2)
local p1, separator = trim_trailing_separator(p1)
-- Prevents joining drive letters with a redundant separator (`C:\\foo`),
-- as `trim_trailing_separator()` doesn't trim separators from drive letters.
return p1:sub(#p1) == separator and p1 .. p2 or p1 .. separator.. p2
return p1:sub(#p1) == separator and p1 .. p2 or p1 .. separator .. p2
end
-- Check if path is absolute.
---@param path string
---@return boolean
function is_absolute(path)
if path:sub(1, 2) == '\\\\' then return true
elseif state.platform == 'windows' then return path:find('^%a+:') ~= nil
else return path:sub(1, 1) == '/' end
if path:sub(1, 2) == '\\\\' then
return true
elseif state.platform == 'windows' then
return path:find('^%a+:') ~= nil
else
return path:sub(1, 1) == '/'
end
end
-- Ensure path is absolute.
@@ -287,9 +294,13 @@ function normalize_path(path)
path = trim_trailing_separator(path)
--Deduplication of path separators
if is_unc then path = path:gsub('(.\\)\\+', '%1')
elseif state.platform == 'windows' then path = path:gsub('\\\\+', '\\')
else path = path:gsub('//+', '/') end
if is_unc then
path = path:gsub('(.\\)\\+', '%1')
elseif state.platform == 'windows' then
path = path:gsub('\\\\+', '\\')
else
path = path:gsub('//+', '/')
end
return path
end
@@ -355,14 +366,16 @@ function read_directory(path, opts)
local files, directories = {}, {}
for _, item in ipairs(items) do
if item ~= '.' and item ~= '..' and (opts.hidden or item:sub(1, 1) ~= ".") then
if item ~= '.' and item ~= '..' and (opts.hidden or item:sub(1, 1) ~= '.') then
local info = utils.file_info(join_path(path, item))
if info then
if info.is_file then
if not opts.types or has_any_extension(item, opts.types) then
files[#files + 1] = item
end
else directories[#directories + 1] = item end
else
directories[#directories + 1] = item
end
end
end
end
@@ -410,7 +423,7 @@ function decide_navigation_in_list(paths, current_index, delta)
if state.shuffle then
state.shuffle_history = state.shuffle_history or {
pos = #state.history,
paths = itable_slice(state.history)
paths = itable_slice(state.history),
}
state.shuffle_history.pos = state.shuffle_history.pos + delta
local history_path = state.shuffle_history.paths[state.shuffle_history.pos]
@@ -442,8 +455,11 @@ function decide_navigation_in_list(paths, current_index, delta)
local new_index = current_index + delta
if mp.get_property_native('loop-playlist') then
if new_index > #paths then new_index = new_index % #paths
elseif new_index < 1 then new_index = #paths - new_index end
if new_index > #paths then
new_index = new_index % #paths
elseif new_index < 1 then
new_index = #paths - new_index
end
elseif new_index < 1 or new_index > #paths then
return
end
@@ -456,11 +472,14 @@ function navigate_directory(delta)
if not state.path or is_protocol(state.path) then return false end
local paths, current_index = get_adjacent_files(state.path, {
types = config.types.autoload,
hidden = options.show_hidden_files
hidden = options.show_hidden_files,
})
if paths and current_index then
local _, path = decide_navigation_in_list(paths, current_index, delta)
if path then mp.commandv('loadfile', path) return true end
if path then
mp.commandv('loadfile', path)
return true
end
end
return false
end
@@ -497,19 +516,19 @@ function delete_file(path)
]]
local escaped_path = string.gsub(path, "'", "''")
escaped_path = string.gsub(escaped_path, "", "")
escaped_path = string.gsub(escaped_path, "%%", "%%%%")
ps_code = string.gsub(ps_code, "__path__", escaped_path)
args = { 'powershell', '-NoProfile', '-Command', ps_code }
escaped_path = string.gsub(escaped_path, '', '')
escaped_path = string.gsub(escaped_path, '%%', '%%%%')
ps_code = string.gsub(ps_code, '__path__', escaped_path)
args = {'powershell', '-NoProfile', '-Command', ps_code}
else
args = { 'cmd', '/C', 'del', path }
args = {'cmd', '/C', 'del', path}
end
else
if options.use_trash then
--On Linux and Macos the app trash-cli/trash must be installed first.
args = { 'trash', path }
args = {'trash', path}
else
args = { 'rm', path }
args = {'rm', path}
end
end
return mp.command_native({
@@ -524,23 +543,37 @@ end
function serialize_chapter_ranges(normalized_chapters)
local ranges = {}
local simple_ranges = {
{name = 'openings', patterns = {
{
name = 'openings',
patterns = {
'^op ', '^op$', ' op$',
'^opening$', ' opening$'
}, requires_next_chapter = true},
{name = 'intros', patterns = {
'^opening$', ' opening$',
},
requires_next_chapter = true
},
{
name = 'intros',
patterns = {
'^intro$', ' intro$',
'^avant$', '^prologue$'
}, requires_next_chapter = true},
{name = 'endings', patterns = {
'^avant$', '^prologue$',
},
requires_next_chapter = true
},
{
name = 'endings',
patterns = {
'^ed ', '^ed$', ' ed$',
'^ending ', '^ending$', ' ending$',
}},
{name = 'outros', patterns = {
}
},
{
name = 'outros',
patterns = {
'^outro$', ' outro$',
'^closing$', '^closing ',
'^preview$', '^pv$',
}},
}
},
}
local sponsor_ranges = {}
@@ -580,8 +613,10 @@ function serialize_chapter_ranges(normalized_chapters)
local end_match = end_chapter.lowercase_title:match('segment end *%(' .. id .. '%)')
if end_match then
local range = table_assign({
start_chapter = chapter, end_chapter = end_chapter,
start = chapter.time, ['end'] = end_chapter.time,
start_chapter = chapter,
end_chapter = end_chapter,
start = chapter.time,
['end'] = end_chapter.time,
}, config.chapter_ranges.ads)
ranges[#ranges + 1], sponsor_ranges[#sponsor_ranges + 1] = range, range
end_chapter.is_end_only = true
@@ -663,10 +698,10 @@ function render()
local smaller_side = math.min(display.width, display.height)
local center_x, center_y, icon_size = display.width / 2, display.height / 2, math.max(smaller_side / 4, 56)
ass:icon(center_x, center_y - icon_size / 4, icon_size, 'not_started', {
color = fg, opacity = config.opacity.idle_indicator
color = fg, opacity = config.opacity.idle_indicator,
})
ass:txt(center_x, center_y + icon_size / 2, 8, t('Drop files or URLs to play here'), {
size = icon_size / 4, color = fg, opacity = config.opacity.idle_indicator
size = icon_size / 4, color = fg, opacity = config.opacity.idle_indicator,
})
end
@@ -675,7 +710,7 @@ function render()
and not (state.pause and options.pause_indicator == 'static') then
local smaller_side = math.min(display.width, display.height)
ass:icon(display.width / 2, display.height / 2, smaller_side / 4, 'graphic_eq', {
color = fg, opacity = config.opacity.audio_indicator
color = fg, opacity = config.opacity.audio_indicator,
})
end

View File

@@ -24,7 +24,8 @@ defaults = {
timeline_step = 5,
timeline_cache = true,
controls = 'menu,gap,subtitles,<has_many_audio>audio,<has_many_video>video,<has_many_edition>editions,<stream>stream-quality,gap,space,speed,space,shuffle,loop-playlist,loop-file,gap,prev,items,next,gap,fullscreen',
controls =
'menu,gap,subtitles,<has_many_audio>audio,<has_many_video>video,<has_many_edition>editions,<stream>stream-quality,gap,space,speed,space,shuffle,loop-playlist,loop-file,gap,prev,items,next,gap,fullscreen',
controls_size = 32,
controls_margin = 8,
controls_spacing = 2,
@@ -85,9 +86,11 @@ defaults = {
buffered_time_threshold = 60,
pause_indicator = 'flash',
stream_quality_options = '4320,2160,1440,1080,720,480,360,240,144',
video_types= '3g2,3gp,asf,avi,f4v,flv,h264,h265,m2ts,m4v,mkv,mov,mp4,mp4v,mpeg,mpg,ogm,ogv,rm,rmvb,ts,vob,webm,wmv,y4m',
audio_types= 'aac,ac3,aiff,ape,au,cue,dsf,dts,flac,m4a,mid,midi,mka,mp3,mp4a,oga,ogg,opus,spx,tak,tta,wav,weba,wma,wv',
image_types= 'apng,avif,bmp,gif,j2k,jp2,jfif,jpeg,jpg,jxl,mj2,png,svg,tga,tif,tiff,webp',
video_types =
'3g2,3gp,asf,avi,f4v,flv,h264,h265,m2ts,m4v,mkv,mov,mp4,mp4v,mpeg,mpg,ogm,ogv,rm,rmvb,ts,vob,webm,wmv,y4m',
audio_types =
'aac,ac3,aiff,ape,au,cue,dsf,dts,flac,m4a,mid,midi,mka,mp3,mp4a,oga,ogg,opus,spx,tak,tta,wav,weba,wma,wv',
image_types = 'apng,avif,bmp,gif,j2k,jp2,jfif,jpeg,jpg,jxl,mj2,png,svg,tga,tif,tiff,webp',
subtitle_types = 'aqt,ass,gsub,idx,jss,lrc,mks,pgs,pjs,psb,rt,sbv,slt,smi,sub,sup,srt,ssa,ssf,ttxt,txt,usf,vt,vtt',
default_directory = '~/',
show_hidden_files = false,
@@ -188,11 +191,23 @@ config = {
return ranges
end)(),
opacity = {
timeline = 0.9, position = 1, chapters = 0.8, slider = 0.9, slider_gauge = 1, speed = 0.6,
menu = 1, submenu = 0.4, border = 1, title = 1, tooltip = 1, thumbnail = 1, curtain = 0.5,
idle_indicator = 0.8, audio_indicator = 0.5
timeline = 0.9,
position = 1,
chapters = 0.8,
slider = 0.9,
slider_gauge = 1,
speed = 0.6,
menu = 1,
submenu = 0.4,
border = 1,
title = 1,
tooltip = 1,
thumbnail = 1,
curtain = 0.5,
idle_indicator = 0.8,
audio_indicator = 0.5,
},
cursor_leave_fadeout_elements = {'timeline', 'volume', 'top_bar', 'controls'}
cursor_leave_fadeout_elements = {'timeline', 'volume', 'top_bar', 'controls'},
}
-- Adds `{element}_persistency` property with table of flags when the element should be visible (`{paused = true}`)
for _, name in ipairs({'timeline', 'controls', 'volume', 'top_bar', 'speed'}) do
@@ -221,28 +236,47 @@ function create_default_menu_items()
{title = t('Stream quality'), value = 'script-binding uosc/stream-quality'},
{title = t('Playlist'), value = 'script-binding uosc/items'},
{title = t('Chapters'), value = 'script-binding uosc/chapters'},
{title = t('Navigation'), items = {
{title = t('Next'), hint = t('playlist or file'), value = 'script-binding uosc/next'},
{title = t('Prev'), hint = t('playlist or file'), value = 'script-binding uosc/prev'},
{title = t('Delete file & Next'), value = 'script-binding uosc/delete-file-next'},
{title = t('Delete file & Prev'), value = 'script-binding uosc/delete-file-prev'},
{title = t('Delete file & Quit'), value = 'script-binding uosc/delete-file-quit'},
{title = t('Open file'), value = 'script-binding uosc/open-file'},
},},
{title = t('Utils'), items = {
{title = t('Aspect ratio'), items = {
{title = t('Default'), value = 'set video-aspect-override "-1"'},
{title = '16:9', value = 'set video-aspect-override "16:9"'},
{title = '4:3', value = 'set video-aspect-override "4:3"'},
{title = '2.35:1', value = 'set video-aspect-override "2.35:1"'},
},},
{title = t('Audio devices'), value = 'script-binding uosc/audio-device'},
{title = t('Editions'), value = 'script-binding uosc/editions'},
{title = t('Screenshot'), value = 'async screenshot'},
{title = t('Inputs'), value = 'script-binding uosc/inputs'},
{title = t('Show in directory'), value = 'script-binding uosc/show-in-directory'},
{title = t('Open config folder'), value = 'script-binding uosc/open-config-directory'},
},},
{
title = t('Navigation'),
items = {
{
title = t('Next'),
hint = t('playlist or file'),
value =
'script-binding uosc/next'
},
{
title = t('Prev'),
hint = t('playlist or file'),
value =
'script-binding uosc/prev'
},
{title = t('Delete file & Next'), value = 'script-binding uosc/delete-file-next'},
{title = t('Delete file & Prev'), value = 'script-binding uosc/delete-file-prev'},
{title = t('Delete file & Quit'), value = 'script-binding uosc/delete-file-quit'},
{title = t('Open file'), value = 'script-binding uosc/open-file'},
},
},
{
title = t('Utils'),
items = {
{
title = t('Aspect ratio'),
items = {
{title = t('Default'), value = 'set video-aspect-override "-1"'},
{title = '16:9', value = 'set video-aspect-override "16:9"'},
{title = '4:3', value = 'set video-aspect-override "4:3"'},
{title = '2.35:1', value = 'set video-aspect-override "2.35:1"'},
},
},
{title = t('Audio devices'), value = 'script-binding uosc/audio-device'},
{title = t('Editions'), value = 'script-binding uosc/editions'},
{title = t('Screenshot'), value = 'async screenshot'},
{title = t('Inputs'), value = 'script-binding uosc/inputs'},
{title = t('Show in directory'), value = 'script-binding uosc/show-in-directory'},
{title = t('Open config folder'), value = 'script-binding uosc/open-config-directory'},
},
},
{title = t('Quit'), value = 'quit'},
}
end
@@ -302,10 +336,10 @@ cursor = {
local x, y, time = cursor.x - snap.x, cursor.y - snap.y, mp.get_time()
local time_diff = time - snap.time
if time_diff > 0.001 then
return { x = x / time_diff, y = y / time_diff }
return {x = x / time_diff, y = y / time_diff}
end
end
return { x = 0, y = 0 }
return {x = 0, y = 0}
end,
move = function(x, y)
local old_x, old_y = cursor.x, cursor.y
@@ -314,8 +348,11 @@ cursor = {
-- displays the top bar, so we hardcode cursor position as infinity until
-- we receive a first real mouse move event with coordinates other than 0,0.
if not cursor.first_real_mouse_move_received then
if x > 0 and y > 0 then cursor.first_real_mouse_move_received = true
else x, y = math.huge, math.huge end
if x > 0 and y > 0 then
cursor.first_real_mouse_move_received = true
else
x, y = math.huge, math.huge
end
end
-- Add 0.5 to be in the middle of the pixel
@@ -366,7 +403,7 @@ cursor = {
request_render()
end,
leave = function () cursor.move(math.huge, math.huge) end,
leave = function() cursor.move(math.huge, math.huge) end,
-- Cursor auto-hiding after period of inactivity
autohide = function()
if not cursor.on_primary_up and not Menu:is_open() then cursor.leave() end
@@ -389,7 +426,7 @@ cursor = {
if not prev then return false end
local end_x, end_y = cursor.x + (cursor.x - prev.x) * 1e10, cursor.y + (cursor.y - prev.y) * 1e10
return get_ray_to_rectangle_distance(cursor.x, cursor.y, end_x, end_y, rect)
end
end,
}
state = {
platform = (function()
@@ -457,7 +494,7 @@ state = {
margin_right = 0,
hidpi_scale = 1,
scale = 1,
radius = 0
radius = 0,
}
thumbnail = {width = 0, height = 0, disabled = false}
external = {} -- Properties set by external scripts
@@ -527,18 +564,26 @@ function update_margins()
-- margins are normalized to window size
local left, right, top, bottom = 0, 0, 0, 0
if causes_margin(controls) then bottom = (display.height - controls.ay) / display.height
elseif causes_margin(timeline) then bottom = (display.height - timeline.ay) / display.height end
if causes_margin(controls) then
bottom = (display.height - controls.ay) / display.height
elseif causes_margin(timeline) then
bottom = (display.height - timeline.ay) / display.height
end
if causes_margin(top_bar) then top = top_bar.title_by / display.height end
if causes_margin(volume) then
if options.volume == 'left' then left = volume.bx / display.width
elseif options.volume == 'right' then right = volume.ax / display.width end
if options.volume == 'left' then
left = volume.bx / display.width
elseif options.volume == 'right' then
right = volume.ax / display.width
end
end
if top == state.margin_top and bottom == state.margin_bottom and
left == state.margin_left and right == state.margin_right then return end
left == state.margin_left and right == state.margin_right then
return
end
state.margin_top = top
state.margin_bottom = bottom
@@ -548,14 +593,20 @@ function update_margins()
if utils.shared_script_property_set then
utils.shared_script_property_set('osc-margins', string.format('%f,%f,%f,%f', 0, 0, top, bottom))
end
mp.set_property_native('user-data/osc/margins', { l = left, r = right, t = top, b = bottom })
mp.set_property_native('user-data/osc/margins', {l = left, r = right, t = top, b = bottom})
if not options.adjust_osd_margins then return end
local osd_margin_y, osd_margin_x, osd_factor_x = 0, 0, display.width / display.height * 720
if config.osd_alignment_y == 'bottom' then osd_margin_y = round(bottom * 720)
elseif config.osd_alignment_y == 'top' then osd_margin_y = round(top * 720) end
if config.osd_alignment_x == 'left' then osd_margin_x = round(left * osd_factor_x)
elseif config.osd_alignment_x == 'right' then osd_margin_x = round(right * osd_factor_x) end
if config.osd_alignment_y == 'bottom' then
osd_margin_y = round(bottom * 720)
elseif config.osd_alignment_y == 'top' then
osd_margin_y = round(top * 720)
end
if config.osd_alignment_x == 'left' then
osd_margin_x = round(left * osd_factor_x)
elseif config.osd_alignment_x == 'right' then
osd_margin_x = round(right * osd_factor_x)
end
mp.set_property_native('osd-margin-y', osd_margin_y + config.osd_margin_y)
mp.set_property_native('osd-margin-x', osd_margin_x + config.osd_margin_x)
end
@@ -576,8 +627,11 @@ end
function handle_file_end()
local resume = false
if not state.loop_file then
if state.has_playlist then resume = state.shuffle and navigate_playlist(1)
else resume = options.autoload and navigate_directory(1) end
if state.has_playlist then
resume = state.shuffle and navigate_playlist(1)
else
resume = options.autoload and navigate_directory(1)
end
end
-- Resume only when navigation happened
if resume then mp.command('set pause no') end
@@ -592,7 +646,7 @@ function load_file_index_in_current_directory(index)
if serialized and serialized.dirname then
local files = read_directory(serialized.dirname, {
types = config.types.autoload,
hidden = options.show_hidden_files
hidden = options.show_hidden_files,
})
if not files then return end
@@ -645,7 +699,7 @@ if options.click_threshold > 0 then
last_down = mp.get_time()
if click_timer:is_enabled() then click_timer:kill() else click_timer:resume() end
end,
},}, 'mouse_movement', 'force')
}}, 'mouse_movement', 'force')
mp.enable_key_bindings('mouse_movement', 'allow-vo-dragging+allow-hide-cursor')
end
@@ -668,7 +722,7 @@ mp.register_event('file-loaded', function()
-- Flash top bar on requested file types
for _, type in ipairs(config.top_bar_flash_on) do
if state['is_'..type] then
if state['is_' .. type] then
Elements:flash({'top_bar'})
break
end
@@ -736,7 +790,9 @@ mp.observe_property('playback-time', 'number', create_state_setter('time', funct
if timeout > 0 then
file_end_timer.timeout = timeout
file_end_timer:resume()
else handle_file_end() end
else
handle_file_end()
end
end
end
@@ -750,9 +806,14 @@ mp.observe_property('track-list', 'native', function(name, value)
local types = {sub = 0, image = 0, audio = 0, video = 0}
for _, track in ipairs(value) do
if track.type == 'video' then
if track.image or track.albumart then types.image = types.image + 1
else types.video = types.video + 1 end
elseif types[track.type] then types[track.type] = types[track.type] + 1 end
if track.image or track.albumart then
types.image = types.image + 1
else
types.video = types.video + 1
end
elseif types[track.type] then
types[track.type] = types[track.type] + 1
end
end
set_state('is_audio', types.video == 0 and types.audio > 0)
set_state('is_image', types.image > 0 and types.video == 0 and types.audio == 0)
@@ -814,10 +875,12 @@ mp.observe_property('demuxer-cache-state', 'native', function(prop, cache_state)
if cache_state then
cached_ranges, bof, eof = cache_state['seekable-ranges'], cache_state['bof-cached'], cache_state['eof-cached']
set_state('cache_underrun', cache_state['underrun'])
else cached_ranges = {} end
else
cached_ranges = {}
end
if not (state.duration and (#cached_ranges > 0 or state.cache == 'yes' or
(state.cache == 'auto' and state.is_stream))) then
(state.cache == 'auto' and state.is_stream))) then
if state.uncached_ranges then set_state('uncached_ranges', nil) end
return
end
@@ -890,8 +953,11 @@ mp.set_key_bindings({
---@param flags nil|string
function bind_command(name, callback, flags)
mp.add_key_binding(nil, name, function(...)
if key_binding_overwrites[name] then mp.command(key_binding_overwrites[name])
else callback(...) end
if key_binding_overwrites[name] then
mp.command(key_binding_overwrites[name])
else
callback(...)
end
end, flags)
end
@@ -908,8 +974,11 @@ bind_command('decide-pause-indicator', function() Elements:maybe('pause_indicato
bind_command('menu', function() toggle_menu_with_items() end)
bind_command('menu-blurred', function() toggle_menu_with_items({mouse_nav = true}) end)
bind_command('inputs', function()
if Menu:is_open('inputs') then Menu:close()
else open_command_menu({type = 'inputs', items = get_input_items(), palette = true}) end
if Menu:is_open('inputs') then
Menu:close()
else
open_command_menu({type = 'inputs', items = get_input_items(), palette = true})
end
end)
local track_loaders = {
{name = 'subtitles', prop = 'sub', allowed_types = itable_join(config.types.video, config.types.subtitle)},
@@ -919,7 +988,10 @@ local track_loaders = {
for _, loader in ipairs(track_loaders) do
local menu_type = 'load-' .. loader.name
bind_command(menu_type, function()
if Menu:is_open(menu_type) then Menu:close() return end
if Menu:is_open(menu_type) then
Menu:close()
return
end
local path = state.path
if path then
@@ -1031,7 +1103,10 @@ bind_command('show-in-directory', function()
end
end)
bind_command('stream-quality', function()
if Menu:is_open('stream-quality') then Menu:close() return end
if Menu:is_open('stream-quality') then
Menu:close()
return
end
local ytdl_format = mp.get_property_native('ytdl-format')
local items = {}
@@ -1067,7 +1142,10 @@ bind_command('stream-quality', function()
end)
end)
bind_command('open-file', function()
if Menu:is_open('open-file') then Menu:close() return end
if Menu:is_open('open-file') then
Menu:close()
return
end
local directory
local active_file
@@ -1153,7 +1231,7 @@ bind_command('delete-file-next', function()
if is_local_file then
local paths, current_index = get_adjacent_files(state.path, {
types = config.types.autoload,
hidden = options.show_hidden_files
hidden = options.show_hidden_files,
})
if paths and current_index then
local index, path = decide_navigation_in_list(paths, current_index, 1)
@@ -1161,8 +1239,11 @@ bind_command('delete-file-next', function()
end
end
if next_file then mp.commandv('loadfile', next_file)
else mp.commandv('stop') end
if next_file then
mp.commandv('loadfile', next_file)
else
mp.commandv('stop')
end
end
if is_local_file then delete_file(state.path) end
@@ -1186,7 +1267,8 @@ bind_command('audio-device', create_self_updating_menu_opener({
local hint = string.match(device.name, ao .. '/(.+)')
if not hint then hint = device.name end
items[#items + 1] = {
title = device.description:sub(1, 7) == 'Default' and t('Default %s', device.description:sub(9)) or t(device.description),
title = device.description:sub(1, 7) == 'Default' and t('Default %s', device.description:sub(9)) or
t(device.description),
hint = hint,
active = device.name == current_device,
value = device.name,
@@ -1295,7 +1377,7 @@ Manager = {
---@type table<string, string[]> A map of clients and a list of element ids they disable
_disabled_by = {},
---@type table<string, boolean>
disabled = {}
disabled = {},
}
-- Set client and which elements it wishes disabled. To undo just pass an empty `element_ids` for the same `client`.

View File

@@ -1,5 +1,3 @@
local example_chapters = {
openings = {
yes = {
@@ -7,8 +5,8 @@ local example_chapters = {
'Opening',
},
no = {
'Opening the box'
}
'Opening the box',
},
},
intros = {
yes = {
@@ -18,7 +16,7 @@ local example_chapters = {
'Prologue',
},
no = {
}
},
},
endings = {
yes = {
@@ -28,7 +26,7 @@ local example_chapters = {
no = {
'end of the thread',
'trending',
}
},
},
outros = {
yes = {
@@ -38,28 +36,42 @@ local example_chapters = {
'PV',
},
no = {
}
}
},
},
}
local simple_ranges = {
{name = 'openings', patterns = {
{
name = 'openings',
patterns = {
'^op ', '^op$', ' op$',
'^opening$', ' opening$'
}, requires_next_chapter = true},
{name = 'intros', patterns = {
'^opening$', ' opening$',
},
requires_next_chapter = true
},
{
name = 'intros',
patterns = {
'^intro$', ' intro$',
'^avant$', '^prologue$'
}, requires_next_chapter = true},
{name = 'endings', patterns = {
'^avant$', '^prologue$',
},
requires_next_chapter = true
},
{
name = 'endings',
patterns = {
'^ed ', '^ed$', ' ed$',
'^ending ', '^ending$', ' ending$',
}},
{name = 'outros', patterns = {
}
},
{
name = 'outros',
patterns = {
'^outro$', ' outro$',
'^closing$', '^closing ',
'^preview$', '^pv$',
}},
}
},
}
local function find_any(s, patterns)