Integrated FFplay functionality across the application. This includes support for setting up the FFplay path and invoking FFplay for media playback.
241 lines
4.9 KiB
Go
241 lines
4.9 KiB
Go
//go:build linux
|
|
// +build linux
|
|
|
|
package handler
|
|
|
|
import (
|
|
"archive/tar"
|
|
"errors"
|
|
"fyne.io/fyne/v2"
|
|
"fyne.io/fyne/v2/canvas"
|
|
"fyne.io/fyne/v2/widget"
|
|
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/kernel"
|
|
"github.com/nicksnyder/go-i18n/v2/i18n"
|
|
"github.com/ulikunitz/xz"
|
|
"io"
|
|
"net/http"
|
|
"os"
|
|
"path/filepath"
|
|
)
|
|
|
|
func getPathsToFF() []kernel.FFPathUtilities {
|
|
return []kernel.FFPathUtilities{{FFmpeg: "ffmpeg/bin/ffmpeg", FFprobe: "ffmpeg/bin/ffprobe", FFplay: "ffmpeg/bin/ffplay"}, {FFmpeg: "ffmpeg", FFprobe: "ffprobe", FFplay: "ffplay"}}
|
|
}
|
|
|
|
func (h ConvertorHandler) downloadFFmpeg(progressBar *widget.ProgressBar, progressMessage *canvas.Text) (err error) {
|
|
isDirectoryFFmpeg := isDirectory("ffmpeg")
|
|
if isDirectoryFFmpeg == false {
|
|
err = os.Mkdir("ffmpeg", 0777)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
progressMessage.Text = h.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
|
|
MessageID: "downloadRun",
|
|
})
|
|
fyne.Do(func() {
|
|
progressMessage.Refresh()
|
|
})
|
|
err = downloadFile("ffmpeg/ffmpeg.tar.xz", "https://github.com/BtbN/FFmpeg-Builds/releases/download/latest/ffmpeg-master-latest-linux64-gpl.tar.xz", progressBar)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
progressMessage.Text = h.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
|
|
MessageID: "unzipRun",
|
|
})
|
|
fyne.Do(func() {
|
|
progressMessage.Refresh()
|
|
})
|
|
err = unTarXz("ffmpeg/ffmpeg.tar.xz", "ffmpeg", progressBar)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
_ = os.Remove("ffmpeg/ffmpeg.tar.xz")
|
|
|
|
progressMessage.Text = h.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
|
|
MessageID: "testFF",
|
|
})
|
|
fyne.Do(func() {
|
|
progressMessage.Refresh()
|
|
})
|
|
|
|
err = h.saveSettingFFPath(
|
|
"ffmpeg/ffmpeg-master-latest-linux64-gpl/bin/ffmpeg",
|
|
"ffmpeg/ffmpeg-master-latest-linux64-gpl/bin/ffprobe",
|
|
"ffmpeg/ffmpeg-master-latest-linux64-gpl/bin/ffplay",
|
|
)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
progressMessage.Text = h.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
|
|
MessageID: "completedQueue",
|
|
})
|
|
fyne.Do(func() {
|
|
progressMessage.Refresh()
|
|
})
|
|
|
|
return nil
|
|
}
|
|
|
|
func downloadFile(filepath string, url string, progressBar *widget.ProgressBar) (err error) {
|
|
progressBar.Value = 0
|
|
progressBar.Max = 100
|
|
|
|
req, err := http.NewRequest("GET", url, nil)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
resp, err := http.DefaultClient.Do(req)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
f, err := os.OpenFile(filepath, os.O_CREATE|os.O_WRONLY, 0644)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer f.Close()
|
|
|
|
buf := make([]byte, 32*1024)
|
|
var downloaded int64
|
|
for {
|
|
n, err := resp.Body.Read(buf)
|
|
if err != nil {
|
|
if err == io.EOF {
|
|
break
|
|
}
|
|
return err
|
|
}
|
|
if n > 0 {
|
|
f.Write(buf[:n])
|
|
downloaded += int64(n)
|
|
progressBar.Value = float64(downloaded) / float64(resp.ContentLength) * 100
|
|
fyne.Do(func() {
|
|
progressBar.Refresh()
|
|
})
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func unTarXz(fileTar string, directory string, progressBar *widget.ProgressBar) error {
|
|
progressBar.Value = 0
|
|
progressBar.Max = 100
|
|
|
|
fyne.Do(func() {
|
|
progressBar.Refresh()
|
|
})
|
|
|
|
f, err := os.Open(fileTar)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer f.Close()
|
|
|
|
xzReader, err := xz.NewReader(f)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
tarReader := tar.NewReader(xzReader)
|
|
|
|
totalFiles := 0
|
|
for {
|
|
_, err := tarReader.Next()
|
|
if err == io.EOF {
|
|
break
|
|
}
|
|
if err != nil {
|
|
return err
|
|
}
|
|
totalFiles++
|
|
}
|
|
|
|
// Rewind back to the beginning of the file to re-process
|
|
_, err = f.Seek(0, 0)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
xzReader, err = xz.NewReader(f)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
tarReader = tar.NewReader(xzReader)
|
|
|
|
// We count the number of files already unpacked
|
|
unpackedFiles := 0
|
|
|
|
for {
|
|
header, err := tarReader.Next()
|
|
if err == io.EOF {
|
|
break
|
|
}
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
targetPath := filepath.Join(directory, header.Name)
|
|
switch header.Typeflag {
|
|
case tar.TypeDir:
|
|
err := os.MkdirAll(targetPath, 0755)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
case tar.TypeReg:
|
|
outFile, err := os.Create(targetPath)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer outFile.Close()
|
|
|
|
_, err = io.Copy(outFile, tarReader)
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
default:
|
|
return errors.New("unsupported file type")
|
|
}
|
|
|
|
unpackedFiles++
|
|
progressBar.Value = float64(unpackedFiles) / float64(totalFiles) * 100
|
|
fyne.Do(func() {
|
|
progressBar.Refresh()
|
|
})
|
|
}
|
|
|
|
ffmpegPath := filepath.Join(directory, "ffmpeg-master-latest-linux64-gpl", "bin", "ffmpeg")
|
|
err = os.Chmod(ffmpegPath, 0755)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
ffprobePath := filepath.Join(directory, "ffmpeg-master-latest-linux64-gpl", "bin", "ffprobe")
|
|
err = os.Chmod(ffprobePath, 0755)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
ffplayPath := filepath.Join(directory, "ffmpeg-master-latest-linux64-gpl", "bin", "ffplay")
|
|
err = os.Chmod(ffplayPath, 0755)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func isDirectory(path string) bool {
|
|
fileInfo, err := os.Stat(path)
|
|
if err != nil {
|
|
return false
|
|
}
|
|
|
|
return fileInfo.IsDir()
|
|
}
|