tomasklaen / uosc

Feature-rich minimalist proximity-based UI for MPV player.
GNU Lesser General Public License v2.1
1.67k stars 66 forks source link

Cycle/Toggle Shuffle button not working #235

Closed NaiveInvestigator closed 1 year ago

NaiveInvestigator commented 1 year ago

This is an mpv issue ik but as a workaround we could instead cycle through the commands playlist-shuffle and playlist-unshuffle. But I don't know how to implement it so i looked around and found this comment.

According to that in js it would like this, but not so sure how to add this using the uosc.conf

var state = 0

var commands = [
    'playlist-shuffle',
    'playlist-unshuffle'
]

function perform_action() {
    mp.command(commands[state])
    state = (state + 1) % commands.length
}

mp.add_key_binding('i','toggle-shuffle', perform_action)
tomasklaen commented 1 year ago

Not using shuffle myself. Does mpv ignore the shuffle property? Or how is it broken?

And the playlist-(un)shuffle commands seem to be destructive. I don't want people to press the button, open the playlist to find something there, and see it all randomly ordered.

christoph-heinrich commented 1 year ago

I think command:shuffle:script-binding <your script name>/toggle-shuffle should work.

NaiveInvestigator commented 1 year ago

Not using shuffle myself. Does mpv ignore the shuffle property? Or how is it broken?

According to this comment it says we can shuffle just that it is not toggleable.

And the playlist-(un)shuffle commands seem to be destructive. I don't want people to press the button, open the playlist to find something there, and see it all randomly ordered. I think if you try out the js snippet i gave you'll get what i mean.

But all it does it is that reverts back to the original playlist before we used playlist_shuffle.

I think command:shuffle:script-binding <your script name>/toggle-shuffle should work.

I did that just now but weirdly if i add that in uosc.conf it doesn't work but if i add it directly at uosc.lua it works.

Here is my uosc.conf :

# Display style of current position. available: line, bar
timeline_style=bar
# Line display style config
timeline_line_width=2
timeline_line_width_fullscreen=3
# Scale the width of the line when minimized (timeline_size_min)
timeline_line_width_minimized_scale=10
# Timeline size when minimized, 0 will hide it completely
timeline_size_min=2
# Timeline size when fully expanded, in pixels, 0 to disable
timeline_size_max=40
# Same as ^ but when in fullscreen
timeline_size_min_fullscreen=0
timeline_size_max_fullscreen=60
# Same thing as calling toggle-progress command once on startup
timeline_start_hidden=no
# Comma separated states when timeline should always be visible. available: paused, audio, image, video
timeline_persistency=
# Timeline opacity
timeline_opacity=0.9
# Top border of background color to help visually separate timeline from video
timeline_border=1
# When scrolling above timeline, wheel will seek by this amount of seconds
timeline_step=5
# Opacity of chapter indicators in timeline, 0 to disable
timeline_chapters_opacity=0.8

