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.
This commit is contained in:
Sybren A. Stüvel 2022-04-09 16:16:19 +02:00
parent 0959179225
commit 38aedfe8cc
4 changed files with 42 additions and 9 deletions

@ -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

@ -1,7 +1,7 @@
//go:build !windows
// SPDX-License-Identifier: GPL-3.0-or-later
package worker
package find_blender
import "errors"

@ -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)
}

@ -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")
}