diff --git a/README.md b/README.md index a48dffc..dfc33fa 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,15 @@ # mpv-osc-modern -updated 2022.7.8 +VER 1.1.0 -I have to say sorry that I misspelled the word "modern" to "morden". Now it is corrected. +changelog: +1. Gui activation area is limited to gui area. +2. Time slider show chapter name in tooltip. +3. Volume slider show volume number in tooltip. +4. Volume slider use processed volume number to make loudness transition fluent. +5. Mouse wheel up/down over volume slider to change volume. -This osc is updated to provide a mute button and a simple volume slider, yet they can be disabled through the conf file. - -This modern.lua file is coded with [Lua](https://www.lua.org/), anyone can learn to develop his demanding feature. - ---- +------ Yet another mpv osc script, based on mpv built-in osc @@ -48,7 +49,6 @@ Config file locates at "\~\~/script-opts/osc.conf". Supported options are listed minmousemove=3 -- minimum amount of pixels the mouse has to move between ticks to make the OSC show up iamaprogrammer=yes/no -- use native mpv values and disable OSC internal track list management (and some functions that depend on it) font='mpv-osd-symbols' -- default osc font - seekbarhandlesize=1.0 -- size ratio of the slider handle range 0 ~ 1 seekrange=yes/no -- show seekrange overlay seekrangealpha=128 -- transparency of seekranges seekbarkeyframes=yes/no -- use keyframes when dragging the seekbar @@ -58,6 +58,7 @@ Config file locates at "\~\~/script-opts/osc.conf". Supported options are listed visibility=auto/yes/no -- only used at init to set visibility_mode(...) windowcontrols=auto/yes/no -- whether to show window controls volumecontrol=yes/no -- whether to show mute button and volumne slider + processvolume=yes/no -- volume bar show processd volume language=eng/chs -- eng=English chs=Chinese ``` diff --git a/changelog.md b/changelog.md new file mode 100644 index 0000000..ba0287b --- /dev/null +++ b/changelog.md @@ -0,0 +1,13 @@ +# Changelog +|#|ACTION|CONTENT| +|---|---|---| +|1.|**remove**|user_opts.seekbarhandesize, since it causes side effects.| +|2.|**add**|user_opts.processvolume. the processed volume is to keep the loudness transition fluent, since the internal control gives the loudness dropping to fast when volume is high| +|3.|**add**|state.sys_volume.| +|4.|**add**|state.proc_volume.| +|5.|**add**|function set_volume(val)| +|6.|**change**|inhibit slider.seekRange when nil| +|7.|**change**|time slider show chapter name in tooltip| +|8.|**change**|volume slider show volume in tooltip| +|9.|**add**|when mouse over volume slider, wheel up/down change volume| +|10.|**add**|mp.observer_property('volume', 'number')| diff --git a/modern.lua b/modern.lua index 41db0f8..71306ba 100644 --- a/modern.lua +++ b/modern.lua @@ -29,7 +29,6 @@ local user_opts = { -- internal track list management (and some -- functions that depend on it) font = 'mpv-osd-symbols', -- default osc font - seekbarhandlesize = 1.0, -- size ratio of the slider handle, range 0 ~ 1 seekrange = true, -- show seekrange overlay seekrangealpha = 128, -- transparency of seekranges seekbarkeyframes = true, -- use keyframes when dragging the seekbar @@ -40,6 +39,7 @@ local user_opts = { visibility = 'auto', -- only used at init to set visibility_mode(...) windowcontrols = 'auto', -- whether to show window controls volumecontrol = true, -- whether to show mute button and volumne slider + processvolume = true, -- volue slider show processd volume language = 'eng', -- eng=English, chs=Chinese } @@ -135,7 +135,9 @@ local state = { maximized = false, osd = mp.create_osd_overlay('ass-events'), mute = false, - lastvisibility = user_opts.visibility, -- save last visibility on pause if showtitle + lastvisibility = user_opts.visibility, -- save last visibility on pause if showtitle + sys_volume, --system volume + proc_volume, --processed volume } local window_control_box_width = 138 @@ -324,7 +326,14 @@ function ass_draw_rr_h_ccw(ass, x0, y0, x1, y1, r1, hexagon, r2) end end - +-- set volume +function set_volume(val) + if user_opts.processvolume then + val = 10*math.sqrt(val) + end + mp.commandv('set', 'volume', val) + mp.commandv('add', 'volume', 0) --this prevent volume exceeds limit +end -- -- Tracklist Management -- @@ -485,7 +494,7 @@ function prepare_elements() --draw static slider parts local slider_lo = element.layout.slider -- calculate positions of min and max points - element.slider.min.ele_pos = user_opts.seekbarhandlesize * elem_geo.h / 2 + element.slider.min.ele_pos = elem_geo.h / 2 element.slider.max.ele_pos = elem_geo.w - element.slider.min.ele_pos element.slider.min.glob_pos = element.hitbox.x1 + element.slider.min.ele_pos element.slider.max.glob_pos = element.hitbox.x1 + element.slider.max.ele_pos @@ -584,8 +593,8 @@ function render_elements(master_ass) local s_max = element.slider.max.value -- draw pos marker local pos = element.slider.posF() - local seekRanges = element.slider.seekRangesF() - local rh = user_opts.seekbarhandlesize * elem_geo.h / 2 -- Handle radius + local seekRanges + local rh = elem_geo.h / 2 -- Handle radius local xp if pos then @@ -593,7 +602,7 @@ function render_elements(master_ass) ass_draw_cir_cw(elem_ass, xp, elem_geo.h/2, rh) elem_ass:rect_cw(0, slider_lo.gap, xp, elem_geo.h - slider_lo.gap) end - + if element.slider.seekRangesF ~= nil then seekRanges = element.slider.seekRangesF() end if seekRanges then elem_ass:draw_stop() elem_ass:merge(element.style_ass) @@ -991,8 +1000,9 @@ layouts = function () add_area('input', get_hitbox_coords(posX, posY, 1, osc_geo.w, 104)) -- area for show/hide - add_area('showhide', 0, 0, osc_param.playresx, osc_param.playresy) - + add_area('showhide', 0, osc_param.playresy-200, osc_param.playresx, osc_param.playresy) + add_area('showhide_wc', osc_param.playresx*0.67, 0, osc_param.playresx, 48) + -- fetch values local osc_w, osc_h= osc_geo.w, osc_geo.h @@ -1380,7 +1390,23 @@ function osc_init() ne.slider.tooltipF = function (pos) local duration = mp.get_property_number('duration', nil) if not ((duration == nil) or (pos == nil)) then - possec = duration * (pos / 100) + local possec = duration * (pos / 100) + local chapters = mp.get_property_native('chapter-list', {}) + if #chapters > 0 then + local ch = #chapters + local i + for i = 1, #chapters do + if chapters[i].time / duration * 100 >= pos then + ch = i - 1 + break + end + end + if ch == 0 then + return string.format('[%s] [0/%d]', mp.format_time(possec), #chapters) + elseif chapters[ch].title then + return string.format('[%s] [%d/%d][%s]', mp.format_time(possec), ch, #chapters, chapters[ch].title) + end + end return mp.format_time(possec) else return '' @@ -1462,38 +1488,52 @@ function osc_init() ne = new_element('volumebar', 'slider') ne.visible = (osc_param.playresx >= 700) and user_opts.volumecontrol ne.enabled = (get_track('audio')>0) - ne.slider.markerF = function () - return {} - end - ne.slider.seekRangesF = function() - return nil - end + ne.slider.tooltipF = + function (pos) + local refpos = state.proc_volume + if refpos > 100 then refpos = 100 end + if pos+3 >= refpos and pos-3 <= refpos then + return string.format('%d', state.proc_volume) + else + return '' + end + end + ne.slider.markerF = nil + ne.slider.seekRangesF = nil ne.slider.posF = function () - local val = mp.get_property_number('volume', nil) - return val*val/100 + return state.proc_volume end ne.eventresponder['mouse_move'] = function (element) - if not element.state.mbtnleft then return end -- allow drag for mbtnleft only! + if not element.state.mbtnleft then return end local seekto = get_slider_value(element) if (element.state.lastseek == nil) or (not (element.state.lastseek == seekto)) then - mp.commandv('set', 'volume', 10*math.sqrt(seekto)) + set_volume(seekto) element.state.lastseek = seekto end end ne.eventresponder['mbtn_left_down'] = --exact seeks on single clicks function (element) local seekto = get_slider_value(element) - mp.commandv('set', 'volume', 10*math.sqrt(seekto)) + set_volume(seekto) element.state.mbtnleft = true end ne.eventresponder['mbtn_left_up'] = - function (element) element.state.mbtnleft = false end + function (element) + element.state.mbtnleft = false + end ne.eventresponder['reset'] = function (element) element.state.lastseek = nil end - + ne.eventresponder['wheel_up_press'] = + function (element) + set_volume(state.proc_volume+5) + end + ne.eventresponder['wheel_down_press'] = + function (element) + set_volume(state.proc_volume-5) + end -- tc_left (current pos) ne = new_element('tc_left', 'button') ne.content = function () return (mp.get_property_osd('playback-time')) end @@ -1576,7 +1616,7 @@ function pause_state(name, enabled) if user_opts.showtitle then if enabled then state.lastvisibility = user_opts.visibility - visibility_mode("always", true) + visibility_mode('always', true) show_osc() else visibility_mode(state.lastvisibility, true) @@ -2005,6 +2045,16 @@ mp.observe_property('mute', 'bool', state.mute = val end ) +mp.observe_property('volume', 'number', + function(name, val) + state.sys_volume = val + if user_opts.processvolume then + state.proc_volume = val*val/100 + else + state.proc_volume = val + end + end +) mp.observe_property('border', 'bool', function(name, val) state.border = val @@ -2098,7 +2148,7 @@ function visibility_mode(mode, no_osd) elseif mode == 'never' then enable_osc(false) else - msg.warn('Ignoring unknown visibility mode \"' .. mode .. '\"') + msg.warn('Ignoring unknown visibility mode \'' .. mode .. '\'') return end