# A comma delimited list of items to construct the controls bar above the timeline. Set to `never` to disable.
# Parameter spec: enclosed in `{}` means value, enclosed in `[]` means optional
# Full item syntax: `[<[!]{disposition1}[,[!]{dispositionN}]>]{element}[:{paramN}][#{badge}[>{limit}]][?{tooltip}]`
# Common properties:
#   `{icon}` - parameter used to specify an icon name (example: `face`)
#            - you can pick one here: https://fonts.google.com/icons?selected=Material+Icons
# `{element}`s and their parameters:
#   `{usoc_command}` - preconfigured shorthands for uosc commands that make sense to have as buttons:
#      - `menu`, `subtitles`, `audio`, `video`, `playlist`, `chapters`, `stream-quality`,
#        `open-file`, `items`, `next`, `prev`, `first`, `last`, `audio-device`
#   `fullscreen` - toggle fullscreen
#   `loop-playlist` - button to toggle playlist looping
#   `loop-file` - button to toggle current file looping
#   `speed[:{scale}]` - display speed slider, [{scale}] - factor of controls_size, default: 1.3
#   `command:{icon}:{command}` - button that executes a {command} when pressed
#   `toggle:{icon}:{prop}` - button that toggles mpv property
#   `cycle:{default_icon}:{prop}:{value1}[={icon1}][!]/{valueN}[={iconN}][!]`
#     - button that cycles mpv property between values, each optionally having different icon and active flag
#     - presence of `!` at the end will style the button as active
#   `gap[:{scale}]` - display an empty gap, {scale} - factor of controls_size, default: 0.3
#   `space` - fills all available space between previous and next item, useful to align items to the right
#           - multiple spaces divide the available space among themselves, which can be used for centering
# Item visibility control:
#   `<[!]{disposition1}[,[!]{dispositionN}]>` - optional prefix to control element's visibility
#   - `{disposition}` can be one of:
#     - `image` - true if current file is a single image
#     - `audio` - true for audio only files
#     - `video` - true for files with a video track
#     - `has_many_video` - true for files with more than one video track
#     - `has_audio` - true for files with an audio track
#     - `has_many_audio` - true for files with more than one audio track
#     - `has_sub` - true for files with an subtitle track
#     - `has_many_sub` - true for files with more than one subtitle track
#     - `has_chapter` - true for files with chapter list
#     - `stream` - true if current file is read from a stream
#     - `has_playlist` - true if current playlist has 2 or more items in it
#   - prefix with `!` to negate the required disposition
#   Examples:
#     - `<stream>stream-quality` - show stream quality button only for streams
#     - `<has_audio,!audio>audio` - show audio tracks button for all files that have
#                                   an audio track, but are not exclusively audio only files
# Place `#{badge}[>{limit}]` after the element params to give it a badge. Available badges:
#   `sub`, `audio`, `video` - track type counters
#   `{mpv_prop}` - any mpv prop that makes sense to you: https://mpv.io/manual/master/#property-list
#                - if prop value is an array it'll display its size
#   `>{limit}` will display the badge only if it's numerical value is above this threshold.
#   Example: `#audio>1`
# Place `?{tooltip}` after the element config to give it a tooltip.
#   Example: `<stream>stream-quality?Stream quality`
# Example implementations of some of the available shorthands:
#   menu = command:menu:script-binding uosc/menu?Menu
#   subtitles = command:subtitles:script-binding uosc/subtitles#sub?Subtitles
#   fullscreen = cycle:crop_free:fullscreen:no/yes=fullscreen_exit!?Fullscreen
#   loop-playlist = cycle:repeat:loop-playlist:no/inf!?Loop playlist
#   toggle:{icon}:{prop} = cycle:{icon}:{prop}:no/yes!
shuffle = command:shuffle:script-binding toggle-shuffle?Shuffle
#controls=menu,gap,subtitles,<has_many_audio>audio,<stream>stream-quality,gap,loop-playlist,loop-file,space,speed,space,prev,items,next,shuffle,gap:1,fullscreen
controls=subtitles,<has_many_audio>audio,<stream>stream-quality,gap,loop-playlist,loop-file,space,space,prev,items,next,shuffle
controls_size=32
controls_size_fullscreen=40
controls_margin=8
controls_spacing=2
controls_persistency=

# Where to display volume controls: none, left, right
volume=right
volume_size=40
volume_size_fullscreen=52
volume_opacity=0.9
volume_border=1
volume_step=1
volume_persistency=

# Playback speed widget: mouse drag or wheel to change, click to reset
speed_opacity=0.6
speed_step=0.1
speed_step_is_factor=no
speed_persistency=

# Controls all menus, such as context menu, subtitle loader/selector, etc
menu_item_height=36
menu_item_height_fullscreen=50
menu_min_width=260
menu_min_width_fullscreen=360
menu_wasd_navigation=no
menu_hjkl_navigation=no
menu_opacity=1
menu_parent_opacity=0.4

# Top bar with window controls and media title
# Can be: never, no-border, always
top_bar=no-border
top_bar_size=40
top_bar_size_fullscreen=46
top_bar_controls=yes
top_bar_title=yes
top_bar_persistency=

# Window border drawn in no-border mode
window_border_size=1
window_border_opacity=0.8

# Scale the interface by this factor
ui_scale=1
# Adjust the text scaling to fit your font
font_scale=1
# Border of text and icons when drawn directly on top of video
text_border=1.2
# Pause video on clicks shorter than this number of milliseconds, 0 to disable
pause_on_click_shorter_than=0
# Flash duration in milliseconds used by `flash-{element}` commands
flash_duration=1000
# Distances in pixels below which elements are fully faded in/out
proximity_in=40
proximity_out=120
# RGB HEX color codes
foreground=ffffff
foreground_text=000000
background=000000
background_text=ffffff
# Use only bold font weight throughout the whole UI
font_bold=no
# Show total time instead of time remaining
total_time=no
# Display sub second fraction in timestamps up to this precision
time_precision=0
# Hide UI when mpv autohides the cursor
autohide=no
# Can be: none, flash, static, manual (controlled by flash-pause-indicator and decide-pause-indicator commands)
pause_indicator=manual
# Screen dim when stuff like menu is open, 0 to disable
curtain_opacity=0.5
# Sizes to list in stream quality menu
stream_quality_options=4320,2160,1440,1080,720,480,360,240,144
# Load first file when calling next on a last file in a directory and vice versa
directory_navigation_loops=no
# File types to look for when navigating media files
media_types=3gp,aac,aiff,alac,ape,apng,asf,avi,avif,bmp,dsf,f4v,flac,flv,gif,h264,h265,heic,heif,jfif,jpeg,jpg,jxl,m2ts,m4a,m4v,mid,midi,mka,mkv,mov,mp3,mp4,mp4a,mp4v,mpeg,mpg,oga,ogg,ogm,ogv,opus,png,rm,rmvb,svg,tak,tta,tif,tiff,ts,vob,wav,weba,webm,webp,wma,wmv,wv
# File types to look for when loading external subtitles
subtitle_types=aqt,ass,gsub,idx,jss,lrc,mks,pgs,pjs,psb,rt,slt,smi,sub,sup,srt,ssa,ssf,ttxt,txt,usf,vt,vtt
# Used to approximate text width
# If you are using some wide font and see a lot of right side clipping in menus,
# try bumping this up.
font_height_to_letter_width_ratio=0.5
# Default open-file menu directory
default_directory=~/

