diff --git a/restream/core.go b/restream/core.go index e4105ca3..935565a2 100644 --- a/restream/core.go +++ b/restream/core.go @@ -685,10 +685,16 @@ func (r *restream) onBeforeStart(cfg *app.Config) func([]string) ([]string, erro if t, token, hasTask := r.tasks.Load(cfg.ProcessID()); hasTask { t.SetHWDevice(selectedGPU) t.Release(token) + } else { + return []string{}, fmt.Errorf("process with the ID '%s' not found", cfg.ProcessID()) } config := cfg.Clone() + if selectedGPU == -1 && hasPlaceholder(config, r.replace, "hwdevice") { + return []string{}, fmt.Errorf("no hwdevice found, either not available or no resources requested") + } + resolveDynamicPlaceholder(config, r.replace, map[string]string{ "hwdevice": fmt.Sprintf("%d", selectedGPU), }, map[string]string{ @@ -1865,3 +1871,52 @@ func resolveDynamicPlaceholder(config *app.Config, r replace.Replacer, values ma config.Output[i] = output } } + +// hasPlaceholder checks whether the config has the specified placeholder +func hasPlaceholder(config *app.Config, r replace.Replacer, placeholder string) bool { + for _, option := range config.Options { + if r.Has(option, placeholder) { + return true + } + } + + for _, input := range config.Input { + if r.Has(input.ID, placeholder) { + return true + } + + if r.Has(input.Address, placeholder) { + return true + } + + for _, option := range input.Options { + if r.Has(option, placeholder) { + return true + } + } + } + + for _, output := range config.Output { + if r.Has(output.ID, placeholder) { + return true + } + + if r.Has(output.Address, placeholder) { + return true + } + + for _, option := range output.Options { + if r.Has(option, placeholder) { + return true + } + } + + for _, cleanup := range output.Cleanup { + if r.Has(cleanup.Pattern, placeholder) { + return true + } + } + } + + return false +} diff --git a/restream/replace/replace.go b/restream/replace/replace.go index 016978e7..f526183d 100644 --- a/restream/replace/replace.go +++ b/restream/replace/replace.go @@ -24,6 +24,9 @@ type Replacer interface { // A placeholder name may consist on of the letters a-z and ':'. The placeholder may contain // a glob pattern to find the appropriate template. Replace(str, placeholder, value string, vars map[string]string, config *app.Config, section string) string + + // Has returns whether the string contains the placeholder + Has(str, placeholder string) bool } type replace struct { @@ -80,7 +83,7 @@ func (r *replacer) Replace(str, placeholder, value string, vars map[string]strin } } - params := r.parseParametes(matches[3], vars, repl.defaults) + params := r.parseParameters(matches[3], vars, repl.defaults) v = repl.fn(params, config, section) @@ -100,12 +103,31 @@ func (r *replacer) Replace(str, placeholder, value string, vars map[string]strin return str } -// parseParametes parses the parameters of a placeholder. The params string is a comma-separated +func (r *replacer) Has(str, placeholder string) bool { + matches := r.re.FindAllStringSubmatch(str, -1) + if len(matches) == 0 { + return false + } + + for _, match := range matches { + if ok, _ := glob.Match(placeholder, match[1], ':'); ok { + return true + } + + if match[1] == placeholder { + return true + } + } + + return false +} + +// parseParameters parses the parameters of a placeholder. The params string is a comma-separated // string of key=value pairs. The key and values can be escaped with an \. // The provided defaults will be used as basis. Any parsed key/value from the params might overwrite // the default value. Any variables in the values will be replaced by their value from the // vars parameter. -func (r *replacer) parseParametes(params string, vars map[string]string, defaults map[string]string) map[string]string { +func (r *replacer) parseParameters(params string, vars map[string]string, defaults map[string]string) map[string]string { reSpace := regexp.MustCompile(`^\s+`) p := make(map[string]string) diff --git a/restream/replace/replace_test.go b/restream/replace/replace_test.go index 59a42e5e..4f649a81 100644 --- a/restream/replace/replace_test.go +++ b/restream/replace/replace_test.go @@ -172,7 +172,18 @@ func TestParseParams(t *testing.T) { } for _, test := range tests { - params := r.parseParametes(test[0], nil, map[string]string{"foobar": "def"}) + params := r.parseParameters(test[0], nil, map[string]string{"foobar": "def"}) require.Equal(t, test[1], params["foobar"]) } } + +func TestReplaceHas(t *testing.T) { + r := New() + + require.True(t, r.Has("{foobar}", "foobar")) + require.False(t, r.Has("{foobar}", "barfoo")) + require.True(t, r.Has("{foobar^:}", "foobar")) + require.False(t, r.Has("{foobar^:.}", "foobar")) + require.True(t, r.Has("{foobar^:,hello=world}", "foobar")) + require.True(t, r.Has("{foobar:bla}", "foobar:*")) +}