style: reconfigured and run the whole codebase through lua formatter
This commit is contained in:
204
.editorconfig
204
.editorconfig
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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()
|
||||
|
@@ -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()
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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,
|
||||
})
|
||||
|
||||
|
@@ -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
|
||||
|
@@ -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, {
|
||||
|
@@ -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)
|
||||
|
@@ -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"
|
||||
}
|
||||
|
@@ -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"
|
||||
}
|
||||
|
@@ -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"
|
||||
}
|
||||
|
@@ -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"
|
||||
}
|
||||
|
@@ -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": "плейлист или файл"
|
||||
}
|
||||
|
@@ -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 到此处进行播放"
|
||||
}
|
||||
|
@@ -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.
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
||||
|
@@ -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`.
|
||||
|
@@ -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)
|
||||
|
Reference in New Issue
Block a user