# `chapter_ranges` lets you transform chapter indicators into range indicators.
#
# Chapter range definition syntax:
# ```
# start_pattern<color:opacity>end_pattern
# ```
#
# Multiple start and end patterns can be defined by separating them with `|`:
# ```
# p1|pN<color:opacity>p1|pN
# ```
#
# Multiple chapter ranges can be defined by separating them with comma:
#
# chapter_ranges=range1,rangeN
#
# One of `start_pattern`s can be a custom keyword `{bof}` that will match
# beginning of file when it makes sense.
#
# One of `end_pattern`s can be a custom keyword `{eof}` that will match end of
# file when it makes sense.
#
# Patterns are lua patterns (http://lua-users.org/wiki/PatternsTutorial).
# They only need to occur in a title, not match it completely.
# Matching is case insensitive.
#
# Chapters that end a range and got matched by an `end_pattern` other then `.*`
# will not be shown on hover, unless that chapter is also used to start another
# range.
#
# `color` is a `bbggrr` hexadecimal color code.
# `opacity` is a float number from 0 to 1.
#
# Examples:
#
# Display anime openings and endings as ranges:
# ```
# chapter_ranges=^op| op$|opening<968638:0.5>.*, ^ed| ed$|^end|ending$<968638:0.5>.*|{eof}
# ```
#
# Display skippable youtube video sponsor blocks from https://github.com/po5/mpv_sponsorblock
# ```
# chapter_ranges=sponsor start<3535a5:.5>sponsor end, segment start<3535a5:0.5>segment end
# ```
chapter_ranges=^op |^op$| op$|opening$<968638:0.5>.*, ^ed |^ed$| ed$|ending$<968638:0.5>.*|{eof}, sponsor start<3535a5:.5>sponsor end, segment start<3535a5:0.5>segment end, ^sponsors?<3535a5:.5>.*, ^intro$<968638:0.5>.*, ^outro$<968638:0.5>.*|{eof}
christoph-heinrich commented 1 year ago

You have to add it to the controls line (replacing the original shuffle).

controls=subtitles,<has_many_audio>audio,<stream>stream-quality,gap,loop-playlist,loop-file,space,space,prev,items,next,command:shuffle:script-binding toggle-shuffle?Shuffle
NaiveInvestigator commented 1 year ago

You have to add it to the controls line (replacing the original shuffle).

controls=subtitles,<has_many_audio>audio,<stream>stream-quality,gap,loop-playlist,loop-file,space,space,prev,items,next,command:shuffle:script-binding toggle-shuffle?Shuffle

TYSM!!! That worked perfectly!

hooke007 commented 1 year ago

The command shuffle actually means shuffle when you create the list, so it always work but you thought it was shuffle the current list. Just a niche and misleading command, no bug here.

tomasklaen commented 1 year ago

Huh, so shuffle will actually do nothing when called after the playlist has been added?

I guess this means we should remove the shuffle button completely, as there's no way how to implement its expected functionality with mpv. I definitely don't want it to randomize playlist order. Is mpv really incapable of selecting random next file from playlist?

hooke007 commented 1 year ago

Is mpv really incapable of selecting random next file from playlist?

https://github.com/mpv-player/mpv/issues/7294#issuecomment-569401951 Seems it was not thier interest.

tomasklaen commented 1 year ago

So if we want shuffling that everyone expects, we have to take over file end events and open next random file from playlist ourselves I guess.

NaiveInvestigator commented 1 year ago

Sorry to bother you again @christoph-heinrich but I have a question. As the new shuffle button is now a command it now doesn't highlight itself to show that if it has been pressed or not. i've been trying to figure out how to do it but couldn't progress much sadly.

Is there any way how do achieve that using the new shuffle button?

image no highlight (If not pressed) image with highlight (if pressed)

Edit: Added stuff to make it more concise.

christoph-heinrich commented 1 year ago

I don't think that's possible.

NaiveInvestigator commented 1 year ago

Aww that sucks, this issue is also pretty niche as it is lol, hopefully someday we have a proper implementation. Thank you for all the help again tho!! Really appreciate it

