Skip to content
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
259 changes: 256 additions & 3 deletions player/lua/osc.lua
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ local user_opts = {
windowcontrols_alignment = "right", -- which side to show window controls on
windowcontrols_title = "${media-title}", -- same as title but for windowcontrols
windowcontrols_independent = true, -- show window controls and bottom bar independently
floatingtitle = true, -- show title in the floating layout?
greenandgrumpy = false, -- disable santa hat
livemarkers = true, -- update seekbar chapter markers on duration change
chapter_fmt = "Chapter: %s", -- chapter print format for seekbar-hover. "no" to disable
Expand Down Expand Up @@ -1026,6 +1027,25 @@ local function render_elements(master_ass)

elem_ass:draw_stop()

-- hover position indicator (vertical bar)
if slider_lo.hover_bar and element.slider.tooltipF ~= nil
and mouse_hit(element) then

local hover_val = get_slider_value(element)
local hover_x = get_slider_ele_pos_for(element, hover_val)

elem_ass:new_event()
elem_ass:pos(element.hitbox.x1 + hover_x - 0.75,
element.hitbox.y1 + foV)
elem_ass:an(7)
elem_ass:append(element.layout.style)
ass_append_alpha(elem_ass,
{[1] = 80, [2] = 255, [3] = 255, [4] = 255}, 0)
elem_ass:draw_start()
elem_ass:rect_cw(0, 0, 1.5, elem_geo.h - 2 * foV)
elem_ass:draw_stop()
end

-- add tooltip
if element.slider.tooltipF ~= nil then
if mouse_hit(element) then
Expand Down Expand Up @@ -1205,10 +1225,22 @@ local function window_controls(topbar)
local ne = new_element("wcbar", "box")
ne.is_wc = true
lo = add_layout("wcbar")
lo.geometry = wc_geo
lo.layer = 10
lo.style = osc_styles.wcBar
lo.alpha[1] = user_opts.boxalpha
if user_opts.layout == "floating" then
local blur_extend = 4
lo.geometry = {
x = wc_geo.x - blur_extend, y = wc_geo.y, an = wc_geo.an,
w = wc_geo.w + 2 * blur_extend, h = wc_geo.h + blur_extend,
}
lo.style = "{\\rDefault\\blur1\\bord0\\1c&H" ..
osc_color_convert(user_opts.background_color) .. "\\3c&H" ..
osc_color_convert(user_opts.background_color) .. "}"
lo.alpha[1] = user_opts.boxalpha
else
lo.geometry = wc_geo
lo.style = osc_styles.wcBar
lo.alpha[1] = user_opts.boxalpha
end

local button_y = wc_geo.y - (wc_geo.h / 2)
local first_geo =
Expand Down Expand Up @@ -1842,6 +1874,227 @@ layouts["slimtopbar"] = function()
bar_layout(1, true)
end

layouts["floating"] = function ()

local show_title = user_opts.floatingtitle

local osc_geo = {
w = 690,
h = show_title and 90 or 72,
r = 14,
p = 18,
}

local padX = 10

-- Borderless with soft edges
local pill_style = "{\\rDefault\\blur1\\bord0\\1c&H" ..
osc_color_convert(user_opts.background_color) .. "\\3c&H" ..
osc_color_convert(user_opts.background_color) .. "}"

local minW = 560
if osc_param.display_aspect > 0 and osc_param.playresx < minW + 80 then
osc_param.playresy = (minW + 80) / osc_param.display_aspect
osc_param.playresx = osc_param.playresy * osc_param.display_aspect
end

osc_geo.w = math.max(minW, math.min(osc_geo.w, osc_param.playresx - 80))

-- halign/valign
local posX = math.floor(get_align(user_opts.halign, osc_param.playresx,
osc_geo.w, 0))
local posY = math.floor(get_align(user_opts.valign, osc_param.playresy,
osc_geo.h, 0))

local halfW = (osc_geo.w - 2 * osc_geo.p) / 2

osc_param.areas = {}

add_area("input", get_hitbox_coords(posX, posY, 5, osc_geo.w, osc_geo.h))

-- Show/hide deadzone
local sh_area_y0, sh_area_y1
if user_opts.valign > 0 then
sh_area_y0 = get_align(-1 + (2 * user_opts.deadzonesize),
posY - (osc_geo.h / 2), 0, 0)
sh_area_y1 = osc_param.playresy
else
sh_area_y0 = 0
sh_area_y1 = (posY + (osc_geo.h / 2)) +
get_align(1 - (2 * user_opts.deadzonesize),
osc_param.playresy - (posY + (osc_geo.h / 2)), 0, 0)
end
add_area("showhide", 0, sh_area_y0, osc_param.playresx, sh_area_y1)

local lo

--
-- Background (borderless, soft edges, transparent)
--
new_element("bgbox", "box")
lo = add_layout("bgbox")
lo.geometry = {x = posX, y = posY, an = 5, w = osc_geo.w, h = osc_geo.h}
lo.layer = 10
lo.style = pill_style
lo.alpha[1] = user_opts.boxalpha
lo.alpha[3] = 255
lo.box.radius = osc_geo.r

-- Row positions
local titleY, seekY, ctrlY
if show_title then
titleY = posY - 27 -- title row (top)
seekY = posY - 3 -- seekbar row (middle)
ctrlY = posY + 21 -- controls row (bottom)
else
seekY = posY - 15 -- seekbar row (upper half)
ctrlY = posY + 17 -- controls row (lower half)
end

local tcW = (state.tc_ms) and 170 or 110
if user_opts.tcspace >= 50 and user_opts.tcspace <= 200 then
tcW = tcW * user_opts.tcspace / 100
end

-- Title row (optional)
if show_title then
lo = add_layout("title")
lo.geometry = {x = posX - halfW, y = titleY, an = 4,
w = halfW * 2 - 160, h = 14}
lo.style = string.format("%s{\\clip(%f,%f,%f,%f)}",
osc_styles.vidtitle,
posX - halfW, titleY - 14, posX + halfW - 160, titleY + 14)
lo.button.maxchars = user_opts.boxmaxchars

lo = add_layout("cache")
lo.geometry = {x = posX + halfW, y = titleY, an = 6, w = 150, h = 14}
lo.style = osc_styles.timecodes
end

-- Seekbar row: [tc_left] [seekbar] [tc_right]
local sbPad = 2
local seekY_bar = seekY - 1

lo = add_layout("tc_left")
lo.geometry = {x = posX - halfW, y = seekY_bar, an = 4, w = tcW, h = 18}
lo.style = osc_styles.timecodes

lo = add_layout("tc_right")
lo.geometry = {x = posX + halfW, y = seekY_bar, an = 6, w = tcW, h = 18}
lo.style = osc_styles.timecodes

local sb_l = posX - halfW + tcW + sbPad
local sb_r = posX + halfW - tcW - sbPad
local sb_w = math.max(0, sb_r - sb_l)
local sb_cx = (sb_l + sb_r) / 2

-- Seekbar track background
new_element("bgbar1", "box")
lo = add_layout("bgbar1")
lo.geometry = {x = sb_cx, y = seekY_bar, an = 5, w = sb_w, h = 12}
lo.layer = 15
lo.style = osc_styles.timecodes
lo.alpha[1] =
math.min(255, user_opts.boxalpha + (255 - user_opts.boxalpha) * 0.75)
if user_opts["seekbarstyle"] ~= "bar" then
lo.box.radius = 6
lo.box.hexagon = user_opts["seekbarstyle"] == "diamond"
end

lo = add_layout("seekbar")
lo.geometry = {x = sb_cx, y = seekY_bar, an = 5, w = sb_w, h = 12}
lo.style = osc_styles.timecodes
lo.slider.tooltip_style = osc_styles.vidtitle
lo.slider.tooltip_an = 2
lo.slider.adjust_tooltip = false
lo.slider.hover_bar = true
lo.slider.stype = user_opts["seekbarstyle"]
lo.slider.rtype = user_opts["seekrangestyle"]
lo.slider.gap = 1
lo.slider.border = 0

-- Control row - center: playback controls
local btnDist = 44

lo = add_layout("play_pause")
lo.geometry = {x = posX, y = ctrlY, an = 5, w = 36, h = 36}
lo.style = osc_styles.smallButtonsBar

lo = add_layout("skip_backward")
lo.geometry = {x = posX - btnDist, y = ctrlY, an = 5, w = 28, h = 28}
lo.style = osc_styles.smallButtonsBar

lo = add_layout("skip_forward")
lo.geometry = {x = posX + btnDist, y = ctrlY, an = 5, w = 28, h = 28}
lo.style = osc_styles.smallButtonsBar

lo = add_layout("chapter_prev")
lo.geometry = {x = posX - btnDist * 2, y = ctrlY, an = 5, w = 28, h = 28}
lo.style = osc_styles.smallButtonsBar

lo = add_layout("chapter_next")
lo.geometry = {x = posX + btnDist * 2, y = ctrlY, an = 5, w = 28, h = 28}
lo.style = osc_styles.smallButtonsBar

-- Control row - left side (built left to right)
local ll = posX - halfW

lo = add_layout("menu")
lo.geometry = {x = ll, y = ctrlY, an = 4, w = 20, h = 20}
lo.style = osc_styles.topButtonsBar
ll = ll + 20 + padX

lo = add_layout("playlist_prev")
lo.geometry = {x = ll, y = ctrlY, an = 4, w = 16, h = 16}
lo.style = osc_styles.topButtonsBar
ll = ll + 16 + padX

lo = add_layout("playlist_next")
lo.geometry = {x = ll, y = ctrlY, an = 4, w = 16, h = 16}
lo.style = osc_styles.topButtonsBar
ll = ll + 16 + padX

-- Custom buttons
for i = 1, last_custom_button do
lo = add_layout("custom_button_" .. i)
lo.geometry = {x = ll, y = ctrlY, an = 4, w = 18, h = 18}
lo.style = osc_styles.vidtitleBar
ll = ll + 18 + padX
end

-- Control row - right side (built right to left, uniform padX spacing)
local rr = posX + halfW
local iconW = 27
local tsW = 50

lo = add_layout("fullscreen")
lo.geometry = {x = rr, y = ctrlY, an = 5, w = iconW / 2, h = iconW}
lo.style = osc_styles.smallButtonsBar
rr = rr - iconW - padX

lo = add_layout("volume")
lo.geometry = {x = rr, y = ctrlY, an = 5, w = iconW, h = iconW}
lo.style = osc_styles.smallButtonsBar
rr = rr - tsW - padX

lo = add_layout("sub_track")
lo.geometry = {x = rr, y = ctrlY, an = 5, w = tsW, h = 18}
lo.style = osc_styles.smallButtonsL
rr = rr - tsW - padX

lo = add_layout("audio_track")
lo.geometry = {x = rr, y = ctrlY, an = 5, w = tsW, h = 18}
lo.style = osc_styles.smallButtonsL

-- Cache: in title row if title shown, otherwise in control row
if not show_title then
lo = add_layout("cache")
lo.geometry = {x = ll, y = ctrlY, an = 4, w = 110, h = 18}
lo.style = osc_styles.timecodes
end

end


local function bind_mouse_buttons(element_name)
for _, button in pairs({"mbtn_left", "mbtn_mid", "mbtn_right"}) do
Expand Down
Loading