From 38aedfe8cc48ae230e8d51fe6461ca822b80c612 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sybren=20A=2E=20St=C3=BCvel?= Date: Sat, 9 Apr 2022 16:16:19 +0200 Subject: [PATCH] Worker: make blender-finder find blender.exe and not blender-launcher.exe `blender-launcher.exe` doesn't pipe Blender's stdout/stderr output, so it's not useful for Flamenco. --- internal/worker/command_blender.go | 3 +- .../nonwindows.go} | 2 +- .../windows.go} | 35 +++++++++++++++++-- .../windows_test.go} | 11 +++--- 4 files changed, 42 insertions(+), 9 deletions(-) rename internal/worker/{command_blender_nonwindows.go => find_blender/nonwindows.go} (93%) rename internal/worker/{command_blender_windows.go => find_blender/windows.go} (78%) rename internal/worker/{command_blender_windows_test.go => find_blender/windows_test.go} (67%) diff --git a/internal/worker/command_blender.go b/internal/worker/command_blender.go index bc492be3..ced7e431 100644 --- a/internal/worker/command_blender.go +++ b/internal/worker/command_blender.go @@ -15,6 +15,7 @@ import ( "github.com/google/shlex" "github.com/rs/zerolog" + "git.blender.org/flamenco/internal/worker/find_blender" "git.blender.org/flamenco/pkg/api" ) @@ -117,7 +118,7 @@ func (ce *CommandExecutor) cmdBlenderRenderCommand( // Attempt a platform-specific way to find which Blender executable to // use. If Blender cannot not be found, just use the configured command // and let the OS produce the errors. - path, err := FindBlender() + path, err := find_blender.FindBlender() if err == nil { logger.Info().Str("path", path).Msg("found Blender") parameters.exe = path diff --git a/internal/worker/command_blender_nonwindows.go b/internal/worker/find_blender/nonwindows.go similarity index 93% rename from internal/worker/command_blender_nonwindows.go rename to internal/worker/find_blender/nonwindows.go index 071de15a..90957561 100644 --- a/internal/worker/command_blender_nonwindows.go +++ b/internal/worker/find_blender/nonwindows.go @@ -1,7 +1,7 @@ //go:build !windows // SPDX-License-Identifier: GPL-3.0-or-later -package worker +package find_blender import "errors" diff --git a/internal/worker/command_blender_windows.go b/internal/worker/find_blender/windows.go similarity index 78% rename from internal/worker/command_blender_windows.go rename to internal/worker/find_blender/windows.go index b570ccb9..82aadc9f 100644 --- a/internal/worker/command_blender_windows.go +++ b/internal/worker/find_blender/windows.go @@ -1,16 +1,45 @@ //go:build windows // SPDX-License-Identifier: GPL-3.0-or-later -package worker +package find_blender import ( "fmt" + "os" + "path/filepath" "syscall" "unsafe" ) -// FindBlender returns the path of `blender.exe` associated with ".blend" files. +// FindBlender returns the full path of `blender.exe` associated with ".blend" files. func FindBlender() (string, error) { + exe, err := fileAssociation(".blend") + if err != nil { + return "", err + } + + // Often the association will be with blender-launcher.exe, which is + // unsuitable for use in Flamenco. Use its path to find its `blender.exe`. + dir, file := filepath.Split(exe) + if file != "blender-launcher.exe" { + return exe, nil + } + + blenderPath := filepath.Join(dir, "blender.exe") + _, err = os.Stat(blenderPath) + if err != nil { + if os.IsNotExist(err) { + return "", fmt.Errorf("blender-launcher found at %s but not its blender.exe", exe) + } + return "", fmt.Errorf("investigating %s: %w", blenderPath, err) + } + + return blenderPath, nil +} + +// fileAssociation finds the executable associated with the given extension. +// The extension must be a string like ".blend". +func fileAssociation(extension string) (string, error) { // Load library. libname := "shlwapi.dll" libshlwapi, err := syscall.LoadLibrary(libname) @@ -27,7 +56,7 @@ func FindBlender() (string, error) { } // https://docs.microsoft.com/en-gb/windows/win32/api/shlwapi/nf-shlwapi-assocquerystringw - pszAssoc, err := syscall.UTF16PtrFromString(".blend") + pszAssoc, err := syscall.UTF16PtrFromString(extension) if err != nil { return "", fmt.Errorf("converting string to UTF16: %w", err) } diff --git a/internal/worker/command_blender_windows_test.go b/internal/worker/find_blender/windows_test.go similarity index 67% rename from internal/worker/command_blender_windows_test.go rename to internal/worker/find_blender/windows_test.go index b05e15b3..618cc345 100644 --- a/internal/worker/command_blender_windows_test.go +++ b/internal/worker/find_blender/windows_test.go @@ -1,7 +1,7 @@ //go:build windows // SPDX-License-Identifier: GPL-3.0-or-later -package worker +package find_blender import ( "testing" @@ -13,9 +13,12 @@ import ( // It would be too fragile to always require a file association to be set up with Blender. func TestFindBlender(t *testing.T) { exe, err := FindBlender() - if err == nil { - assert.NotEmpty(t, exe) - } else { + if err != nil { assert.Empty(t, exe) + return } + assert.NotEmpty(t, exe) + assert.NotContains(t, exe, + "blender-launcher", + "FindBlender should find blender.exe, not blender-launcher.exe") }