tomasklaen commented 1 year ago

DAMN this is annoying to implement. And it's not ideal.

It decides on the next file 300ms before the end, so it can potentially cut out punchlines from short videos such as those from r/perfectlycutscreams. But this is necessary because a lot of files actually end like ~100ms or more before their duration, but on corrupted files or files where stream ended prematurely, this can happen way before that. If file is force ended by mpv before our timer kicks in, our simulated file-end event won't fire, and uosc is unable to take over to decide to play the next one.

I couldn't figure out a better way to implement this. There's no "file-reached-end" event in mpv. There are only "im-unloading-the-file" events (file-end, on_unload, ... etc), which are useless here because they trigger even when user opens a different file during playback.

tomasklaen commented 1 year ago

I don't like this implementation as it only mostly works, and cuts out 300ms from the end of every video when uosc's automatic next file/playlist item navigation is used.

If anyone has any input here, like an idea to make this better, I'd appreciate it. If not, I'll go with it as it is.

Btw, unless something else pops up, this is the last thing to resolve for 4.0.

christoph-heinrich commented 1 year ago

Without doing any testing, I think it should be possible to e.g. use the on_load hook and then compare the previous playlist with the current one. If they are different, then the user must have e.g. dragged a file into mpv and we don't do anything, otherwise choose random playlist item etc. This probably also needs a flag because 1. choosing a playlist item might trigger the same hook again and 2. if the user manually chooses a playlist item from within uosc, then we also don't want to randomize in on_load.

Edit: on_load might actually not be a good place, because after the last playlist item mpv won't load a new file... maybe on_after_end_file? I don't know if any changes to the playlist have already happened when that gets called and I can't think of a different way of detecting opening new files from outside of uosc.

Maybe ask for shuffle implementation suggestions in the mpv IRC?

Edit2: Are you sure about the next_file_on_end thing? I think people that want to play other files from the same folder as the file they opened use autoload.lua.

hooke007 commented 1 year ago

The current shuffle would make some people feel strange that user got the endless playlist once activating it.

tomasklaen commented 1 year ago

@christoph-heinrich we can't use on_load, because it fires on any file change (user pressed next file button in the middle of the current file for example). We need an event that fires when file change is about to happen due to playback arriving at the end.

DAMN IT! I had a hunch that I've missed something, and sure enough. The end-file event receives a reason parameter, with eof being one of the values 😳. I'm so impatient when reading docs it makes me blind sometimes...

I'll refactor it when I have some time.

The current shuffle would make some people feel strange that user got the endless playlist once activating it.

That's how every shuffle everywhere works no? That's how I'd expect it to work. mpv is the first media player I've encountered where shuffle just randomizes the playlist order. And that is such a weird thing to do because people now can't browse the playlist in a comfortable alphabetical order. I guess that wasn't a consideration because there was no UI to actually browse it, but that is absolutely not acceptable in uosc.

christoph-heinrich commented 1 year ago

we can't use on_load, because it fires on any file change

That's why we would have needed a flag to differentiate manual file change from automatic ones :wink:, but end-file with the reason is definitely better and I missed it as well :disappointed:

tomasklaen commented 1 year ago

So this wasn't as nice as I hoped for. We still need to simulate the event with timers, as sometimes the end-file is called with stop reason even when file arrived at the end...

And I had to force keep-open-pause=no when user enables next_file_on_end otherwise mpv just pauses the player at the end instead of triggering any other event, and it's impossible to detect that the pause has happened because the file has ended. I can't use a time from end to determine that because 1fps videos pause 1 second before the end duration, which might be a valid user input...

But I was able to lower the cutoff time to 20ms, and it seems to be more stable with tapping to eof. Couldn't find a video it chokes on.

hooke007 commented 1 year ago

I had never tested it. Would this method and https://mpv.io/manual/master/#options-gapless-audio conflict?

tomasklaen commented 1 year ago

If there is a playlist, and uosc's shuffle is disabled, you'll get the default mpv's next file in playlist behavior. So no, it shouldn't.

NaiveInvestigator commented 1 year ago

I tried testing the new shuffle but this happens:

https://user-images.githubusercontent.com/72654596/191947061-82aee7c6-0625-430c-a59a-dd40aa13075c.mp4

Edit: Sometimes this happens with after 7 or 8 songs sometimes immediately

hooke007 commented 1 year ago

@tomasklaen Have I ignored anything else here? when it randomly jumps to the end item in the list, my player would exit when EOF.

tomasklaen commented 1 year ago

Can you elaborate? You have a playlist, you enabled uosc shuffle, and it closes the payer when it randomly selects to play the list item? Or when the last item is at the end?

And do you have keep-open=yes in your mpv.conf?

hooke007 commented 1 year ago

keep-open=yes

Got it. So it is essential now for uosc. (idle=yes works too)