在Fyne.io中集成mpv进行媒体播放

引言

在我的一个项目中,,我需要在Fyne编写的GUI中播放视频。然而Fyne这个框架原生并不支持视频播放,所以我引入了MPV作为视频解码与播放的库。

为了将MPV的输出集成到Fyne的GUI中,我可以通过设置MPV的wid选项来控制。在Windows上,这个WID就是Windows
handle id (HWND)。 在Linux中,这个ID通常为X11的window id。

然而,Fyne同样不支持直接获取window id。为了实现这个功能,我们需要对Fyne进行一些修改,具体修改如下。

修改Fyne源码

首先,在window_windows.go文件中,添加以下代码:

func (w *window) Wid() uintptr {
    w.viewLock.RLock()
    defer w.viewLock.RUnlock()

    if w.closing {
        return 0
    }
    if (w.viewport == nil) {
        return uintptr(0)
    }
    return uintptr(w.viewport.GetWin32Window())
}

接下来,在window_linux.go文件中,添加以下代码:

func (w *window) Wid() uintptr {
    w.viewLock.RLock()
    defer w.viewLock.RUnlock()

    if w.closing {
        return 0
    }
    if (w.viewport == nil) {
        return uintptr(0)
    }
    return uintptr(w.viewport.GetX11Window())
}

测试代码

以下是使用修改后的Fyne源码并结合MPV库的测试代码:

package main

import (
    "fmt"
    "fyne.io/fyne/v2"
    "fyne.io/fyne/v2/app"
    "fyne.io/fyne/v2/theme"
    "github.com/aynakeya/go-mpv"
)

type WindowHandleMagic interface {
    Wid() uintptr
}

// need to apply patch first
func GetWindowHandle(window fyne.Window) uintptr {
    x, ok := window.(WindowHandleMagic)
    if ok {
        return x.Wid()
    }
    return 0
}

func main() {
    a := app.NewWithID("io.fyne.mpvdemo")
    a.SetIcon(theme.FyneLogo())
    window := a.NewWindow("Fyne MPV Player Demo")
    var libmpv *mpv.Mpv = nil
    window.Resize(fyne.NewSize(1080, 720))
    go func() {
        wid := GetWindowHandle(window)
        for wid == 0 {
            wid = GetWindowHandle(window)
        }
        fmt.Printf("got windows handle %d\n", wid)
        libmpv = mpv.Create()
        err := libmpv.Initialize()
        if err != nil {
            panic(err)
        }
        fmt.Println(libmpv.SetOptionString("wid", fmt.Sprintf("%d", wid)))
        fmt.Println(libmpv.Command([]string{"loadfile", "/home/aynakeya/Videos/ymca.mp4"}))
    }()
    window.ShowAndRun()
    if libmpv != nil {
        libmpv.Destroy()
    }
}

效果图

img

Reference

https://github.com/fyne-io/fyne/issues/449#issuecomment-1546820151
AynaLivePlayer