CogentRedTester / mpv-file-browser

A simple no-dependency file browser for mpv player
MIT License
244 stars 7 forks source link

Support playback of bd or dvd iso files #108

Closed IC0hO closed 1 week ago

IC0hO commented 2 weeks ago

Playing Blu-ray and DVD iso files is a bit troublesome. I need to enter some parameters to open them, such as: mpv bd:// --bluray-device="*.iso"

Then I saw this lua plugin that can browse and open iso files. Can this function be added? I hope to get a helpful reply, thank you.

CogentRedTester commented 2 weeks ago

Update to the latest version of file browser and try this addon:

local fb = require 'file-browser'

local disc = {
    name = 'disc-directory',
    priority = 20,
    version = '1.5'
}

local function is_bd_dvd(directory, list)
    local parent_dir, dirname = string.match(directory, '^(.-/)([^/]+)/?$')

    if dirname == 'BDMV' then return 'bd', parent_dir end
    if dirname == 'VIDEO_TS' then return 'dvd', parent_dir end

    for i, item in ipairs(list) do
        if item.type == 'dir' then
            if item.name == 'BDMV/' then return 'bd', directory end
            if item.name == 'VIDEO_TS/' then return 'dvd', directory end
        end
    end

    return false
end

function disc:can_parse(directory, parse_state)
    return parse_state.source == 'browser' and directory ~= ''
end

function disc:parse(directory, parse_state)
    local list, opts = self:defer(directory, parse_state)
    if not list or #list == 0 then return list, opts end

    local bd_dvd, disc_dir = is_bd_dvd(opts.directory or directory, list)
    if not bd_dvd then return list, opts end

    if not opts.sorted then
        fb.sort(list)
        opts.sorted = true
    end

    if not opts.filtered then
        fb.filter(list)
        opts.filtered = true
    end

    if bd_dvd == 'bd' then
        table.insert(list, 1, {
            type = 'file',
            name = '',
            label = '💿 BD DETECTED - PLAY BLU-RAY',
            path = 'bd://',
            mpv_options = { ['bluray-device'] = disc_dir },
        })
    else
        table.insert(list, 1, {
            type = 'file',
            name = '',
            label = '💿 DVD DETECTED - PLAY DVD',
            path = 'dvd://',
            mpv_options = { ['dvd-device'] = disc_dir },
        })
    end

    return list, opts
end

return disc

It does require the ISOs to be extracted first I believe.

IC0hO commented 2 weeks ago

This can read bd or dvd directories, but it would be nice to be able to open iso file directly. I referred to his code and simply modified the code of the open_item function in modules/playlist.lua, just to browse and open iso file, which may not be standard. I don't know how to develop a addon to do this.

--runs the loadfile or loadlist command
local function open_item(item, opts)
    -- open bluray iso or dir
    local function open_bluray(path)
        mp.set_property('bluray-device', path)
        mp.commandv('loadfile', 'bd://')
    end

    -- open dvd iso or dir
    local function open_dvd(path)
        mp.set_property('dvd-device', path)
        mp.commandv('loadfile', 'dvd://')
    end

    if fb_utils.parseable_item(item) then
        return loadlist(item, opts)
    end

    local path = fb_utils.get_full_path(item, opts.directory)
    if g.sub_extensions[ fb_utils.get_extension(item.name, "") ] then
        mp.commandv("sub-add", path, opts.flag == "replace" and "select" or "auto")
    elseif g.audio_extensions[ fb_utils.get_extension(item.name, "") ] then
        mp.commandv("audio-add", path, opts.flag == "replace" and "select" or "auto")
    elseif fb_utils.get_extension(item.name, "") == "iso" then
        local idle = mp.get_property('idle')
        if idle ~= 'yes' then mp.set_property('idle', 'yes') end
        mp.register_event("end-file", end_file)
        open_bluray(path)
        mp.add_timeout(1.0, function()
            if idle ~= 'yes' then mp.set_property('idle', idle) end
            if loaded_fail then
                loaded_fail = false
                open_dvd(path)
            end
        end)
    else
        if opts.autoload then autoload_dir(path, opts)
        else loadfile(path, opts, item.mpv_options) end
    end
end
CogentRedTester commented 2 weeks ago

Try this addon:

local mp = require 'mp'
local msg = require 'mp.msg'
local fb = require 'file-browser'

local isos = {
    name = 'iso-loader',
    priority = 20,
    version = '1.5'
}

function isos:setup()
    fb.add_default_extension('iso')
end

function isos:can_parse()
    return true
end

function isos:parse(directory, parse_state)
    local list, opts = self:defer(directory, parse_state)
    if not list or #list == 0 then return list, opts end

    for _, item in ipairs(list) do
        local path = fb.get_full_path(item, opts.directory or directory)
        if fb.get_extension(path) == 'iso' then
            item.mpv_options = { ['bluray-device'] = path, ['dvd-device'] = path }
            item.path = 'bd://'
        end
    end

    return list, opts
end

mp.add_hook('on_load_fail', 50, function()
    if mp.get_property('stream-open-filename') == 'bd://' then
        msg.info('failed to load bluray-device, attempting dvd-device')
        mp.set_property('stream-open-filename', 'dvd://')
    end
end)

return isos
CogentRedTester commented 2 weeks ago

I don't have any ISOs so I can't test if this works myself.

IC0hO commented 2 weeks ago

Thank you for your help, now I can play the iso file directly.

It would be great if this addon could record the path of the ISO file that is playing correctly, so that pressing the Home key could locate the path of the currently playing file.

Another small issue is that files marked in green as playing correctly, if I play one ISO file, now all ISO files are marked in green.

However, these issues do not affect normal use, and it is already working fine.

CogentRedTester commented 2 weeks ago

Try out this experimental branch of file-browser here: https://github.com/CogentRedTester/mpv-file-browser/pull/110

IC0hO commented 2 weeks ago

After using this branch, open the iso file and press the home key to return to the location of the iso file.

It seems that this addon for opening iso files will mark all iso files in green after opening an iso file.

IC0hO commented 2 weeks ago

The fb.register_directory_alias function in modules/apis/fb.lua may be better modified like this:

function fb.register_directory_alias(directory, alias, pattern)
    if not pattern then
        alias = '^' .. fb_utils.pattern_escape(alias) .. '[%d]*'
    end

    g.directory_aliases[alias] = directory
    msg.verbose('registering directory alias', alias, directory)

    directory_movement.set_current_file(g.current_file.original_path)

    return alias
end

Because the default open path is bd://, during playback, you can enter loadfile bd://0, loadfile bd://1, etc., in the console to switch titles. Before the modification, if you switched titles during playback, you couldn't press the home key to return to the ISO file location. After the modification, this functionality works.

CogentRedTester commented 1 week ago

The latest commit in that branch should now support bd://%d type paths. As or the highlighting issue, that's a side effect of how the API works, and I don't intend to try to fix it at this stage.

Edit: actually, I have made a change that may prevent all the ISOs from being highlighted, but I can't guarantee I won't revert it in the future.

IC0hO commented 1 week ago

Thank you, it works now.