Add FFplay support to the application

Integrated FFplay functionality across the application. This includes support for setting up the FFplay path and invoking FFplay for media playback.
This commit is contained in:
Leonid Nikitin 2025-05-19 22:49:09 +05:00
parent a831d56d93
commit 306383449a
Signed by: kor-elf
GPG Key ID: DAB5355A11C22541
17 changed files with 244 additions and 24 deletions

View File

@ -9,6 +9,8 @@ type RepositoryContract interface {
SavePathFfmpeg(code string) (setting.Setting, error) SavePathFfmpeg(code string) (setting.Setting, error)
GetPathFfprobe() (string, error) GetPathFfprobe() (string, error)
SavePathFfprobe(code string) (setting.Setting, error) SavePathFfprobe(code string) (setting.Setting, error)
GetPathFfplay() (string, error)
SavePathFfplay(code string) (setting.Setting, error)
} }
type Repository struct { type Repository struct {
@ -34,3 +36,11 @@ func (r Repository) GetPathFfprobe() (string, error) {
func (r Repository) SavePathFfprobe(path string) (setting.Setting, error) { func (r Repository) SavePathFfprobe(path string) (setting.Setting, error) {
return r.settingRepository.CreateOrUpdate("ffprobe", path) return r.settingRepository.CreateOrUpdate("ffprobe", path)
} }
func (r Repository) GetPathFfplay() (string, error) {
return r.settingRepository.GetValue("ffplay")
}
func (r Repository) SavePathFfplay(path string) (setting.Setting, error) {
return r.settingRepository.CreateOrUpdate("ffplay", path)
}

View File

@ -18,7 +18,8 @@ type ViewContract interface {
SelectFFPath( SelectFFPath(
ffmpegPath string, ffmpegPath string,
ffprobePath string, ffprobePath string,
save func(ffmpegPath string, ffprobePath string) error, ffplayPath string,
save func(ffmpegPath string, ffprobePath string, ffplayPath string) error,
cancel func(), cancel func(),
donwloadFFmpeg func(progressBar *widget.ProgressBar, progressMessage *canvas.Text) error, donwloadFFmpeg func(progressBar *widget.ProgressBar, progressMessage *canvas.Text) error,
) )

View File

@ -15,7 +15,8 @@ import (
func (v View) SelectFFPath( func (v View) SelectFFPath(
currentPathFfmpeg string, currentPathFfmpeg string,
currentPathFfprobe string, currentPathFfprobe string,
save func(ffmpegPath string, ffprobePath string) error, currentPathFfplay string,
save func(ffmpegPath string, ffprobePath string, ffplayPath string) error,
cancel func(), cancel func(),
donwloadFFmpeg func(progressBar *widget.ProgressBar, progressMessage *canvas.Text) error, donwloadFFmpeg func(progressBar *widget.ProgressBar, progressMessage *canvas.Text) error,
) { ) {
@ -25,6 +26,7 @@ func (v View) SelectFFPath(
ffmpegPath, buttonFFmpeg, buttonFFmpegMessage := v.getButtonSelectFile(currentPathFfmpeg) ffmpegPath, buttonFFmpeg, buttonFFmpegMessage := v.getButtonSelectFile(currentPathFfmpeg)
ffprobePath, buttonFFprobe, buttonFFprobeMessage := v.getButtonSelectFile(currentPathFfprobe) ffprobePath, buttonFFprobe, buttonFFprobeMessage := v.getButtonSelectFile(currentPathFfprobe)
ffplayPath, buttonFFplay, buttonFFplayMessage := v.getButtonSelectFile(currentPathFfplay)
link := widget.NewHyperlink("https://ffmpeg.org/download.html", &url.URL{ link := widget.NewHyperlink("https://ffmpeg.org/download.html", &url.URL{
Scheme: "https", Scheme: "https",
@ -58,6 +60,15 @@ func (v View) SelectFFPath(
{ {
Widget: container.NewHScroll(buttonFFprobeMessage), Widget: container.NewHScroll(buttonFFprobeMessage),
}, },
{
Text: v.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "pathToFfplay",
}),
Widget: buttonFFplay,
},
{
Widget: container.NewHScroll(buttonFFplayMessage),
},
{ {
Widget: errorMessage, Widget: errorMessage,
}, },
@ -66,7 +77,7 @@ func (v View) SelectFFPath(
MessageID: "save", MessageID: "save",
}), }),
OnSubmit: func() { OnSubmit: func() {
err := save(*ffmpegPath, *ffprobePath) err := save(*ffmpegPath, *ffprobePath, *ffplayPath)
if err != nil { if err != nil {
errorMessage.Text = err.Error() errorMessage.Text = err.Error()
} }

View File

@ -16,6 +16,7 @@ type ConvertorHandlerContract interface {
FfPathSelection() FfPathSelection()
GetFfmpegVersion() (string, error) GetFfmpegVersion() (string, error)
GetFfprobeVersion() (string, error) GetFfprobeVersion() (string, error)
GetFfplayVersion() (string, error)
} }
type ConvertorHandler struct { type ConvertorHandler struct {
@ -53,13 +54,14 @@ func (h ConvertorHandler) MainConvertor() {
h.convertorView.Main(conversion) h.convertorView.Main(conversion)
return return
} }
h.convertorView.SelectFFPath("", "", h.saveSettingFFPath, nil, h.downloadFFmpeg) h.convertorView.SelectFFPath("", "", "", h.saveSettingFFPath, nil, h.downloadFFmpeg)
} }
func (h ConvertorHandler) FfPathSelection() { func (h ConvertorHandler) FfPathSelection() {
ffmpeg, _ := h.convertorRepository.GetPathFfmpeg() ffmpeg, _ := h.convertorRepository.GetPathFfmpeg()
ffprobe, _ := h.convertorRepository.GetPathFfprobe() ffprobe, _ := h.convertorRepository.GetPathFfprobe()
h.convertorView.SelectFFPath(ffmpeg, ffprobe, h.saveSettingFFPath, h.MainConvertor, h.downloadFFmpeg) ffplay, _ := h.convertorRepository.GetPathFfplay()
h.convertorView.SelectFFPath(ffmpeg, ffprobe, ffplay, h.saveSettingFFPath, h.MainConvertor, h.downloadFFmpeg)
} }
func (h ConvertorHandler) GetFfmpegVersion() (string, error) { func (h ConvertorHandler) GetFfmpegVersion() (string, error) {
@ -70,6 +72,10 @@ func (h ConvertorHandler) GetFfprobeVersion() (string, error) {
return h.app.GetConvertorService().GetFFprobeVersion() return h.app.GetConvertorService().GetFFprobeVersion()
} }
func (h ConvertorHandler) GetFfplayVersion() (string, error) {
return h.app.GetConvertorService().GetFFplayVersion()
}
func (h ConvertorHandler) runConvert(setting view.HandleConvertSetting) { func (h ConvertorHandler) runConvert(setting view.HandleConvertSetting) {
h.app.GetQueue().Add(&kernel.ConvertSetting{ h.app.GetQueue().Add(&kernel.ConvertSetting{
VideoFileInput: setting.FileInput, VideoFileInput: setting.FileInput,
@ -98,15 +104,21 @@ func (h ConvertorHandler) checkingFFPathUtilities() bool {
if ffprobeChecking == false { if ffprobeChecking == false {
continue continue
} }
ffplayChecking, _ := h.app.GetConvertorService().ChangeFFplayPath(item.FFplay)
if ffplayChecking == false {
continue
}
_, _ = h.convertorRepository.SavePathFfmpeg(item.FFmpeg) _, _ = h.convertorRepository.SavePathFfmpeg(item.FFmpeg)
_, _ = h.convertorRepository.SavePathFfprobe(item.FFprobe) _, _ = h.convertorRepository.SavePathFfprobe(item.FFprobe)
_, _ = h.convertorRepository.SavePathFfplay(item.FFplay)
return true return true
} }
return false return false
} }
func (h ConvertorHandler) saveSettingFFPath(ffmpegPath string, ffprobePath string) error { func (h ConvertorHandler) saveSettingFFPath(ffmpegPath string, ffprobePath string, ffplayPath string) error {
ffmpegChecking, _ := h.app.GetConvertorService().ChangeFFmpegPath(ffmpegPath) ffmpegChecking, _ := h.app.GetConvertorService().ChangeFFmpegPath(ffmpegPath)
if ffmpegChecking == false { if ffmpegChecking == false {
errorText := h.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{ errorText := h.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
@ -123,8 +135,17 @@ func (h ConvertorHandler) saveSettingFFPath(ffmpegPath string, ffprobePath strin
return errors.New(errorText) return errors.New(errorText)
} }
ffplayChecking, _ := h.app.GetConvertorService().ChangeFFplayPath(ffplayPath)
if ffplayChecking == false {
errorText := h.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "errorFFplay",
})
return errors.New(errorText)
}
_, _ = h.convertorRepository.SavePathFfmpeg(ffmpegPath) _, _ = h.convertorRepository.SavePathFfmpeg(ffmpegPath)
_, _ = h.convertorRepository.SavePathFfprobe(ffprobePath) _, _ = h.convertorRepository.SavePathFfprobe(ffprobePath)
_, _ = h.convertorRepository.SavePathFfplay(ffplayPath)
h.MainConvertor() h.MainConvertor()
@ -142,5 +163,10 @@ func (h ConvertorHandler) checkingFFPath() bool {
return false return false
} }
_, err = h.app.GetConvertorService().GetFFplayVersion()
if err != nil {
return false
}
return true return true
} }

View File

@ -10,7 +10,7 @@ import (
) )
func getPathsToFF() []kernel.FFPathUtilities { func getPathsToFF() []kernel.FFPathUtilities {
return []kernel.FFPathUtilities{{"ffmpeg/bin/ffmpeg", "ffmpeg/bin/ffprobe"}, {"ffmpeg", "ffprobe"}} 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) { func (h ConvertorHandler) downloadFFmpeg(progressBar *widget.ProgressBar, progressMessage *canvas.Text) (err error) {

View File

@ -19,7 +19,7 @@ import (
) )
func getPathsToFF() []kernel.FFPathUtilities { func getPathsToFF() []kernel.FFPathUtilities {
return []kernel.FFPathUtilities{{"ffmpeg/bin/ffmpeg", "ffmpeg/bin/ffprobe"}, {"ffmpeg", "ffprobe"}} 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) { func (h ConvertorHandler) downloadFFmpeg(progressBar *widget.ProgressBar, progressMessage *canvas.Text) (err error) {
@ -60,7 +60,11 @@ func (h ConvertorHandler) downloadFFmpeg(progressBar *widget.ProgressBar, progre
progressMessage.Refresh() progressMessage.Refresh()
}) })
err = h.saveSettingFFPath("ffmpeg/ffmpeg-master-latest-linux64-gpl/bin/ffmpeg", "ffmpeg/ffmpeg-master-latest-linux64-gpl/bin/ffprobe") 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 { if err != nil {
return err return err
} }
@ -217,6 +221,12 @@ func unTarXz(fileTar string, directory string, progressBar *widget.ProgressBar)
return err 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 return nil
} }

View File

@ -19,7 +19,7 @@ import (
) )
func getPathsToFF() []kernel.FFPathUtilities { func getPathsToFF() []kernel.FFPathUtilities {
return []kernel.FFPathUtilities{{"ffmpeg\\bin\\ffmpeg.exe", "ffmpeg\\bin\\ffprobe.exe"}} return []kernel.FFPathUtilities{{FFmpeg: "ffmpeg\\bin\\ffmpeg.exe", FFprobe: "ffmpeg\\bin\\ffprobe.exe", FFplay: "ffmpeg\\bin\\ffplay.exe"}}
} }
func (h ConvertorHandler) downloadFFmpeg(progressBar *widget.ProgressBar, progressMessage *canvas.Text) (err error) { func (h ConvertorHandler) downloadFFmpeg(progressBar *widget.ProgressBar, progressMessage *canvas.Text) (err error) {
@ -59,7 +59,11 @@ func (h ConvertorHandler) downloadFFmpeg(progressBar *widget.ProgressBar, progre
fyne.Do(func() { fyne.Do(func() {
progressMessage.Refresh() progressMessage.Refresh()
}) })
err = h.saveSettingFFPath("ffmpeg/ffmpeg-master-latest-win64-gpl/bin/ffmpeg.exe", "ffmpeg/ffmpeg-master-latest-win64-gpl/bin/ffprobe.exe") err = h.saveSettingFFPath(
"ffmpeg/ffmpeg-master-latest-win64-gpl/bin/ffmpeg.exe",
"ffmpeg/ffmpeg-master-latest-win64-gpl/bin/ffprobe.exe",
"ffmpeg/ffmpeg-master-latest-win64-gpl/bin/ffplay.exe",
)
if err != nil { if err != nil {
return err return err
} }

View File

@ -117,8 +117,14 @@ func (h MenuHandler) openAbout() {
MessageID: "errorFFprobeVersion", MessageID: "errorFFprobeVersion",
}) })
} }
ffplay, err := h.convertorHandler.GetFfplayVersion()
if err != nil {
ffplay = h.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "errorFFplayVersion",
})
}
h.menuView.About(ffmpeg, ffprobe) h.menuView.About(ffmpeg, ffprobe, ffplay)
} }
func (h MenuHandler) openGratitude() { func (h MenuHandler) openGratitude() {

View File

@ -32,8 +32,10 @@ type ConvertorContract interface {
GetTotalDuration(file *File) (float64, error) GetTotalDuration(file *File) (float64, error)
GetFFmpegVesrion() (string, error) GetFFmpegVesrion() (string, error)
GetFFprobeVersion() (string, error) GetFFprobeVersion() (string, error)
GetFFplayVersion() (string, error)
ChangeFFmpegPath(path string) (bool, error) ChangeFFmpegPath(path string) (bool, error)
ChangeFFprobePath(path string) (bool, error) ChangeFFprobePath(path string) (bool, error)
ChangeFFplayPath(path string) (bool, error)
GetRunningProcesses() map[int]*exec.Cmd GetRunningProcesses() map[int]*exec.Cmd
GetSupportFormats() (encoder.ConvertorFormatsContract, error) GetSupportFormats() (encoder.ConvertorFormatsContract, error)
} }
@ -46,6 +48,7 @@ type ProgressContract interface {
type FFPathUtilities struct { type FFPathUtilities struct {
FFmpeg string FFmpeg string
FFprobe string FFprobe string
FFplay string
} }
type runningProcesses struct { type runningProcesses struct {
@ -177,6 +180,17 @@ func (s Convertor) GetFFprobeVersion() (string, error) {
return text[0], nil return text[0], nil
} }
func (s Convertor) GetFFplayVersion() (string, error) {
cmd := exec.Command(s.ffPathUtilities.FFplay, "-version")
helper.PrepareBackgroundCommand(cmd)
out, err := cmd.CombinedOutput()
if err != nil {
return "", err
}
text := regexp.MustCompile("\r?\n").Split(strings.TrimSpace(string(out)), -1)
return text[0], nil
}
func (s Convertor) ChangeFFmpegPath(path string) (bool, error) { func (s Convertor) ChangeFFmpegPath(path string) (bool, error) {
cmd := exec.Command(path, "-version") cmd := exec.Command(path, "-version")
helper.PrepareBackgroundCommand(cmd) helper.PrepareBackgroundCommand(cmd)
@ -205,6 +219,20 @@ func (s Convertor) ChangeFFprobePath(path string) (bool, error) {
return true, nil return true, nil
} }
func (s Convertor) ChangeFFplayPath(path string) (bool, error) {
cmd := exec.Command(path, "-version")
helper.PrepareBackgroundCommand(cmd)
out, err := cmd.CombinedOutput()
if err != nil {
return false, err
}
if strings.Contains(strings.TrimSpace(string(out)), "ffplay") == false {
return false, nil
}
s.ffPathUtilities.FFplay = path
return true, nil
}
func (s Convertor) GetSupportFormats() (encoder.ConvertorFormatsContract, error) { func (s Convertor) GetSupportFormats() (encoder.ConvertorFormatsContract, error) {
formats := encoder.NewConvertorFormats() formats := encoder.NewConvertorFormats()
cmd := exec.Command(s.ffPathUtilities.FFmpeg, "-encoders") cmd := exec.Command(s.ffPathUtilities.FFmpeg, "-encoders")

30
kernel/ffplay.go Normal file
View File

@ -0,0 +1,30 @@
package kernel
import (
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/helper"
"os/exec"
)
type FFplay struct {
ffPathUtilities *FFPathUtilities
}
type FFplaySetting struct {
PathToFile string
}
type FFplayContract interface {
Run(setting FFplaySetting) error
}
func NewFFplay(ffPathUtilities *FFPathUtilities) *FFplay {
return &FFplay{ffPathUtilities: ffPathUtilities}
}
func (ffplay FFplay) Run(setting FFplaySetting) error {
args := []string{setting.PathToFile}
cmd := exec.Command(ffplay.ffPathUtilities.FFplay, args...)
helper.PrepareBackgroundCommand(cmd)
return cmd.Start()
}

View File

@ -66,6 +66,7 @@ type QueueLayoutObject struct {
items map[int]QueueLayoutItem items map[int]QueueLayoutItem
localizerService LocalizerContract localizerService LocalizerContract
queueStatisticsFormat *queueStatisticsFormat queueStatisticsFormat *queueStatisticsFormat
ffplayService FFplayContract
} }
type QueueLayoutItem struct { type QueueLayoutItem struct {
@ -73,11 +74,12 @@ type QueueLayoutItem struct {
ProgressBar *widget.ProgressBar ProgressBar *widget.ProgressBar
StatusMessage *canvas.Text StatusMessage *canvas.Text
MessageError *canvas.Text MessageError *canvas.Text
buttonPlay *widget.Button
status *StatusContract status *StatusContract
} }
func NewQueueLayoutObject(queue QueueListContract, localizerService LocalizerContract) *QueueLayoutObject { func NewQueueLayoutObject(queue QueueListContract, localizerService LocalizerContract, ffplayService FFplayContract) *QueueLayoutObject {
title := widget.NewLabel(localizerService.GetMessage(&i18n.LocalizeConfig{MessageID: "queue"})) title := widget.NewLabel(localizerService.GetMessage(&i18n.LocalizeConfig{MessageID: "queue"}))
title.TextStyle.Bold = true title.TextStyle.Bold = true
@ -98,6 +100,7 @@ func NewQueueLayoutObject(queue QueueListContract, localizerService LocalizerCon
items: items, items: items,
localizerService: localizerService, localizerService: localizerService,
queueStatisticsFormat: queueStatisticsFormat, queueStatisticsFormat: queueStatisticsFormat,
ffplayService: ffplayService,
} }
queue.AddListener(queueLayoutObject) queue.AddListener(queueLayoutObject)
@ -121,11 +124,18 @@ func (o QueueLayoutObject) Add(id int, queue *Queue) {
statusMessage := canvas.NewText(o.getStatusTitle(queue.Status), theme.Color(theme.ColorNamePrimary)) statusMessage := canvas.NewText(o.getStatusTitle(queue.Status), theme.Color(theme.ColorNamePrimary))
messageError := canvas.NewText("", theme.Color(theme.ColorNameError)) messageError := canvas.NewText("", theme.Color(theme.ColorNameError))
buttonPlay := widget.NewButtonWithIcon("", theme.Icon(theme.IconNameMediaPlay), func() {
})
buttonPlay.Hide()
content := container.NewVBox( content := container.NewVBox(
container.NewHScroll(widget.NewLabel(queue.Setting.VideoFileInput.Name)), container.NewHScroll(widget.NewLabel(queue.Setting.VideoFileInput.Name)),
progressBar, progressBar,
container.NewHScroll(statusMessage), container.NewHScroll(container.NewHBox(
buttonPlay,
statusMessage,
)),
container.NewHScroll(messageError), container.NewHScroll(messageError),
canvas.NewLine(theme.Color(theme.ColorNameFocus)), canvas.NewLine(theme.Color(theme.ColorNameFocus)),
container.NewPadded(), container.NewPadded(),
@ -141,6 +151,7 @@ func (o QueueLayoutObject) Add(id int, queue *Queue) {
ProgressBar: progressBar, ProgressBar: progressBar,
StatusMessage: statusMessage, StatusMessage: statusMessage,
MessageError: messageError, MessageError: messageError,
buttonPlay: buttonPlay,
status: &queue.Status, status: &queue.Status,
} }
o.container.Add(content) o.container.Add(content)
@ -169,6 +180,20 @@ func (o QueueLayoutObject) ChangeQueueStatus(queueId int, queue *Queue) {
item.MessageError.Refresh() item.MessageError.Refresh()
}) })
} }
if queue.Status == StatusType(Completed) {
item.buttonPlay.Show()
item.buttonPlay.OnTapped = func() {
item.buttonPlay.Disable()
go func() {
_ = o.ffplayService.Run(FFplaySetting{
PathToFile: queue.Setting.VideoFileOut.Path,
})
fyne.Do(func() {
item.buttonPlay.Enable()
})
}()
}
}
if o.queueStatisticsFormat.isChecked(queue.Status) == false && item.CanvasObject.Visible() == true { if o.queueStatisticsFormat.isChecked(queue.Status) == false && item.CanvasObject.Visible() == true {
item.CanvasObject.Hide() item.CanvasObject.Hide()
} else if item.CanvasObject.Visible() == false { } else if item.CanvasObject.Visible() == false {

View File

@ -83,5 +83,7 @@ func (w Window) GetLayout() LayoutContract {
} }
func (w Window) SetOnDropped(callback func(position fyne.Position, uris []fyne.URI)) { func (w Window) SetOnDropped(callback func(position fyne.Position, uris []fyne.URI)) {
w.windowFyne.SetOnDropped(callback) fyne.Do(func() {
w.windowFyne.SetOnDropped(callback)
})
} }

View File

@ -23,8 +23,8 @@ hash = "sha1-0ec753be8df955a117404fb634b01b45eb386e2a"
other = "Cancel" other = "Cancel"
[changeFFPath] [changeFFPath]
hash = "sha1-46793a2844600d0eb19fa3540fb9564ee5705491" hash = "sha1-1f704de0560f8135eb6924cd232ed919ca2e5af0"
other = "FFmpeg and FFprobe" other = "FFmpeg, FFprobe and FFplay"
[changeLanguage] [changeLanguage]
hash = "sha1-8b276eaf378d485c769fb3d5dcc06dfc25b0c01b" hash = "sha1-8b276eaf378d485c769fb3d5dcc06dfc25b0c01b"
@ -238,6 +238,14 @@ other = "this is not FFmpeg"
hash = "sha1-9a4148d42186b6b32cf83bef726e23022c53283f" hash = "sha1-9a4148d42186b6b32cf83bef726e23022c53283f"
other = "Could not determine FFmpeg version" other = "Could not determine FFmpeg version"
[errorFFplay]
hash = "sha1-988122112ac6002094e25518cfb5f0d606217298"
other = "this is not FFplay"
[errorFFplayVersion]
hash = "sha1-cd60928d20d93210e103dd464306ab138bf1b184"
other = "Could not determine FFplay version"
[errorFFprobe] [errorFFprobe]
hash = "sha1-86d1b0b4c4ccd6a4f71e758fc67ce11aff4ba9b8" hash = "sha1-86d1b0b4c4ccd6a4f71e758fc67ce11aff4ba9b8"
other = "this is not FFprobe" other = "this is not FFprobe"
@ -330,6 +338,10 @@ other = "Enable option"
hash = "sha1-fafc50f1db0f720fe83a96cd70a9e1ad824e96b6" hash = "sha1-fafc50f1db0f720fe83a96cd70a9e1ad824e96b6"
other = "Path to FFmpeg:" other = "Path to FFmpeg:"
[pathToFfplay]
hash = "sha1-5389830dd75a63aa8a5e41e8f07c5fadd8385398"
other = "Path to FFplay:"
[pathToFfprobe] [pathToFfprobe]
hash = "sha1-b872edc9633a2e81ef678dc46fe46a7e91732024" hash = "sha1-b872edc9633a2e81ef678dc46fe46a7e91732024"
other = "Path to FFprobe:" other = "Path to FFprobe:"

View File

@ -23,8 +23,8 @@ hash = "sha1-0ec753be8df955a117404fb634b01b45eb386e2a"
other = "Болдырмау" other = "Болдырмау"
[changeFFPath] [changeFFPath]
hash = "sha1-46793a2844600d0eb19fa3540fb9564ee5705491" hash = "sha1-1f704de0560f8135eb6924cd232ed919ca2e5af0"
other = "FFmpeg және FFprobe" other = "FFmpeg, FFprobe және FFplay"
[changeLanguage] [changeLanguage]
hash = "sha1-8b276eaf378d485c769fb3d5dcc06dfc25b0c01b" hash = "sha1-8b276eaf378d485c769fb3d5dcc06dfc25b0c01b"
@ -238,6 +238,14 @@ other = "бұл FFmpeg емес"
hash = "sha1-9a4148d42186b6b32cf83bef726e23022c53283f" hash = "sha1-9a4148d42186b6b32cf83bef726e23022c53283f"
other = "FFmpeg нұсқасын анықтау мүмкін болмады" other = "FFmpeg нұсқасын анықтау мүмкін болмады"
[errorFFplay]
hash = "sha1-988122112ac6002094e25518cfb5f0d606217298"
other = "бұл FFplay емес"
[errorFFplayVersion]
hash = "sha1-cd60928d20d93210e103dd464306ab138bf1b184"
other = "FFplay нұсқасын анықтау мүмкін болмады"
[errorFFprobe] [errorFFprobe]
hash = "sha1-86d1b0b4c4ccd6a4f71e758fc67ce11aff4ba9b8" hash = "sha1-86d1b0b4c4ccd6a4f71e758fc67ce11aff4ba9b8"
other = "бұл FFprobe емес" other = "бұл FFprobe емес"
@ -330,6 +338,10 @@ other = "Опцияны қосу"
hash = "sha1-fafc50f1db0f720fe83a96cd70a9e1ad824e96b6" hash = "sha1-fafc50f1db0f720fe83a96cd70a9e1ad824e96b6"
other = "FFmpeg жол:" other = "FFmpeg жол:"
[pathToFfplay]
hash = "sha1-5389830dd75a63aa8a5e41e8f07c5fadd8385398"
other = "FFplay жол:"
[pathToFfprobe] [pathToFfprobe]
hash = "sha1-b872edc9633a2e81ef678dc46fe46a7e91732024" hash = "sha1-b872edc9633a2e81ef678dc46fe46a7e91732024"
other = "FFprobe жол:" other = "FFprobe жол:"

View File

@ -4,7 +4,7 @@ aboutText = "Простенький интерфейс для консольно
buttonDownloadFFmpeg = "Скачать автоматически FFmpeg" buttonDownloadFFmpeg = "Скачать автоматически FFmpeg"
buttonForSelectedDirTitle = "Сохранить в папку:" buttonForSelectedDirTitle = "Сохранить в папку:"
cancel = "Отмена" cancel = "Отмена"
changeFFPath = "FFmpeg и FFprobe" changeFFPath = "FFmpeg, FFprobe и FFplay"
changeLanguage = "Поменять язык" changeLanguage = "Поменять язык"
checkboxOverwriteOutputFilesTitle = "Разрешить перезаписать файл" checkboxOverwriteOutputFilesTitle = "Разрешить перезаписать файл"
choose = "выбрать" choose = "выбрать"
@ -58,6 +58,8 @@ errorDatabaseTimeout = "Не смогли открыть файл конфигу
errorDragAndDrop1File = "Можно перетащить только 1 файл" errorDragAndDrop1File = "Можно перетащить только 1 файл"
errorFFmpeg = "это не FFmpeg" errorFFmpeg = "это не FFmpeg"
errorFFmpegVersion = "Не смогли определить версию FFmpeg" errorFFmpegVersion = "Не смогли определить версию FFmpeg"
errorFFplay = "это не FFplay"
errorFFplayVersion = "Не смогли определить версию FFplay"
errorFFprobe = "это не FFprobe" errorFFprobe = "это не FFprobe"
errorFFprobeVersion = "Не смогли определить версию FFprobe" errorFFprobeVersion = "Не смогли определить версию FFprobe"
errorIsFolder = "Можно перетаскивать только файл" errorIsFolder = "Можно перетаскивать только файл"
@ -81,6 +83,7 @@ licenseLinkOther = "Лицензии от других продуктов, ко
or = "или" or = "или"
parameterCheckbox = "Включить параметр" parameterCheckbox = "Включить параметр"
pathToFfmpeg = "Путь к FFmpeg:" pathToFfmpeg = "Путь к FFmpeg:"
pathToFfplay = "Путь к FFplay:"
pathToFfprobe = "Путь к FFprobe:" pathToFfprobe = "Путь к FFprobe:"
preset_fast = "fast (медленней чем faster, но будет файл и меньше весить)" preset_fast = "fast (медленней чем faster, но будет файл и меньше весить)"
preset_faster = "faster (медленней чем veryfast, но будет файл и меньше весить)" preset_faster = "faster (медленней чем veryfast, но будет файл и меньше весить)"

13
main.go
View File

@ -36,15 +36,16 @@ func init() {
return return
} }
ffPathUtilities = &kernel.FFPathUtilities{FFmpeg: "", FFprobe: ""} ffPathUtilities = &kernel.FFPathUtilities{FFmpeg: "", FFprobe: "", FFplay: ""}
convertorService := kernel.NewService(ffPathUtilities) convertorService := kernel.NewService(ffPathUtilities)
ffplayService := kernel.NewFFplay(ffPathUtilities)
queue := kernel.NewQueueList() queue := kernel.NewQueueList()
application = kernel.NewApp( application = kernel.NewApp(
appMetadata, appMetadata,
localizerService, localizerService,
queue, queue,
kernel.NewQueueLayoutObject(queue, localizerService), kernel.NewQueueLayoutObject(queue, localizerService, ffplayService),
convertorService, convertorService,
) )
} }
@ -93,6 +94,14 @@ func main() {
} }
ffPathUtilities.FFprobe = pathFFprobe ffPathUtilities.FFprobe = pathFFprobe
pathFFplay, err := convertorRepository.GetPathFfplay()
if err != nil && errors.Is(err, dberror.ErrRecordNotFound) == false {
errorView.PanicError(err)
application.GetWindow().ShowAndRun()
return
}
ffPathUtilities.FFplay = pathFFplay
application.RunConvertor() application.RunConvertor()
defer application.AfterClosing() defer application.AfterClosing()

View File

@ -12,7 +12,7 @@ import (
) )
type ViewContract interface { type ViewContract interface {
About(ffmpegVersion string, ffprobeVersion string) About(ffmpegVersion string, ffprobeVersion string, ffplayVersion string)
Gratitude() Gratitude()
} }
@ -60,7 +60,7 @@ func (v View) Gratitude() {
view.Show() view.Show()
} }
func (v View) About(ffmpegVersion string, ffprobeVersion string) { func (v View) About(ffmpegVersion string, ffprobeVersion string, ffplayVersion string) {
view := v.app.GetAppFyne().NewWindow(v.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{ view := v.app.GetAppFyne().NewWindow(v.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "about", MessageID: "about",
})) }))
@ -134,6 +134,7 @@ func (v View) About(ffmpegVersion string, ffprobeVersion string) {
)), )),
v.getAboutFfmpeg(ffmpegVersion), v.getAboutFfmpeg(ffmpegVersion),
v.getAboutFfprobe(ffprobeVersion), v.getAboutFfprobe(ffprobeVersion),
v.getAboutFfplay(ffplayVersion),
widget.NewCard(v.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{ widget.NewCard(v.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "AlsoUsedProgram", MessageID: "AlsoUsedProgram",
}), "", v.getOther()), }), "", v.getOther()),
@ -207,6 +208,36 @@ func (v View) getAboutFfprobe(version string) *fyne.Container {
) )
} }
func (v View) getAboutFfplay(version string) *fyne.Container {
programmName := canvas.NewText(" FFplay", colornames.Darkgreen)
programmName.TextStyle = fyne.TextStyle{Bold: true}
programmName.TextSize = 20
programmLink := widget.NewHyperlink(v.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "programmLink",
}), &url.URL{
Scheme: "https",
Host: "ffmpeg.org",
Path: "ffplay.html",
})
licenseLink := widget.NewHyperlink(v.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
MessageID: "licenseLink",
}), &url.URL{
Scheme: "https",
Host: "ffmpeg.org",
Path: "legal.html",
})
return container.NewVBox(
programmName,
widget.NewLabel(version),
widget.NewRichTextFromMarkdown("**FFmpeg** is a trademark of **[Fabrice Bellard](http://bellard.org/)**, originator of the **[FFmpeg](https://ffmpeg.org/about.html)** project."),
widget.NewRichTextFromMarkdown("This software uses libraries from the **FFmpeg** project under the **[LGPLv2.1](http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html)**."),
container.NewHBox(programmLink, licenseLink),
)
}
func (v View) getOther() *fyne.Container { func (v View) getOther() *fyne.Container {
return container.NewVBox( return container.NewVBox(
canvas.NewLine(colornames.Darkgreen), canvas.NewLine(colornames.Darkgreen),